Importing or Connecting an External CA¶
CA Import (One-Time Migration)¶
If you have an existing CA and want the operator to manage it going forward, you can import the CA data into the operator's PVC.
Prerequisites¶
- An existing Puppet/OpenVox CA with
ca_crt.pem,ca_key.pem, andca_crl.pem - The operator installed in the cluster
Steps¶
-
Create the
CertificateAuthorityresource as usual (withoutspec.external): -
Wait for the PVC to be created, then copy your CA data into it:
# Find the PVC kubectl get pvc -l openvox.voxpupuli.org/certificate-authority=production-ca # Create a temporary pod to copy data kubectl run ca-import --image=busybox --restart=Never \ --overrides='{ "spec": { "containers": [{ "name": "ca-import", "image": "busybox", "command": ["sleep", "3600"], "volumeMounts": [{ "name": "ca-data", "mountPath": "/ca" }] }], "volumes": [{ "name": "ca-data", "persistentVolumeClaim": { "claimName": "production-ca-data" } }] } }' # Copy CA files kubectl cp ca_crt.pem ca-import:/ca/ca_crt.pem kubectl cp ca_key.pem ca-import:/ca/ca_key.pem kubectl cp ca_crl.pem ca-import:/ca/ca_crl.pem # Clean up kubectl delete pod ca-import -
The CA setup Job will detect existing data and skip regeneration. The operator will create the corresponding Secrets and transition to
Ready.
External CA (Ongoing Delegation)¶
If you have a Puppet/OpenVox CA running outside the cluster and want to keep using it, configure spec.external on the CertificateAuthority resource. The operator will delegate CSR signing and CRL fetching to the external CA URL.
Prerequisites¶
- A running Puppet/OpenVox CA accessible from the cluster (e.g.
https://puppet-ca.example.com:8140) - The CA's public certificate (
ca_crt.pem) - (Optional) A client certificate and key for mTLS authentication
Using an existing Puppet CA
On a traditional Puppet CA server, the CA certificate is typically located at /etc/puppetlabs/puppet/ssl/certs/ca.pem. You can copy it with:
Steps¶
-
Create Secrets with the CA certificate and optional client credentials:
-
Create the
CertificateAuthorityresource withspec.external:apiVersion: openvox.voxpupuli.org/v1alpha1 kind: CertificateAuthority metadata: name: external-ca spec: allowSubjectAltNames: true allowAuthorizationExtensions: true enableInfraCRL: true crlRefreshInterval: 5m external: url: https://puppet-ca.example.com:8140 caSecretRef: external-ca-cert tlsSecretRef: external-ca-tls -
The operator will:
- Skip PVC creation and CA setup Job
- Validate the referenced Secrets
- Set the CA phase to
External - Periodically fetch the CRL from the external CA
-
Route CSR signing requests to the external CA
-
Verify the CA transitions to
Externalphase:
External CA Fields¶
| Field | Required | Description |
|---|---|---|
url |
Yes | Base URL of the external CA (e.g. https://puppet-ca.example.com:8140) |
caSecretRef |
No | Secret name containing ca_crt.pem for TLS verification |
tlsSecretRef |
No | Secret name containing tls.crt and tls.key for mTLS client auth |
insecureSkipVerify |
No | Skip TLS verification (not recommended for production) |
Notes¶
spec.externaland customspec.storageare mutually exclusive. External CAs do not need local storage.- The
Certificatecontroller accepts bothReadyandExternalphases as "CA is available", so existingCertificateresources work without changes. - The operator does not manage the external CA's lifecycle (upgrades, backups, etc.). You are responsible for maintaining it.
- CRL refresh still works with external CAs -- the operator fetches the CRL via the Puppet CA HTTP API and stores it in a local Secret.
For the full field reference, see ExternalCASpec.
Using Another openvox-stack as External CA¶
In a multi-cluster or multi-namespace setup you can run one openvox-stack as the primary CA and point secondary stacks at it using spec.external. This avoids duplicate CA key material and keeps a single source of truth for certificate signing.
Steps¶
-
In the primary stack's namespace, export the CA certificate from its Secret:
-
Create the CA certificate Secret in the secondary namespace:
-
Determine the primary CA's Service URL. If the primary stack runs in the same cluster, use the internal ClusterIP Service:
# Format: https://<ca-name>-internal.<namespace>.svc:8140 # Example: https://production-ca-internal.primary.svc:8140If the primary stack runs in a different cluster, expose it via LoadBalancer, Ingress, or VPN and use that URL instead.
-
Create the secondary
CertificateAuthorityresource:apiVersion: openvox.voxpupuli.org/v1alpha1 kind: CertificateAuthority metadata: name: secondary-ca namespace: secondary spec: allowSubjectAltNames: true allowAuthorizationExtensions: true enableInfraCRL: true crlRefreshInterval: 5m external: url: https://production-ca-internal.primary.svc:8140 caSecretRef: primary-ca-cert -
The secondary stack will now delegate all CSR signing and CRL fetching to the primary CA.