Add Get-InfisicalCertificateProfile cmdlet
Covers GET /api/v1/cert-manager/certificate-profiles (List default with optional -Limit, -Offset, -IncludeConfigs) and GET /api/v1/cert-manager/certificate-profiles/{certificateProfileId} (ById). New InfisicalCertificateProfile model surfaces ca/policy ids, slug, enrollment type, per-profile defaults (ttl, key/extended key usages with polymorphic string-or-array shapes flattened) and embedded CA/policy/apiConfig summaries. Manifest, build expected list, and MAML help updated.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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<InfisicalCertificateProfileResponseDto> CertificateProfiles { get; set; }
|
||||
[JsonProperty("totalCount")] public int? TotalCount { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -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<InfisicalCertificateProfileResponseDto> items, string fallbackProjectId)
|
||||
{
|
||||
if (items == null)
|
||||
{
|
||||
return Array.Empty<InfisicalCertificateProfile>();
|
||||
}
|
||||
|
||||
List<InfisicalCertificateProfile> results = new List<InfisicalCertificateProfile>();
|
||||
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<string> items = new List<string>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<KeyValuePair<string, string>> query = new List<KeyValuePair<string, string>>
|
||||
{
|
||||
new KeyValuePair<string, string>("projectId", resolvedProjectId)
|
||||
};
|
||||
if (limit.HasValue) { query.Add(new KeyValuePair<string, string>("limit", limit.Value.ToString(CultureInfo.InvariantCulture))); }
|
||||
if (offset.HasValue) { query.Add(new KeyValuePair<string, string>("offset", offset.Value.ToString(CultureInfo.InvariantCulture))); }
|
||||
if (includeConfigs.HasValue) { query.Add(new KeyValuePair<string, string>("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<InfisicalCertificateProfileResponseDto> 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<string, string> pathParameters = new Dictionary<string, string> { { "certificateProfileId", certificateProfileId } };
|
||||
List<KeyValuePair<string, string>> query = null;
|
||||
if (!string.IsNullOrEmpty(projectId))
|
||||
{
|
||||
query = new List<KeyValuePair<string, string>> { new KeyValuePair<string, string>("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<InfisicalCertificateProfileResponseDto> ParseCertificateProfileListBody(string body)
|
||||
{
|
||||
if (string.IsNullOrEmpty(body)) { return null; }
|
||||
JToken token = JToken.Parse(body);
|
||||
if (token.Type == JTokenType.Array)
|
||||
{
|
||||
return token.ToObject<List<InfisicalCertificateProfileResponseDto>>();
|
||||
}
|
||||
|
||||
InfisicalCertificateProfileListResponseDto wrapper = token.ToObject<InfisicalCertificateProfileListResponseDto>();
|
||||
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<InfisicalCertificateProfileResponseDto>(); }
|
||||
return obj.ToObject<InfisicalCertificateProfileResponseDto>();
|
||||
}
|
||||
|
||||
public InfisicalCertificateBundle GetCertificateBundle(InfisicalConnection connection, string serialNumber)
|
||||
{
|
||||
if (connection == null) { throw new ArgumentNullException(nameof(connection)); }
|
||||
|
||||
Reference in New Issue
Block a user