From 148a09f0d9379c0276aa82b7c2199b2173294a62 Mon Sep 17 00:00:00 2001 From: GraceSolutions Date: Thu, 4 Jun 2026 19:34:50 -0400 Subject: [PATCH] feat(cmdlets): add Get-InfisicalCertificateApplication, Get-InfisicalCertificateApplicationEnrollment, New-InfisicalScepDynamicChallenge Get-InfisicalCertificateApplication exposes List/ById/ByName parameter sets over /api/v1/cert-manager/applications. Get-InfisicalCertificateApplicationEnrollment returns the per-application/profile enrollment block (API/EST/ACME/SCEP) with the computed RA cert thumbprint. New-InfisicalScepDynamicChallenge wraps POST /scep/applications/{appId}/profiles/{profileId}/challenge and returns the minted challenge as a SecureString (default) or string (-AsPlainText), surfacing plan-restriction and not-configured errors as descriptive ErrorRecords. --- ...etInfisicalCertificateApplicationCmdlet.cs | 61 +++++++++++++++++++ ...lCertificateApplicationEnrollmentCmdlet.cs | 43 +++++++++++++ .../NewInfisicalScepDynamicChallengeCmdlet.cs | 49 +++++++++++++++ 3 files changed, 153 insertions(+) create mode 100644 src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationCmdlet.cs create mode 100644 src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationEnrollmentCmdlet.cs create mode 100644 src/PSInfisicalAPI/Cmdlets/NewInfisicalScepDynamicChallengeCmdlet.cs diff --git a/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationCmdlet.cs new file mode 100644 index 0000000..9636eb7 --- /dev/null +++ b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationCmdlet.cs @@ -0,0 +1,61 @@ +using System; +using System.Management.Automation; +using PSInfisicalAPI.Connections; +using PSInfisicalAPI.Models; +using PSInfisicalAPI.Pki; + +namespace PSInfisicalAPI.Cmdlets +{ + [Cmdlet(VerbsCommon.Get, "InfisicalCertificateApplication", DefaultParameterSetName = "List")] + [OutputType(typeof(InfisicalCertificateApplication))] + public sealed class GetInfisicalCertificateApplicationCmdlet : InfisicalCmdletBase + { + [Parameter(ParameterSetName = "ById", Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)] + [Alias("Id", "ApplicationId")] + public string Id { get; set; } + + [Parameter(ParameterSetName = "ByName", Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)] + [Alias("Name", "ApplicationName")] + public string ApplicationName { get; set; } + + [Parameter] public string ProjectId { get; set; } + + [Parameter(ParameterSetName = "List")] public int? Limit { get; set; } + + [Parameter(ParameterSetName = "List")] public int? Offset { 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)) + { + InfisicalCertificateApplication app = client.GetCertificateApplication(connection, Id, resolvedProjectId); + if (app != null) { WriteObject(app); } + return; + } + + if (string.Equals(ParameterSetName, "ByName", StringComparison.Ordinal)) + { + InfisicalCertificateApplication app = client.GetCertificateApplicationByName(connection, ApplicationName, resolvedProjectId); + if (app != null) { WriteObject(app); } + return; + } + + InfisicalCertificateApplication[] all = client.ListCertificateApplications(connection, resolvedProjectId, Limit, Offset); + foreach (InfisicalCertificateApplication app in all) + { + WriteObject(app); + } + } + catch (Exception exception) + { + ThrowTerminatingForException("GetInfisicalCertificateApplicationCmdlet", "GetCertificateApplication", exception); + } + } + } +} diff --git a/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationEnrollmentCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationEnrollmentCmdlet.cs new file mode 100644 index 0000000..378ce6b --- /dev/null +++ b/src/PSInfisicalAPI/Cmdlets/GetInfisicalCertificateApplicationEnrollmentCmdlet.cs @@ -0,0 +1,43 @@ +using System; +using System.Management.Automation; +using PSInfisicalAPI.Connections; +using PSInfisicalAPI.Models; +using PSInfisicalAPI.Pki; + +namespace PSInfisicalAPI.Cmdlets +{ + [Cmdlet(VerbsCommon.Get, "InfisicalCertificateApplicationEnrollment")] + [OutputType(typeof(InfisicalCertificateApplicationEnrollment))] + public sealed class GetInfisicalCertificateApplicationEnrollmentCmdlet : InfisicalCmdletBase + { + [Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)] + [Alias("Id", "ApplicationId")] + public string ApplicationId { get; set; } + + [Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)] + [Alias("CertificateProfileId")] + public string ProfileId { get; set; } + + [Parameter] public string ProjectId { get; set; } + + protected override void ProcessRecord() + { + try + { + InfisicalConnection connection = InfisicalSessionManager.RequireCurrent(); + InfisicalPkiClient client = new InfisicalPkiClient(HttpClient, Logger); + string resolvedProjectId = ResolveProjectId(connection, ProjectId); + + InfisicalCertificateApplicationEnrollment enrollment = client.GetCertificateApplicationEnrollment(connection, ApplicationId, ProfileId, resolvedProjectId); + if (enrollment != null) + { + WriteObject(enrollment); + } + } + catch (Exception exception) + { + ThrowTerminatingForException("GetInfisicalCertificateApplicationEnrollmentCmdlet", "GetCertificateApplicationEnrollment", exception); + } + } + } +} diff --git a/src/PSInfisicalAPI/Cmdlets/NewInfisicalScepDynamicChallengeCmdlet.cs b/src/PSInfisicalAPI/Cmdlets/NewInfisicalScepDynamicChallengeCmdlet.cs new file mode 100644 index 0000000..8534252 --- /dev/null +++ b/src/PSInfisicalAPI/Cmdlets/NewInfisicalScepDynamicChallengeCmdlet.cs @@ -0,0 +1,49 @@ +using System; +using System.Management.Automation; +using System.Security; +using PSInfisicalAPI.Connections; +using PSInfisicalAPI.Pki; + +namespace PSInfisicalAPI.Cmdlets +{ + [Cmdlet(VerbsCommon.New, "InfisicalScepDynamicChallenge")] + [OutputType(typeof(SecureString))] + [OutputType(typeof(string))] + public sealed class NewInfisicalScepDynamicChallengeCmdlet : InfisicalCmdletBase + { + [Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true)] + [Alias("Id", "ApplicationId")] + public string ApplicationId { get; set; } + + [Parameter(Mandatory = true, Position = 1, ValueFromPipelineByPropertyName = true)] + [Alias("CertificateProfileId")] + public string ProfileId { get; set; } + + [Parameter] public SwitchParameter AsPlainText { get; set; } + + protected override void ProcessRecord() + { + try + { + InfisicalConnection connection = InfisicalSessionManager.RequireCurrent(); + InfisicalPkiClient client = new InfisicalPkiClient(HttpClient, Logger); + + string challenge = client.GenerateScepDynamicChallenge(connection, ApplicationId, ProfileId); + if (AsPlainText.IsPresent) + { + WriteObject(challenge); + return; + } + + SecureString secure = new SecureString(); + foreach (char c in challenge) { secure.AppendChar(c); } + secure.MakeReadOnly(); + WriteObject(secure); + } + catch (Exception exception) + { + ThrowTerminatingForException("NewInfisicalScepDynamicChallengeCmdlet", "GenerateScepDynamicChallenge", exception); + } + } + } +}