Fix chain-install hang and pick the certificate store by process elevation
Request-InfisicalCertificate -InstallChain could hang indefinitely. Adding a root certificate to CurrentUser\Root makes Windows raise a modal trust confirmation dialog, and X509Store.Add blocks until it is answered. When that dialog was hidden or the session non-interactive (scheduled task, MECM task sequence) the cmdlet appeared to stop right after installing the intermediate, with no indication why. A warning is now emitted before the blocking call. -StoreLocation now defaults to the process elevation when the caller does not supply it: LocalMachine when elevated, CurrentUser otherwise. This is what most callers want, and it sidesteps the trust prompt entirely because writing LocalMachine\Root already required elevation. Applied to both Request-InfisicalCertificate and Install-InfisicalCertificate; the resolved value is reported on the verbose stream and an explicit -StoreLocation wins. Chain routing is unchanged and already correct: self-signed certificates go to the Root store and everything else to CertificateAuthority, within whichever location was resolved. When the resolved location is LocalMachine and -KeyStorageFlags was not supplied, the private key is written to the machine key store. Without this the key lands in the calling user's profile while the certificate sits in LocalMachine\My, which is the usual cause of an installed certificate that reports no usable private key to a service. Reuse detection now searches the store location the install will write to rather than always searching CurrentUser, so -AllowRenewal and the existing certificate short-circuit behave consistently with where certificates land. Elevation detection moved to InfisicalCmdletBase (evaluated through the engine, since the module targets netstandard2.0 and carries no System.Security.Principal.Windows reference) and is shared with Write-InfisicalScepMdmProfileToWmi, which loses its private copy. README gains the fuller worked example, a genericized output transcript, and a "Where certificates get installed" section; cmdlet help updated to match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
@{
|
||||
RootModule = 'PSInfisicalAPI.psm1'
|
||||
ModuleVersion = '2026.07.30.2239'
|
||||
ModuleVersion = '2026.07.30.2259'
|
||||
GUID = 'b8a2f3d4-7c51-4d2f-9e6a-1f0c8b3d4e51'
|
||||
Author = 'Grace Solutions'
|
||||
CompanyName = 'Grace Solutions'
|
||||
@@ -74,7 +74,7 @@
|
||||
LicenseUri = 'https://www.gnu.org/licenses/agpl-3.0.html'
|
||||
ProjectUri = 'https://prod.git.gracesolution.info/gsadmin/PSInfisicalAPI'
|
||||
ReleaseNotes = 'See CHANGELOG.md in the project repository for release history.'
|
||||
CommitHash = 'f62b3e90b1b1'
|
||||
CommitHash = 'f56fd15b3864'
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -1285,6 +1285,8 @@ $GetInfisicalCertificatePolicyResult = Get-InfisicalCertificatePolicy @GetInfisi
|
||||
<maml:para>-CertificateAuthorityId only works against a CA that permits direct issuance (Get-InfisicalCertificateAuthority reports this as EnableDirectIssuance). The cmdlet resolves the issuer and validates this before generating a keypair, naming the subscriber, CA, or profile it will use on the verbose stream and in the -WhatIf target. Profile issuance is the only path that ignores that flag, so -CertificateProfileId works against a CA whose EnableDirectIssuance is False. Note that enableDirectIssuance appears in no Infisical create or update schema, so it cannot be changed through the API or UI after the CA exists.</maml:para>
|
||||
<maml:para>There is no -CertificateTemplateId parameter because Infisical's REST API exposes no template-based issuance route; when the API asks for 'a certificate template or subscriber', supply -CertificateProfileId or -PkiSubscriberSlug, or use a CA that allows direct issuance.</maml:para>
|
||||
<maml:para>-CommonName takes the bare value ('web01.contoso.com'), not an RDN; a leading 'CN=' is stripped because the CSR builder adds the prefix itself. -DnsName accepts the mixed output of Get-InfisicalSANList: IP literals in that list are emitted as iPAddress SAN entries rather than dNSName entries.</maml:para>
|
||||
<maml:para>When -StoreLocation is not supplied it is chosen from the process elevation: an elevated session installs to LocalMachine, otherwise CurrentUser. The choice is reported on the verbose stream. Chain members are routed by type regardless of location - self-signed certificates to the Root store, others to CertificateAuthority. When the resolved location is LocalMachine and -KeyStorageFlags was not supplied, the private key is placed in the machine key store so the installed certificate has a usable key outside the calling user's profile.</maml:para>
|
||||
<maml:para>Installing a root into CurrentUser\Root makes Windows display a modal trust confirmation dialog, and the call blocks until it is answered; in a non-interactive session this looks like a hang. The cmdlet emits a warning before blocking. Run elevated or pass -StoreLocation LocalMachine to install machine-wide without a prompt.</maml:para>
|
||||
</maml:alert>
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
|
||||
@@ -1285,6 +1285,8 @@ $GetInfisicalCertificatePolicyResult = Get-InfisicalCertificatePolicy @GetInfisi
|
||||
<maml:para>-CertificateAuthorityId only works against a CA that permits direct issuance (Get-InfisicalCertificateAuthority reports this as EnableDirectIssuance). The cmdlet resolves the issuer and validates this before generating a keypair, naming the subscriber, CA, or profile it will use on the verbose stream and in the -WhatIf target. Profile issuance is the only path that ignores that flag, so -CertificateProfileId works against a CA whose EnableDirectIssuance is False. Note that enableDirectIssuance appears in no Infisical create or update schema, so it cannot be changed through the API or UI after the CA exists.</maml:para>
|
||||
<maml:para>There is no -CertificateTemplateId parameter because Infisical's REST API exposes no template-based issuance route; when the API asks for 'a certificate template or subscriber', supply -CertificateProfileId or -PkiSubscriberSlug, or use a CA that allows direct issuance.</maml:para>
|
||||
<maml:para>-CommonName takes the bare value ('web01.contoso.com'), not an RDN; a leading 'CN=' is stripped because the CSR builder adds the prefix itself. -DnsName accepts the mixed output of Get-InfisicalSANList: IP literals in that list are emitted as iPAddress SAN entries rather than dNSName entries.</maml:para>
|
||||
<maml:para>When -StoreLocation is not supplied it is chosen from the process elevation: an elevated session installs to LocalMachine, otherwise CurrentUser. The choice is reported on the verbose stream. Chain members are routed by type regardless of location - self-signed certificates to the Root store, others to CertificateAuthority. When the resolved location is LocalMachine and -KeyStorageFlags was not supplied, the private key is placed in the machine key store so the installed certificate has a usable key outside the calling user's profile.</maml:para>
|
||||
<maml:para>Installing a root into CurrentUser\Root makes Windows display a modal trust confirmation dialog, and the call blocks until it is answered; in a non-interactive session this looks like a hang. The cmdlet emits a warning before blocking. Run elevated or pass -StoreLocation LocalMachine to install machine-wide without a prompt.</maml:para>
|
||||
</maml:alert>
|
||||
</maml:alertSet>
|
||||
<command:examples>
|
||||
|
||||
Reference in New Issue
Block a user