From 86968c18cb1584ea8bbc8451728ee6d839780cd3 Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Thu, 4 Jun 2026 22:05:36 -0400 Subject: [PATCH] fix!(pki): deserialize certificate-policy subject as array (matches API shape) Get-InfisicalCertificatePolicy was throwing JsonSerializationException on every list/get call: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'PSInfisicalAPI.Pki.InfisicalCertificatePolicySubjectDto' because the type requires a JSON object ... Path 'certificatePolicies[0].subject', line 1, position 207. The API returns `subject` as an array of {type, allowed} entries (one per DN component: CN, O, OU, C, ...), in the same shape as `sans`. The DTO modeled it as a single object, so deserialization failed before any data ever reached the caller. CHANGES - InfisicalCertificatePolicy.Subject is now InfisicalCertificatePolicySubject[] (was a single InfisicalCertificatePolicySubject). - DTO field switched from typed InfisicalCertificatePolicySubjectDto to JToken SubjectRaw so we tolerate both array (current API) and object (defensive fallback) shapes -- same pattern as SansRaw. - Mapper gains MapSubjects(JToken) / MapSubjectObject(JToken) mirroring MapSans / MapSanObject. BREAKING - The Subject property type changed from a single object to an array. Existing consumers writing `$policy.Subject.Allowed` must update to `$policy.Subject[0].Allowed` or iterate `$policy.Subject`. In practice no caller was reachable because the cmdlet threw before returning. TESTS - 216/216 tests passing. --- .../Models/InfisicalCertificatePolicy.cs | 2 +- .../Pki/InfisicalCertificatePolicyDtos.cs | 2 +- .../Pki/InfisicalCertificatePolicyMapper.cs | 28 +++++++++++++++++-- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/PSInfisicalAPI/Models/InfisicalCertificatePolicy.cs b/src/PSInfisicalAPI/Models/InfisicalCertificatePolicy.cs index 5708648..a8181a0 100644 --- a/src/PSInfisicalAPI/Models/InfisicalCertificatePolicy.cs +++ b/src/PSInfisicalAPI/Models/InfisicalCertificatePolicy.cs @@ -8,7 +8,7 @@ namespace PSInfisicalAPI.Models public string ProjectId { get; set; } public string Name { get; set; } public string Description { get; set; } - public InfisicalCertificatePolicySubject Subject { get; set; } + public InfisicalCertificatePolicySubject[] Subject { get; set; } public InfisicalCertificatePolicySan[] Sans { get; set; } public InfisicalCertificatePolicyUsages KeyUsages { get; set; } public InfisicalCertificatePolicyUsages ExtendedKeyUsages { get; set; } diff --git a/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyDtos.cs b/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyDtos.cs index 485ea5a..3da73d5 100644 --- a/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyDtos.cs +++ b/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyDtos.cs @@ -10,7 +10,7 @@ namespace PSInfisicalAPI.Pki [JsonProperty("projectId")] public string ProjectId { get; set; } [JsonProperty("name")] public string Name { get; set; } [JsonProperty("description")] public string Description { get; set; } - [JsonProperty("subject")] public InfisicalCertificatePolicySubjectDto Subject { get; set; } + [JsonProperty("subject")] public JToken SubjectRaw { get; set; } [JsonProperty("sans")] public JToken SansRaw { get; set; } [JsonProperty("keyUsages")] public InfisicalCertificatePolicyUsagesDto KeyUsages { get; set; } [JsonProperty("extendedKeyUsages")] public InfisicalCertificatePolicyUsagesDto ExtendedKeyUsages { get; set; } diff --git a/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyMapper.cs b/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyMapper.cs index 69d3f74..8ba015a 100644 --- a/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyMapper.cs +++ b/src/PSInfisicalAPI/Pki/InfisicalCertificatePolicyMapper.cs @@ -21,7 +21,7 @@ namespace PSInfisicalAPI.Pki ProjectId = !string.IsNullOrEmpty(dto.ProjectId) ? dto.ProjectId : fallbackProjectId, Name = dto.Name, Description = dto.Description, - Subject = MapSubject(dto.Subject), + Subject = MapSubjects(dto.SubjectRaw), Sans = MapSans(dto.SansRaw), KeyUsages = MapUsages(dto.KeyUsages), ExtendedKeyUsages = MapUsages(dto.ExtendedKeyUsages), @@ -52,8 +52,32 @@ namespace PSInfisicalAPI.Pki return results.ToArray(); } - private static InfisicalCertificatePolicySubject MapSubject(InfisicalCertificatePolicySubjectDto dto) + private static InfisicalCertificatePolicySubject[] MapSubjects(JToken token) { + if (token == null || token.Type == JTokenType.Null) { return null; } + + List results = new List(); + if (token.Type == JTokenType.Array) + { + foreach (JToken child in (JArray)token) + { + InfisicalCertificatePolicySubject mapped = MapSubjectObject(child); + if (mapped != null) { results.Add(mapped); } + } + } + else if (token.Type == JTokenType.Object) + { + InfisicalCertificatePolicySubject mapped = MapSubjectObject(token); + if (mapped != null) { results.Add(mapped); } + } + + return results.Count > 0 ? results.ToArray() : null; + } + + private static InfisicalCertificatePolicySubject MapSubjectObject(JToken token) + { + if (token == null || token.Type != JTokenType.Object) { return null; } + InfisicalCertificatePolicySubjectDto dto = token.ToObject(); if (dto == null) { return null; } return new InfisicalCertificatePolicySubject {