Add a cert-manager environment seeding script
Stands up a complete Certificate Manager environment from one declarative configuration block, taking only a base URI, client id, and client secret. Standalone: the module consumes the result but is not needed to produce it, since InfisicalConnection deliberately does not expose its access token. Seeds an RSA hierarchy carrying server and client authentication for SCCM/MECM, and an ECDSA P-384 hierarchy carrying server, client, and code signing. Objects are cross-referenced by name in the configuration and resolved to ids at run time, so adding a policy or profile means adding an entry rather than editing code. Creating a subordinate CA needed more than one call. Infisical only self-signs on creation for a root, and only when given an expiry; a subordinate is created with status pending-certificate and generateIntermediateCaCertificate is never invoked by the create path. The script performs the sequence itself: create, GET the CSR, sign it with the parent, then import the certificate and chain back onto the subordinate. Idempotent by lookup on each natural key, so a re-run reports what exists and creates only what is missing, and -WhatIf shows the whole plan without contacting anything beyond authentication. Also corrects a documentation error this research surfaced. The README claimed a newly created CA defaults to direct issuance enabled, on the strength of the database column default. The creation service passes enableDirectIssuance:false explicitly, so every CA created through the API or UI has it disabled and nothing can enable it afterwards - which makes certificate profiles the only workable issuance path, not merely the recommended one. Validated by parsing the script, exercising the policy payload builders against the shapes Infisical's zod schemas accept, confirming every enum literal matches a defined Infisical value, checking that all name cross-references resolve, and running -WhatIf to the point of authentication. Not yet exercised against a live Infisical instance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+9
-1
@@ -10,7 +10,7 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
|
||||
|
||||
- Build produced from commit 67cf0abac2dd.
|
||||
|
||||
## Unreleased (carried forward)
|
||||
## Unreleased (carried forward)
|
||||
|
||||
## 2026.07.30.2344
|
||||
|
||||
@@ -30,6 +30,14 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) loos
|
||||
|
||||
## Unreleased (carried forward)
|
||||
|
||||
### Added (tooling)
|
||||
|
||||
- `Scripts/Initialize-InfisicalCertManagerEnvironment.ps1` seeds a Certificate Manager project, CA hierarchy, certificate policies, and API enrollment profiles from one declarative configuration block, taking only a base URI, client id, and client secret. Idempotent and `-WhatIf`-aware. Seeds an RSA hierarchy for SCCM/MECM server and client authentication, and an ECDSA P-384 hierarchy for server/client authentication and code signing.
|
||||
|
||||
### Fixed (documentation)
|
||||
|
||||
- Corrected the claim that a newly created certificate authority has direct issuance enabled. The creation service passes `enableDirectIssuance: false` explicitly, so **every** CA created through the API or UI has it disabled regardless of the database default, and nothing can enable it afterwards. Certificate profiles remain the only path that ignores the flag.
|
||||
|
||||
### Fixed (certificate reuse)
|
||||
|
||||
- **Switching certificate profiles reused the old certificate.** The reuse check matched on common name alone, so requesting from a client-authentication profile on a host already holding a server-authentication certificate for the same name returned the existing certificate — with the wrong extended key usages. The reuse search is now scoped by `-CertificateProfileId` or `-CertificateAuthorityId`.
|
||||
|
||||
@@ -343,7 +343,7 @@ When the resolved location is `LocalMachine` and `-KeyStorageFlags` was not supp
|
||||
| Parameter | Common name | Use when |
|
||||
| -------------------------- | ------------------------------------ | ------------------------------------------------------------------------ |
|
||||
| `-CertificateProfileId` | **Per request**, constrained by policy | Fleet enrollment — many machines, each with its own CN. Works on any CA. |
|
||||
| `-CertificateAuthorityId` | **Per request**, unconstrained | Fleet enrollment where no policy is wanted. Needs direct issuance on the CA. |
|
||||
| `-CertificateAuthorityId` | **Per request**, unconstrained | Rarely usable — needs direct issuance, which cannot be enabled (see below). |
|
||||
| `-PkiSubscriberSlug` | **Fixed** by the subscriber record | One named identity — a specific service or host, provisioned in advance. |
|
||||
|
||||
**A PKI subscriber is a per-identity object, not a fleet template.** `signSubscriberCert` rejects any CSR whose CN differs from the subscriber's:
|
||||
@@ -413,7 +413,15 @@ t.renameColumn("requireTemplateForIssuance", "enableDirectIssuance");
|
||||
.update({ name: slugifiedName, enableDirectIssuance: !ca.enableDirectIssuance });
|
||||
```
|
||||
|
||||
Any CA created before that migration with "require template for issuance" enabled now reads `EnableDirectIssuance = False` permanently. The options are to **use a profile** (which ignores the flag), or to create a new CA — new CAs default to `true`.
|
||||
Any CA created before that migration with "require template for issuance" enabled now reads `EnableDirectIssuance = False` permanently.
|
||||
|
||||
Creating a new CA does not help either. Although the database column defaults to `true`, the creation service passes `false` explicitly:
|
||||
|
||||
```ts
|
||||
const ca = await certificateAuthorityDAL.create({ projectId, name: resolvedCaName, status, enableDirectIssuance: false }, tx);
|
||||
```
|
||||
|
||||
So **every CA created through the API or UI has direct issuance disabled**, and nothing can turn it on afterwards. Use a certificate profile, which ignores the flag entirely.
|
||||
|
||||
```powershell
|
||||
Get-InfisicalCertificateAuthority -ProjectId ($Project.Id) -Kind Internal |
|
||||
|
||||
Reference in New Issue
Block a user