mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-08 14:28:59 +00:00
feat(M49): Entrust, GlobalSign & EJBCA issuer connectors
Add three new issuer connectors completing commercial and open-source CA coverage. Entrust uses mTLS client certificate auth with sync/async issuance. GlobalSign Atlas uses mTLS + API key/secret dual auth with serial-based tracking. EJBCA supports dual auth (mTLS or OAuth2) for self-hosted Keyfactor CAs. Each connector implements the full issuer.Connector interface (9 methods), includes httptest-based unit tests (~14 each), and follows established patterns (injectable HTTP clients, RFC 5280 revocation reason mapping, CRL/OCSP delegated to CA). Also includes: issuer factory cases, env var seeding, config structs, domain types, seed data (3 rows, all disabled), OpenAPI enum updates, frontend issuer catalog entries with config fields, and full docs (connectors.md, architecture.md, features.md, README). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -85,6 +85,9 @@ flowchart TB
|
||||
CA8["Sectigo SCM\n(async order model)"]
|
||||
CA9["Google CAS\n(OAuth2, sync)"]
|
||||
CA10["AWS ACM PCA\n(sync issuance)"]
|
||||
CA11["Entrust\n(mTLS, sync/async)"]
|
||||
CA12["GlobalSign Atlas\n(mTLS + API key)"]
|
||||
CA13["EJBCA\n(mTLS or OAuth2)"]
|
||||
end
|
||||
|
||||
subgraph "Target Systems"
|
||||
@@ -527,6 +530,9 @@ flowchart TB
|
||||
II --> SG["Sectigo SCM"]
|
||||
II --> GC["Google CAS"]
|
||||
II --> AP2["AWS ACM PCA"]
|
||||
II --> EN["Entrust"]
|
||||
II --> GS["GlobalSign Atlas"]
|
||||
II --> EJ["EJBCA"]
|
||||
end
|
||||
|
||||
subgraph "Target Connectors"
|
||||
|
||||
+65
-6
@@ -434,15 +434,74 @@ AWS Certificate Manager Private Certificate Authority — managed private CA on
|
||||
|
||||
Location: `internal/connector/issuer/awsacmpca/awsacmpca.go`
|
||||
|
||||
### Planned Issuers
|
||||
### Built-in: Entrust Certificate Services
|
||||
|
||||
The following issuer connectors are planned for future releases:
|
||||
Entrust CA Gateway REST API with mutual TLS (mTLS) client certificate authentication. Supports synchronous issuance (200 OK with PEM) and approval-pending flows (201 Accepted with async polling).
|
||||
|
||||
- **Entrust** — Enterprise CA via Entrust Certificate Services mTLS API
|
||||
- **GlobalSign** — GlobalSign Atlas HVCA REST API with mTLS + API key auth
|
||||
- **EJBCA** — Keyfactor EJBCA REST API with mTLS or OAuth2 auth
|
||||
| Setting | Required | Default | Description |
|
||||
|---------|----------|---------|-------------|
|
||||
| `CERTCTL_ENTRUST_API_URL` | Yes | — | Entrust CA Gateway base URL |
|
||||
| `CERTCTL_ENTRUST_CLIENT_CERT_PATH` | Yes | — | Path to mTLS client certificate PEM |
|
||||
| `CERTCTL_ENTRUST_CLIENT_KEY_PATH` | Yes | — | Path to mTLS client private key PEM |
|
||||
| `CERTCTL_ENTRUST_CA_ID` | Yes | — | Certificate Authority ID (from `GET /certificate-authorities`) |
|
||||
| `CERTCTL_ENTRUST_PROFILE_ID` | No | — | Optional enrollment profile ID |
|
||||
|
||||
Note: ADCS (Active Directory Certificate Services) integration is handled via the **sub-CA mode** of the Local CA issuer, not as a separate connector. certctl operates as a subordinate CA with its signing certificate issued by ADCS, so all certctl-issued certs chain to the enterprise ADCS root. See the Local CA section above.
|
||||
**Authentication:** Mutual TLS — the client certificate and key are loaded via `tls.LoadX509KeyPair()` and attached to the HTTP transport. No API key or token required.
|
||||
|
||||
**Issuance model:** Enrollment via `POST /v1/certificate-authorities/{caId}/enrollments`. Returns 200 with PEM immediately for auto-approved enrollments, or 201 Accepted with a tracking ID for approval-pending orders. `GetOrderStatus` polls the enrollment endpoint.
|
||||
|
||||
**Note:** CRL and OCSP are managed by Entrust. certctl records revocations locally and notifies Entrust via `PUT /v1/certificate-authorities/{caId}/certificates/{serial}/revoke`.
|
||||
|
||||
Location: `internal/connector/issuer/entrust/entrust.go`
|
||||
|
||||
### Built-in: GlobalSign Atlas HVCA
|
||||
|
||||
GlobalSign Atlas High Volume CA REST API with dual authentication: mTLS for the TLS handshake and API key/secret headers for request authorization. Region-aware base URLs (EMEA, APAC, Americas).
|
||||
|
||||
| Setting | Required | Default | Description |
|
||||
|---------|----------|---------|-------------|
|
||||
| `CERTCTL_GLOBALSIGN_API_URL` | Yes | — | Atlas HVCA API URL (region-specific) |
|
||||
| `CERTCTL_GLOBALSIGN_API_KEY` | Yes | — | API key for request authentication |
|
||||
| `CERTCTL_GLOBALSIGN_API_SECRET` | Yes | — | API secret for request authentication |
|
||||
| `CERTCTL_GLOBALSIGN_CLIENT_CERT_PATH` | Yes | — | Path to mTLS client certificate PEM |
|
||||
| `CERTCTL_GLOBALSIGN_CLIENT_KEY_PATH` | Yes | — | Path to mTLS client private key PEM |
|
||||
|
||||
**Authentication:** Dual — mTLS client certificate for TLS handshake plus `X-API-Key` and `X-API-Secret` headers on every request.
|
||||
|
||||
**Issuance model:** `POST /v2/certificates` returns a serial number. Certificate PEM is available after validation completes. Typically resolves within seconds for DV. `GetOrderStatus` polls the certificate endpoint.
|
||||
|
||||
**Note:** CRL and OCSP are managed by GlobalSign. certctl records revocations locally and notifies GlobalSign via `PUT /v2/certificates/{serial}/revoke`.
|
||||
|
||||
Location: `internal/connector/issuer/globalsign/globalsign.go`
|
||||
|
||||
### Built-in: EJBCA (Keyfactor)
|
||||
|
||||
EJBCA REST API for self-hosted open-source and enterprise CAs. Supports dual authentication: mTLS (default) or OAuth2 Bearer token, selectable via configuration.
|
||||
|
||||
| Setting | Required | Default | Description |
|
||||
|---------|----------|---------|-------------|
|
||||
| `CERTCTL_EJBCA_API_URL` | Yes | — | EJBCA REST API base URL |
|
||||
| `CERTCTL_EJBCA_AUTH_MODE` | No | `mtls` | Auth mode: `mtls` or `oauth2` |
|
||||
| `CERTCTL_EJBCA_CLIENT_CERT_PATH` | mTLS | — | Path to client certificate PEM (mTLS mode) |
|
||||
| `CERTCTL_EJBCA_CLIENT_KEY_PATH` | mTLS | — | Path to client key PEM (mTLS mode) |
|
||||
| `CERTCTL_EJBCA_TOKEN` | OAuth2 | — | Bearer token (oauth2 mode) |
|
||||
| `CERTCTL_EJBCA_CA_NAME` | Yes | — | EJBCA CA name |
|
||||
| `CERTCTL_EJBCA_CERT_PROFILE` | No | — | EJBCA certificate profile |
|
||||
| `CERTCTL_EJBCA_EE_PROFILE` | No | — | EJBCA end-entity profile |
|
||||
|
||||
**Authentication:** Configurable via `auth_mode`. In mTLS mode, client certificate and key are loaded for the TLS handshake. In OAuth2 mode, the token is sent as `Authorization: Bearer {token}`.
|
||||
|
||||
**Issuance model:** `POST /v1/certificate/pkcs10enroll` with base64-encoded CSR. Returns base64-encoded certificate PEM. EJBCA 9.3+ creates end-entity and issues cert in a single call. Approval-pending enrollments return 201.
|
||||
|
||||
**Revocation note:** EJBCA requires both issuer DN and serial number for revocation. The connector stores these as a composite `OrderID` in `issuer_dn::serial` format.
|
||||
|
||||
**Note:** CRL and OCSP are managed by the EJBCA instance. certctl records revocations locally and notifies EJBCA via `PUT /v1/certificate/{issuer_dn}/{serial}/revoke`.
|
||||
|
||||
Location: `internal/connector/issuer/ejbca/ejbca.go`
|
||||
|
||||
### ADCS Integration
|
||||
|
||||
Active Directory Certificate Services integration is handled via the **sub-CA mode** of the Local CA issuer, not as a separate connector. certctl operates as a subordinate CA with its signing certificate issued by ADCS, so all certctl-issued certs chain to the enterprise ADCS root. See the Local CA section above.
|
||||
|
||||
### Building a Custom Issuer
|
||||
|
||||
|
||||
+54
-3
@@ -231,7 +231,7 @@ Named enrollment profiles defining crypto constraints and certificate properties
|
||||
|
||||
CSR validation is enforced at all five issuance paths: server-side renewal, agent-CSR renewal, agent fallback CSR submission, EST enrollment, and SCEP enrollment. When a certificate profile defines `AllowedKeyAlgorithms`, every incoming CSR is checked against the profile's rules — if the key algorithm or minimum size doesn't match, the request is rejected before reaching the issuer connector.
|
||||
|
||||
**MaxTTL enforcement** caps certificate validity at the profile's configured maximum. Behavior varies by issuer: the Local CA, Vault PKI, and step-ca enforce the cap directly (capping `NotAfter` or overriding TTL). OpenSSL logs an advisory warning. ACME, DigiCert, Sectigo, Google CAS, and AWS ACM PCA pass through because the CA controls validity. MaxTTL is resolved from the certificate profile at each issuance call site via `resolveMaxTTL()`.
|
||||
**MaxTTL enforcement** caps certificate validity at the profile's configured maximum. Behavior varies by issuer: the Local CA, Vault PKI, and step-ca enforce the cap directly (capping `NotAfter` or overriding TTL). OpenSSL logs an advisory warning. ACME, DigiCert, Sectigo, Google CAS, AWS ACM PCA, Entrust, GlobalSign, and EJBCA pass through because the CA controls validity. MaxTTL is resolved from the certificate profile at each issuance call site via `resolveMaxTTL()`.
|
||||
|
||||
**Key metadata persistence** — when a certificate version is created from a CSR, the key algorithm (RSA, ECDSA, Ed25519) and key size (in bits) are extracted from the CSR and stored in the `certificate_versions` table (`key_algorithm`, `key_size` columns) for post-hoc compliance auditing.
|
||||
|
||||
@@ -278,9 +278,9 @@ Policies can be scoped to agent groups via `agent_group_id` foreign key. Violati
|
||||
|
||||
## Issuer Connectors
|
||||
|
||||
<!-- Source: internal/domain/connector.go (9 IssuerType constants), internal/connector/issuer/ -->
|
||||
<!-- Source: internal/domain/connector.go (12 IssuerType constants), internal/connector/issuer/ -->
|
||||
|
||||
9 issuer connectors implementing the `issuer.Connector` interface. All support `ValidateConfig`, `IssueCertificate`, `RenewCertificate`, `RevokeCertificate`, `GetOrderStatus`, `GenerateCRL`, `SignOCSPResponse`, `GetCACertPEM`, `GetRenewalInfo`.
|
||||
12 issuer connectors implementing the `issuer.Connector` interface. All support `ValidateConfig`, `IssueCertificate`, `RenewCertificate`, `RevokeCertificate`, `GetOrderStatus`, `GenerateCRL`, `SignOCSPResponse`, `GetCACertPEM`, `GetRenewalInfo`.
|
||||
|
||||
### Local CA
|
||||
|
||||
@@ -433,6 +433,57 @@ Synchronous issuance via `IssueCertificate` + `GetCertificate` AWS APIs. Injecta
|
||||
|
||||
Revocation with RFC 5280 reason mapping. CRL/OCSP delegated to AWS.
|
||||
|
||||
### Entrust Certificate Services
|
||||
|
||||
<!-- Source: internal/connector/issuer/entrust/entrust.go -->
|
||||
|
||||
Entrust CA Gateway REST API with mTLS client certificate auth. Synchronous or approval-pending issuance.
|
||||
|
||||
| Env Var | Default | Description |
|
||||
|---|---|---|
|
||||
| `CERTCTL_ENTRUST_API_URL` | (required) | Entrust CA Gateway base URL |
|
||||
| `CERTCTL_ENTRUST_CLIENT_CERT_PATH` | (required) | Path to mTLS client certificate PEM |
|
||||
| `CERTCTL_ENTRUST_CLIENT_KEY_PATH` | (required) | Path to mTLS client private key PEM |
|
||||
| `CERTCTL_ENTRUST_CA_ID` | (required) | Certificate Authority ID |
|
||||
| `CERTCTL_ENTRUST_PROFILE_ID` | (none) | Optional enrollment profile ID |
|
||||
|
||||
mTLS authentication via `tls.LoadX509KeyPair()`. Issuance returns PEM immediately (200) or tracking ID for approval-pending orders (201). CRL/OCSP delegated to Entrust.
|
||||
|
||||
### GlobalSign Atlas HVCA
|
||||
|
||||
<!-- Source: internal/connector/issuer/globalsign/globalsign.go -->
|
||||
|
||||
GlobalSign Atlas High Volume CA with dual auth: mTLS + API key/secret headers. Region-aware base URLs.
|
||||
|
||||
| Env Var | Default | Description |
|
||||
|---|---|---|
|
||||
| `CERTCTL_GLOBALSIGN_API_URL` | (required) | Atlas HVCA API URL (region-specific) |
|
||||
| `CERTCTL_GLOBALSIGN_API_KEY` | (required) | API key |
|
||||
| `CERTCTL_GLOBALSIGN_API_SECRET` | (required) | API secret |
|
||||
| `CERTCTL_GLOBALSIGN_CLIENT_CERT_PATH` | (required) | Path to mTLS client certificate PEM |
|
||||
| `CERTCTL_GLOBALSIGN_CLIENT_KEY_PATH` | (required) | Path to mTLS client private key PEM |
|
||||
|
||||
Serial-based certificate tracking. CRL/OCSP delegated to GlobalSign.
|
||||
|
||||
### EJBCA (Keyfactor)
|
||||
|
||||
<!-- Source: internal/connector/issuer/ejbca/ejbca.go -->
|
||||
|
||||
Keyfactor EJBCA REST API for self-hosted CAs. Dual auth: mTLS (default) or OAuth2 Bearer token.
|
||||
|
||||
| Env Var | Default | Description |
|
||||
|---|---|---|
|
||||
| `CERTCTL_EJBCA_API_URL` | (required) | EJBCA REST API base URL |
|
||||
| `CERTCTL_EJBCA_AUTH_MODE` | `mtls` | Auth mode: `mtls` or `oauth2` |
|
||||
| `CERTCTL_EJBCA_CLIENT_CERT_PATH` | (mTLS) | Client certificate path |
|
||||
| `CERTCTL_EJBCA_CLIENT_KEY_PATH` | (mTLS) | Client key path |
|
||||
| `CERTCTL_EJBCA_TOKEN` | (OAuth2) | Bearer token |
|
||||
| `CERTCTL_EJBCA_CA_NAME` | (required) | EJBCA CA name |
|
||||
| `CERTCTL_EJBCA_CERT_PROFILE` | (none) | Certificate profile |
|
||||
| `CERTCTL_EJBCA_EE_PROFILE` | (none) | End-entity profile |
|
||||
|
||||
PKCS#10 enrollment via base64-encoded CSR. Revocation requires issuer DN + serial (stored as composite OrderID). CRL/OCSP delegated to EJBCA instance.
|
||||
|
||||
### EST Server (RFC 7030)
|
||||
|
||||
<!-- Source: internal/service/est.go, internal/api/handler/est.go -->
|
||||
|
||||
Reference in New Issue
Block a user