CAPIF Certificate Generation Architecture
Summary
This document describes the changes made to the certificate generation and management architecture in CAPIF, implemented in the OCF182-certs-generation branch. The main objective is to allow a single Vault server to serve multiple CAPIF instances efficiently and securely.
Main Changes
Previous Architecture
In the previous implementation, Vault was responsible for:
- Generating the root CA and intermediate CA
- Generating service certificates
- Storing and distributing certificates
Problems:
- Vault generated service certificates (less secure)
- Difficult scalability for multiple CAPIF instances
- Strong coupling between Vault and each CAPIF instance
New Architecture
In the new implementation:
┌──────────────────────────────────────────────────────────────┐
│ VAULT │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ 1. Generates Root CA │ │
│ │ 2. Generates Intermediate CA │ │
│ │ 3. Configures signing role │ │
│ │ 4. Stores CA bundle in secret/ca │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
│ Functions: │
│ ✓ SIGNS certificates (receives CSR) │
│ ✓ STORES signed certificates │
└──────────────────────────────────────────────────────────────┘
▲
│
┌────────────────────┼────────────────────┐
│ │ │
▼ ▼ ▼
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ CAPIF #1 │ │ CAPIF #2 │ │ CAPIF #N │
│ CCF_ID: A │ │ CCF_ID: B │ │ CCF_ID: C │
└──────────────┘ └──────────────┘ └──────────────┘
Benefits:
- ✅ Enhanced security: each service generates its own private key
- ✅ Scalability: one Vault serves multiple CAPIF instances
- ✅ Isolation: certificates organized by CCF_ID
- ✅ PKI best practices: separation between generation and signing
Modified Components
1. Vault (services/vault/vault_prepare_certs.sh)
Main changes:
- No longer generates service certificates, only PKI infrastructure
- Generates only root CA and intermediate CA
- Configures PKI signing endpoint at
/v1/pki_int/sign/my-ca - Stores CA bundle in
secret/ca(KV v2) - Configures
my-casigning role with flexible policies that allow signing any CSR
2. NGINX (services/nginx/nginx_prepare.sh)
New primary certificate generation component:
Implemented flow:
- Fetches CA certificate from Vault (
secret/ca) - Generates its own private key (
server.key) if it doesn't exist - Creates a CSR (Certificate Signing Request) with CAPIF hostname
- Sends CSR to Vault for signing
- Receives signed certificate (
server.crt) - Extracts public key from certificate (
server_pub.pem) - Obtains unique CCF_ID from Helper
- Stores all certificates in Vault under
secret/capif/${CCF_ID}/nginx
Important note: This script includes retries with timeout to handle ordered service startups.
3. Register (services/register/register_prepare.sh)
Similar pattern to NGINX:
- Generates its own private key (
register_key.key) - Creates CSR with complete organization information
- Obtains CA from Vault
- Requests certificate signing from Vault via PKI endpoint
- Saves signed certificate locally
4. Helper Service (services/helper/helper_service/app.py)
Modifications at application startup:
- Creates a dedicated
certs/directory with restrictive permissions - Generates key pair and CSR for superadmin certificate using pyOpenSSL
- Saves private key locally with 600 permissions
- Requests certificate signing from Vault
- Downloads and stores signed superadmin certificate
- Downloads and saves CA root from Vault
Security improvements: permission validation and robust error handling.
5. API Services (Invoker, Provider, Security)
Modified prepare_*.sh scripts:
New consumption pattern (no longer generate certificates):
- Query Helper to obtain CAPIF instance's CCF_ID
- Retrieve server's public key from Vault using path
secret/capif/${CCF_ID}/nginx - Save public key to local location
- Implement robust retries to wait for NGINX to generate and store certificates
Affected files:
prepare_invoker.shprepare_provider.shprepare_security.sh
Certificate Organization in Vault
KV (Key-Value v2) Structure
Root level:
secret/ca: Stores intermediate CA certificate (accessible by all CAPIF instances)
Per-CAPIF level:
secret/capif/<CCF_ID>/nginx/: Contains certificates for each CAPIF instanceserver_crt: Server certificateserver_key: Server private keyserver_pub: Extracted public keyca: Copy of CA bundle
Note: In the future, sub-levels for register/ and helper/ will be added under each CCF_ID.
PKI Endpoints
Root PKI Engine (pki/):
root/generate/internal: Generates root CAconfig/urls: Configures issuance and CRL URLsroot/sign-intermediate: Signs intermediate CA
Intermediate PKI Engine (pki_int/):
intermediate/generate/internal: Generates intermediate CA CSRintermediate/set-signed: Installs signed intermediate certificateroles/my-ca: Defines signing role with its policiessign/my-ca: Endpoint used by services to sign their CSRs
Deployment Flow
1. Vault Initialization
Execute once per Vault cluster:
- In Docker: run
vault_prepare_certs.shscript - In Kubernetes: apply ConfigMap and Job from
helm/vault-job/vault-job.yaml
Expected result:
- ✅ Root CA generated
- ✅ Intermediate CA generated and signed
- ✅
my-carole configured - ✅ CA bundle stored in
secret/ca
2. CAPIF Instance Deployment
Each CAPIF instance (identified by unique CCF_ID):
- Helper starts → Generates unique CCF_ID
-
NGINX starts:
-
Generates
server.keyandserver.csr - Requests signing from Vault
- Receives
server.crt - Stores in
secret/capif/${CCF_ID}/nginx -
Register starts:
-
Generates registration certificate
- Requests signing from Vault
-
API Services start:
-
Retrieve certificates from Vault using CCF_ID
- Use public key for validation
Advantages of New Architecture
Security
- Private keys never transit: each service generates its private key locally
- Principle of least privilege: Vault only has CA role, doesn't manage service keys
- Isolation per CAPIF: certificates separated by CCF_ID
Scalability
- One Vault, multiple CAPIF: total decoupling
- Namespace per instance:
secret/capif/${CCF_ID}/ - No collisions: unique CCF_ID guarantees separation
Operations
- Simplified rotation: each CAPIF can regenerate its certificates independently
- Improved auditing: can track which CAPIF requested which certificate
- Independent deployment: a CAPIF can restart without affecting others
Helm/Kubernetes Compatibility
The helm/vault-job/vault-job.yaml file has been significantly simplified:
Main changes:
- ❌ No longer generates certificates for specific services
- ✅ Only executes basic PKI setup (Root CA, Intermediate CA, signing role)
- ✅ Lighter: 144 lines removed
- ✅ ConfigMap contains a self-contained script that enables PKI engines, generates CAs and configures signing role
- ✅ Job runs only once when deploying Vault namespace
Docker Compose Configuration
Changes in services/docker-compose-capif.yml:
NGINX:
- No longer mounts external certificate volumes
- Certificates are generated dynamically in
/etc/nginx/certsat startup - New environment variables:
VAULT_HOSTNAME,VAULT_PORT,VAULT_ACCESS_TOKEN,CAPIF_HOSTNAME
Helper:
- Manages its own certificate directory internally
certs/directory is automatically created byapp.pyat startup- No longer requires external volumes for certificates
Migration from Previous Architecture
Migration steps:
- Backup existing certificates: Export current certificates from Vault (optional, for history)
- Deploy new Vault: Execute updated
vault_prepare_certs.shscript - Clean old certificates: Remove certificate directories in NGINX and Register services
- Redeploy CAPIF services: Execute
run.shso services automatically generate their new certificates
Important considerations:
- ⚠️ Downtime: There will be a service interruption during migration
- ⚠️ New CCF_ID: Each instance will get a new unique CCF_ID
- ⚠️ Regenerated certificates: All service certificates will be new
- ✅ No API changes: CAPIF's public interface remains the same
- ✅ Compatibility: Existing clients will continue working after obtaining new CA
Testing
Recommended verifications:
- Verify CA in Vault: Query
secret/data/cawith curl to confirm CA bundle is available - Start CAPIF: Execute startup script and observe logs from each service
- Verify NGINX certificate: Use
openssl x509inside container to inspect generated certificate - Verify storage in Vault: Obtain CCF_ID from Helper and query path
secret/capif/${CCF_ID}/nginxin Vault - Run test suite: Run
run_capif_tests.shto validate complete functionality
Troubleshooting
Error: "Unable to retrieve CA certificate from Vault"
Cause: Vault has not been properly initialized with PKI infrastructure
Solution: Execute Vault preparation script (vault_prepare_certs.sh) inside container
Error: "Failed to sign server certificate"
Cause: my-ca signing role is not configured or Vault token doesn't have sufficient permissions
Solution: Verify role exists and token has write permissions on pki_int/sign/my-ca
Error: "Unable to retrieve CCF_ID from Helper"
Cause: Helper service hasn't completed initialization yet
Solution: Wait 30-60 seconds. Service scripts implement automatic retries with incremental delays
References
Modified Files (Branch OCF182-certs-generation)
services/vault/vault_prepare_certs.sh- PKI Setupservices/nginx/nginx_prepare.sh- NGINX certs generationservices/register/register_prepare.sh- Register certs generationservices/helper/helper_service/app.py- Superadmin cert generationservices/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh- Cert consumptionservices/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh- Cert consumptionservices/TS29222_CAPIF_Security_API/prepare_security.sh- Cert consumptionhelm/vault-job/vault-job.yaml- Kubernetes Jobservices/docker-compose-capif.yml- Docker Configuration
Related Documentation
Document Version: 1.0
Date: February 2026
Branch: OCF182-certs-generation
Author: CAPIF Team