diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5bfbdb..3c0b34b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
## Unreleased
- Infisical API error responses are now parsed to surface the server-side `message`, `error`, and `reqId` fields. The 4xx/5xx exception message includes the human-readable explanation (e.g. "The project is of type secret-manager") instead of an opaque `Infisical API returned 400 (Bad Request)`. The `InfisicalApiException` gains `ApiErrorMessage` and `ApiRequestId` properties; `InfisicalErrorDetails` carries the same fields so PowerShell error records and logger output expose them.
+- `Get-InfisicalCertificateProfile` added with `List` (default) and `ById` parameter sets. List binds to `GET /api/v1/cert-manager/certificate-profiles` (optional `-Limit`, `-Offset`, `-IncludeConfigs`); ById binds to `GET /api/v1/cert-manager/certificate-profiles/{certificateProfileId}`. New `InfisicalCertificateProfile` model surfaces ca/policy ids, slug, enrollment type, per-profile defaults (ttl, key/extended key usages), and the embedded CA/policy/apiConfig summaries.
## 2026.06.04.1920
diff --git a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
index 8540047..15a12f8 100644
--- a/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
+++ b/Module/PSInfisicalAPI/en-US/PSInfisicalAPI.dll-Help.xml
@@ -1128,6 +1128,48 @@ $GetInfisicalPkiSubscriberResult = Get-InfisicalPkiSubscriber @GetInfisicalPkiSu
+
+
+ Get-InfisicalCertificateProfile
+ Lists or retrieves Infisical certificate profiles in a project.
+ Get
+ InfisicalCertificateProfile
+
+
+ Default (List parameter set) returns every certificate profile configured on the project via /api/v1/cert-manager/certificate-profiles, with optional -Limit, -Offset, and -IncludeConfigs. When -ProfileId is supplied (ById parameter set) the cmdlet returns one profile by its id. -ProjectId defaults to the session-pinned project in both modes.
+
+
+ Notes
+
+ Profiles bind a CA and a certificate policy and surface defaults (TtlDays, KeyAlgorithm, KeyUsages, ExtendedKeyUsages). Use the returned profile Id when wiring profile-based issuance against Request-InfisicalCertificate.
+
+
+
+
+ EXAMPLE 1
+ Get-InfisicalCertificateProfile
+ Lists every certificate profile defined on the session-pinned project.
+
+
+ EXAMPLE 2
+ Get-InfisicalCertificateProfile -ProfileId '8257641e-c808-454e-ac92-8dc920be865f'
+ Retrieves a single certificate profile by id from the session-pinned project.
+
+
+ EXAMPLE 3
+ $GetInfisicalCertificateProfileListResult = Get-InfisicalCertificateProfile | Where-Object { $_.Slug -ieq 'codesigning' }
+
+$GetInfisicalCertificateProfileParameters = New-Object -TypeName 'System.Collections.Specialized.OrderedDictionary' -ArgumentList ([System.StringComparer]::OrdinalIgnoreCase)
+$GetInfisicalCertificateProfileParameters.ProfileId = $GetInfisicalCertificateProfileListResult[0].Id
+$GetInfisicalCertificateProfileParameters.ProjectId = $ConnectInfisicalParameters.ProjectId
+$GetInfisicalCertificateProfileParameters.Verbose = $True
+
+$GetInfisicalCertificateProfileResult = Get-InfisicalCertificateProfile @GetInfisicalCertificateProfileParameters
+ Filters profiles whose slug equals 'codesigning' and refetches the canonical record for the first match using a splatted parameter set.
+
+
+
+
Search-InfisicalCertificate
diff --git a/build.ps1 b/build.ps1
index 301e5ac..d5db70a 100644
--- a/build.ps1
+++ b/build.ps1
@@ -131,6 +131,7 @@ function Write-Manifest {
'Remove-InfisicalTag',
'Get-InfisicalCertificateAuthority',
'Get-InfisicalPkiSubscriber',
+ 'Get-InfisicalCertificateProfile',
'Get-InfisicalCertificate',
'Search-InfisicalCertificate',
'Request-InfisicalCertificate',
@@ -202,7 +203,7 @@ if (`$cmds.Count -eq 0) {
throw "No cmdlets were exported by the PSInfisicalAPI module."
}
-`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificate','Search-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate')
+`$expectedCmds = @('Connect-Infisical','Disconnect-Infisical','Get-InfisicalSecret','New-InfisicalSecret','Update-InfisicalSecret','Remove-InfisicalSecret','Copy-InfisicalSecret','ConvertTo-InfisicalSecretDictionary','Export-InfisicalSecrets','Get-InfisicalProject','New-InfisicalProject','Update-InfisicalProject','Remove-InfisicalProject','Get-InfisicalEnvironment','New-InfisicalEnvironment','Update-InfisicalEnvironment','Remove-InfisicalEnvironment','Get-InfisicalFolder','New-InfisicalFolder','Update-InfisicalFolder','Remove-InfisicalFolder','Get-InfisicalTag','New-InfisicalTag','Update-InfisicalTag','Remove-InfisicalTag','Get-InfisicalCertificateAuthority','Get-InfisicalPkiSubscriber','Get-InfisicalCertificateProfile','Get-InfisicalCertificate','Search-InfisicalCertificate','Request-InfisicalCertificate','ConvertTo-InfisicalCertificate','Install-InfisicalCertificate','Uninstall-InfisicalCertificate','Export-InfisicalCertificate')
foreach (`$expected in `$expectedCmds) {
if (-not (Get-Command -Name `$expected -Module PSInfisicalAPI -ErrorAction SilentlyContinue)) {
throw "Cmdlet not found: `$expected"
diff --git a/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateProfileCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateProfileCmdlet.cs
new file mode 100644
index 0000000..7f20258
--- /dev/null
+++ b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateProfileCmdlet.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Management.Automation;
+using PSInfisicalAPI.Connections;
+using PSInfisicalAPI.Models;
+using PSInfisicalAPI.Pki;
+
+namespace PSInfisicalAPI.Cmdlets
+{
+ [Cmdlet(VerbsCommon.Get, "InfisicalCertificateProfile", DefaultParameterSetName = "List")]
+ [OutputType(typeof(InfisicalCertificateProfile))]
+ public sealed class GetInfisicalCertificateProfileCmdlet : InfisicalCmdletBase
+ {
+ [Parameter(ParameterSetName = "ById", Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)]
+ [Alias("Id", "CertificateProfileId")]
+ public string ProfileId { get; set; }
+
+ [Parameter] public string ProjectId { get; set; }
+
+ [Parameter(ParameterSetName = "List")] public int? Limit { get; set; }
+
+ [Parameter(ParameterSetName = "List")] public int? Offset { get; set; }
+
+ [Parameter(ParameterSetName = "List")] public SwitchParameter IncludeConfigs { get; set; }
+
+ protected override void ProcessRecord()
+ {
+ try
+ {
+ InfisicalConnection connection = InfisicalSessionManager.RequireCurrent();
+ InfisicalPkiClient client = new InfisicalPkiClient(HttpClient, Logger);
+ string resolvedProjectId = ResolveProjectId(connection, ProjectId);
+
+ if (string.Equals(ParameterSetName, "ById", StringComparison.Ordinal))
+ {
+ InfisicalCertificateProfile profile = client.GetCertificateProfile(connection, ProfileId, resolvedProjectId);
+ if (profile != null)
+ {
+ WriteObject(profile);
+ }
+
+ return;
+ }
+
+ bool? includeConfigs = MyInvocation.BoundParameters.ContainsKey("IncludeConfigs") ? (bool?)IncludeConfigs.IsPresent : null;
+ InfisicalCertificateProfile[] all = client.ListCertificateProfiles(connection, resolvedProjectId, Limit, Offset, includeConfigs);
+ foreach (InfisicalCertificateProfile profile in all)
+ {
+ WriteObject(profile);
+ }
+ }
+ catch (Exception exception)
+ {
+ ThrowTerminatingForException("GetInfisicalCertificateProfileCmdlet", "GetCertificateProfile", exception);
+ }
+ }
+ }
+}
diff --git a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointNames.cs b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointNames.cs
index a4b70de..779bba9 100644
--- a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointNames.cs
+++ b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointNames.cs
@@ -54,5 +54,8 @@ namespace PSInfisicalAPI.Endpoints
public const string ListPkiSubscribers = "ListPkiSubscribers";
public const string GetPkiSubscriber = "GetPkiSubscriber";
+
+ public const string ListCertificateProfiles = "ListCertificateProfiles";
+ public const string GetCertificateProfile = "GetCertificateProfile";
}
}
diff --git a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs
index 24d9131..e1ae4fe 100644
--- a/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs
+++ b/src/PSInfisicalAPI/Endpoints/InfisicalEndpointRegistry.cs
@@ -642,6 +642,26 @@ namespace PSInfisicalAPI.Endpoints
Template = "/api/v1/pki/subscribers/{subscriberName}",
RequiresAuthorization = true
});
+
+ Add(map, new InfisicalEndpointDefinition
+ {
+ Name = InfisicalEndpointNames.ListCertificateProfiles,
+ Resource = "Pki",
+ Version = "v1",
+ Method = "GET",
+ Template = "/api/v1/cert-manager/certificate-profiles",
+ RequiresAuthorization = true
+ });
+
+ Add(map, new InfisicalEndpointDefinition
+ {
+ Name = InfisicalEndpointNames.GetCertificateProfile,
+ Resource = "Pki",
+ Version = "v1",
+ Method = "GET",
+ Template = "/api/v1/cert-manager/certificate-profiles/{certificateProfileId}",
+ RequiresAuthorization = true
+ });
}
public static InfisicalEndpointDefinition Get(string name)
diff --git a/src/PSInfisicalAPI/Models/InfisicalCertificateProfile.cs b/src/PSInfisicalAPI/Models/InfisicalCertificateProfile.cs
new file mode 100644
index 0000000..0497414
--- /dev/null
+++ b/src/PSInfisicalAPI/Models/InfisicalCertificateProfile.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace PSInfisicalAPI.Models
+{
+ public sealed class InfisicalCertificateProfile
+ {
+ public string Id { get; set; }
+ public string ProjectId { get; set; }
+ public string CaId { get; set; }
+ public string CertificatePolicyId { get; set; }
+ public string Slug { get; set; }
+ public string Description { get; set; }
+ public string EnrollmentType { get; set; }
+ public string IssuerType { get; set; }
+ public string EstConfigId { get; set; }
+ public string ApiConfigId { get; set; }
+ public string AcmeConfigId { get; set; }
+ public string ScepConfigId { get; set; }
+ public DateTimeOffset? CreatedAtUtc { get; set; }
+ public DateTimeOffset? UpdatedAtUtc { get; set; }
+ public InfisicalCertificateProfileDefaults Defaults { get; set; }
+ public InfisicalCertificateAuthoritySummary CertificateAuthority { get; set; }
+ public InfisicalCertificatePolicySummary CertificatePolicy { get; set; }
+ public InfisicalCertificateProfileApiConfig ApiConfig { get; set; }
+ }
+
+ public sealed class InfisicalCertificateProfileDefaults
+ {
+ public int? TtlDays { get; set; }
+ public string KeyAlgorithm { get; set; }
+ public string SignatureAlgorithm { get; set; }
+ public string[] KeyUsages { get; set; }
+ public string[] ExtendedKeyUsages { get; set; }
+ }
+
+ public sealed class InfisicalCertificateAuthoritySummary
+ {
+ public string Id { get; set; }
+ public string Status { get; set; }
+ public string Name { get; set; }
+ public bool? IsExternal { get; set; }
+ public string ExternalType { get; set; }
+ }
+
+ public sealed class InfisicalCertificatePolicySummary
+ {
+ public string Id { get; set; }
+ public string ProjectId { get; set; }
+ public string Name { get; set; }
+ }
+
+ public sealed class InfisicalCertificateProfileApiConfig
+ {
+ public string Id { get; set; }
+ public bool? AutoRenew { get; set; }
+ public int? RenewBeforeDays { get; set; }
+ }
+}
diff --git a/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileDtos.cs b/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileDtos.cs
new file mode 100644
index 0000000..8c9fb32
--- /dev/null
+++ b/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileDtos.cs
@@ -0,0 +1,66 @@
+using System.Collections.Generic;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+
+namespace PSInfisicalAPI.Pki
+{
+ internal sealed class InfisicalCertificateProfileResponseDto
+ {
+ [JsonProperty("id")] public string Id { get; set; }
+ [JsonProperty("projectId")] public string ProjectId { get; set; }
+ [JsonProperty("caId")] public string CaId { get; set; }
+ [JsonProperty("certificatePolicyId")] public string CertificatePolicyId { get; set; }
+ [JsonProperty("slug")] public string Slug { get; set; }
+ [JsonProperty("description")] public string Description { get; set; }
+ [JsonProperty("enrollmentType")] public string EnrollmentType { get; set; }
+ [JsonProperty("issuerType")] public string IssuerType { get; set; }
+ [JsonProperty("estConfigId")] public string EstConfigId { get; set; }
+ [JsonProperty("apiConfigId")] public string ApiConfigId { get; set; }
+ [JsonProperty("acmeConfigId")] public string AcmeConfigId { get; set; }
+ [JsonProperty("scepConfigId")] public string ScepConfigId { get; set; }
+ [JsonProperty("createdAt")] public string CreatedAt { get; set; }
+ [JsonProperty("updatedAt")] public string UpdatedAt { get; set; }
+ [JsonProperty("defaults")] public InfisicalCertificateProfileDefaultsDto Defaults { get; set; }
+ [JsonProperty("certificateAuthority")] public InfisicalCertificateAuthoritySummaryDto CertificateAuthority { get; set; }
+ [JsonProperty("certificatePolicy")] public InfisicalCertificatePolicySummaryDto CertificatePolicy { get; set; }
+ [JsonProperty("apiConfig")] public InfisicalCertificateProfileApiConfigDto ApiConfig { get; set; }
+ }
+
+ internal sealed class InfisicalCertificateProfileDefaultsDto
+ {
+ [JsonProperty("ttlDays")] public int? TtlDays { get; set; }
+ [JsonProperty("keyAlgorithm")] public string KeyAlgorithm { get; set; }
+ [JsonProperty("signatureAlgorithm")] public string SignatureAlgorithm { get; set; }
+ [JsonProperty("keyUsages")] public JToken KeyUsagesRaw { get; set; }
+ [JsonProperty("extendedKeyUsages")] public JToken ExtendedKeyUsagesRaw { get; set; }
+ }
+
+ internal sealed class InfisicalCertificateAuthoritySummaryDto
+ {
+ [JsonProperty("id")] public string Id { get; set; }
+ [JsonProperty("status")] public string Status { get; set; }
+ [JsonProperty("name")] public string Name { get; set; }
+ [JsonProperty("isExternal")] public bool? IsExternal { get; set; }
+ [JsonProperty("externalType")] public string ExternalType { get; set; }
+ }
+
+ internal sealed class InfisicalCertificatePolicySummaryDto
+ {
+ [JsonProperty("id")] public string Id { get; set; }
+ [JsonProperty("projectId")] public string ProjectId { get; set; }
+ [JsonProperty("name")] public string Name { get; set; }
+ }
+
+ internal sealed class InfisicalCertificateProfileApiConfigDto
+ {
+ [JsonProperty("id")] public string Id { get; set; }
+ [JsonProperty("autoRenew")] public bool? AutoRenew { get; set; }
+ [JsonProperty("renewBeforeDays")] public int? RenewBeforeDays { get; set; }
+ }
+
+ internal sealed class InfisicalCertificateProfileListResponseDto
+ {
+ [JsonProperty("certificateProfiles")] public List CertificateProfiles { get; set; }
+ [JsonProperty("totalCount")] public int? TotalCount { get; set; }
+ }
+}
diff --git a/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileMapper.cs b/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileMapper.cs
new file mode 100644
index 0000000..7550ff1
--- /dev/null
+++ b/src/PSInfisicalAPI/Pki/InfisicalCertificateProfileMapper.cs
@@ -0,0 +1,155 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Linq;
+using PSInfisicalAPI.Models;
+
+namespace PSInfisicalAPI.Pki
+{
+ internal static class InfisicalCertificateProfileMapper
+ {
+ public static InfisicalCertificateProfile Map(InfisicalCertificateProfileResponseDto dto, string fallbackProjectId)
+ {
+ if (dto == null)
+ {
+ return null;
+ }
+
+ return new InfisicalCertificateProfile
+ {
+ Id = dto.Id,
+ ProjectId = !string.IsNullOrEmpty(dto.ProjectId) ? dto.ProjectId : fallbackProjectId,
+ CaId = dto.CaId,
+ CertificatePolicyId = dto.CertificatePolicyId,
+ Slug = dto.Slug,
+ Description = dto.Description,
+ EnrollmentType = dto.EnrollmentType,
+ IssuerType = dto.IssuerType,
+ EstConfigId = dto.EstConfigId,
+ ApiConfigId = dto.ApiConfigId,
+ AcmeConfigId = dto.AcmeConfigId,
+ ScepConfigId = dto.ScepConfigId,
+ CreatedAtUtc = ParseTimestamp(dto.CreatedAt),
+ UpdatedAtUtc = ParseTimestamp(dto.UpdatedAt),
+ Defaults = MapDefaults(dto.Defaults),
+ CertificateAuthority = MapCa(dto.CertificateAuthority),
+ CertificatePolicy = MapPolicy(dto.CertificatePolicy),
+ ApiConfig = MapApiConfig(dto.ApiConfig)
+ };
+ }
+
+ public static InfisicalCertificateProfile[] MapMany(IEnumerable items, string fallbackProjectId)
+ {
+ if (items == null)
+ {
+ return Array.Empty();
+ }
+
+ List results = new List();
+ foreach (InfisicalCertificateProfileResponseDto dto in items)
+ {
+ InfisicalCertificateProfile mapped = Map(dto, fallbackProjectId);
+ if (mapped != null)
+ {
+ results.Add(mapped);
+ }
+ }
+
+ return results.ToArray();
+ }
+
+ private static InfisicalCertificateProfileDefaults MapDefaults(InfisicalCertificateProfileDefaultsDto dto)
+ {
+ if (dto == null)
+ {
+ return null;
+ }
+
+ return new InfisicalCertificateProfileDefaults
+ {
+ TtlDays = dto.TtlDays,
+ KeyAlgorithm = dto.KeyAlgorithm,
+ SignatureAlgorithm = dto.SignatureAlgorithm,
+ KeyUsages = FlattenStringOrStringArray(dto.KeyUsagesRaw),
+ ExtendedKeyUsages = FlattenStringOrStringArray(dto.ExtendedKeyUsagesRaw)
+ };
+ }
+
+ private static InfisicalCertificateAuthoritySummary MapCa(InfisicalCertificateAuthoritySummaryDto dto)
+ {
+ if (dto == null)
+ {
+ return null;
+ }
+
+ return new InfisicalCertificateAuthoritySummary
+ {
+ Id = dto.Id,
+ Status = dto.Status,
+ Name = dto.Name,
+ IsExternal = dto.IsExternal,
+ ExternalType = dto.ExternalType
+ };
+ }
+
+ private static InfisicalCertificatePolicySummary MapPolicy(InfisicalCertificatePolicySummaryDto dto)
+ {
+ if (dto == null)
+ {
+ return null;
+ }
+
+ return new InfisicalCertificatePolicySummary
+ {
+ Id = dto.Id,
+ ProjectId = dto.ProjectId,
+ Name = dto.Name
+ };
+ }
+
+ private static InfisicalCertificateProfileApiConfig MapApiConfig(InfisicalCertificateProfileApiConfigDto dto)
+ {
+ if (dto == null)
+ {
+ return null;
+ }
+
+ return new InfisicalCertificateProfileApiConfig
+ {
+ Id = dto.Id,
+ AutoRenew = dto.AutoRenew,
+ RenewBeforeDays = dto.RenewBeforeDays
+ };
+ }
+
+ internal static string[] FlattenStringOrStringArray(JToken token)
+ {
+ if (token == null || token.Type == JTokenType.Null) { return null; }
+ if (token.Type == JTokenType.String) { return new[] { (string)token }; }
+ if (token.Type == JTokenType.Array)
+ {
+ List items = new List();
+ foreach (JToken child in (JArray)token)
+ {
+ if (child != null && child.Type == JTokenType.String) { items.Add((string)child); }
+ }
+
+ return items.ToArray();
+ }
+
+ return null;
+ }
+
+ private static DateTimeOffset? ParseTimestamp(string value)
+ {
+ if (string.IsNullOrEmpty(value)) { return null; }
+ DateTimeOffset parsed;
+ if (DateTimeOffset.TryParse(value, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out parsed))
+ {
+ return parsed;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/src/PSInfisicalAPI/Pki/InfisicalPkiClient.cs b/src/PSInfisicalAPI/Pki/InfisicalPkiClient.cs
index a098cf0..da03488 100644
--- a/src/PSInfisicalAPI/Pki/InfisicalPkiClient.cs
+++ b/src/PSInfisicalAPI/Pki/InfisicalPkiClient.cs
@@ -338,6 +338,95 @@ namespace PSInfisicalAPI.Pki
return wrapper != null ? wrapper.Subscribers : null;
}
+ public InfisicalCertificateProfile[] ListCertificateProfiles(InfisicalConnection connection, string projectId, int? limit, int? offset, bool? includeConfigs)
+ {
+ if (connection == null) { throw new ArgumentNullException(nameof(connection)); }
+ string resolvedProjectId = FirstNonEmpty(projectId, connection.ProjectId);
+ if (string.IsNullOrEmpty(resolvedProjectId)) { throw new InfisicalConfigurationException("ProjectId is required."); }
+
+ List> query = new List>
+ {
+ new KeyValuePair("projectId", resolvedProjectId)
+ };
+ if (limit.HasValue) { query.Add(new KeyValuePair("limit", limit.Value.ToString(CultureInfo.InvariantCulture))); }
+ if (offset.HasValue) { query.Add(new KeyValuePair("offset", offset.Value.ToString(CultureInfo.InvariantCulture))); }
+ if (includeConfigs.HasValue) { query.Add(new KeyValuePair("includeConfigs", includeConfigs.Value ? "true" : "false")); }
+
+ try
+ {
+ _logger.Information(Component, "Attempting to list Infisical certificate profiles. Please Wait...");
+ InfisicalHttpResponse response = _invoker.InvokeWithCandidateFallback(connection, InfisicalEndpointNames.ListCertificateProfiles, "ListCertificateProfiles", null, query, null);
+ string body = response.Body;
+ response.Clear();
+
+ List source = ParseCertificateProfileListBody(body);
+ InfisicalCertificateProfile[] mapped = InfisicalCertificateProfileMapper.MapMany(source, resolvedProjectId);
+ _logger.Information(Component, "Infisical certificate profile list retrieval was successful.");
+ return mapped;
+ }
+ catch (Exception)
+ {
+ _logger.Error(Component, "Infisical certificate profile list retrieval failed.");
+ throw;
+ }
+ }
+
+ public InfisicalCertificateProfile GetCertificateProfile(InfisicalConnection connection, string certificateProfileId, string projectId)
+ {
+ if (connection == null) { throw new ArgumentNullException(nameof(connection)); }
+ if (string.IsNullOrEmpty(certificateProfileId)) { throw new InfisicalConfigurationException("CertificateProfileId is required."); }
+
+ Dictionary pathParameters = new Dictionary { { "certificateProfileId", certificateProfileId } };
+ List> query = null;
+ if (!string.IsNullOrEmpty(projectId))
+ {
+ query = new List> { new KeyValuePair("projectId", projectId) };
+ }
+
+ try
+ {
+ _logger.Information(Component, string.Concat("Attempting to retrieve Infisical certificate profile '", certificateProfileId, "'. Please Wait..."));
+ InfisicalHttpResponse response = _invoker.InvokeWithCandidateFallback(connection, InfisicalEndpointNames.GetCertificateProfile, "GetCertificateProfile", pathParameters, query, null);
+ string body = response.Body;
+ response.Clear();
+
+ InfisicalCertificateProfileResponseDto inner = ParseCertificateProfileSingleBody(body);
+ string fallbackProjectId = !string.IsNullOrEmpty(projectId) ? projectId : connection.ProjectId;
+ InfisicalCertificateProfile mapped = InfisicalCertificateProfileMapper.Map(inner, fallbackProjectId);
+ _logger.Information(Component, "Infisical certificate profile retrieval was successful.");
+ return mapped;
+ }
+ catch (Exception)
+ {
+ _logger.Error(Component, "Infisical certificate profile retrieval failed.");
+ throw;
+ }
+ }
+
+ private List ParseCertificateProfileListBody(string body)
+ {
+ if (string.IsNullOrEmpty(body)) { return null; }
+ JToken token = JToken.Parse(body);
+ if (token.Type == JTokenType.Array)
+ {
+ return token.ToObject>();
+ }
+
+ InfisicalCertificateProfileListResponseDto wrapper = token.ToObject();
+ return wrapper != null ? wrapper.CertificateProfiles : null;
+ }
+
+ private InfisicalCertificateProfileResponseDto ParseCertificateProfileSingleBody(string body)
+ {
+ if (string.IsNullOrEmpty(body)) { return null; }
+ JToken token = JToken.Parse(body);
+ if (token.Type != JTokenType.Object) { return null; }
+ JObject obj = (JObject)token;
+
+ if (obj["certificateProfile"] is JObject inner) { return inner.ToObject(); }
+ return obj.ToObject();
+ }
+
public InfisicalCertificateBundle GetCertificateBundle(InfisicalConnection connection, string serialNumber)
{
if (connection == null) { throw new ArgumentNullException(nameof(connection)); }