Skip to content

PKI and Certificate Authority

The pesitwizard-pki module provides a built-in certificate authority (CA) for generating and managing TLS certificates.

Overview

┌─────────────────────────────────────────────────────────────┐
│                    Root CA (Root CA)                          │
│                  Validity: 10 years                           │
└─────────────────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────┐
│                Intermediate CA (Signing CA)                   │
│                  Validity: 5 years                            │
└─────────────────────────────────────────────────────────────┘

              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
        ┌──────────┐   ┌──────────┐   ┌──────────┐
        │ Server   │   │ Client   │   │ Client   │
        │   TLS    │   │ Partner1 │   │ Partner2 │
        │ 1 year   │   │ 1 year   │   │ 1 year   │
        └──────────┘   └──────────┘   └──────────┘

Configuration

CA Initialization

On first startup, the admin console can initialize the CA:

yaml
pesitwizard:
  pki:
    enabled: true
    ca:
      # Root CA information
      root-dn: "CN=PeSIT Wizard Root CA,O=MyCompany,C=FR"
      root-validity-years: 10
      # Intermediate CA information
      signing-dn: "CN=PeSIT Wizard Signing CA,O=MyCompany,C=FR"
      signing-validity-years: 5
    # Key storage
    keystore:
      path: /app/pki/ca-keystore.p12
      password: ${CA_KEYSTORE_PASSWORD}

Environment Variables

VariableDescription
CA_KEYSTORE_PASSWORDCA keystore password
PESITWIZARD_PKI_ENABLEDEnable/disable PKI

Management via the Console

Certificates Tab

The admin console provides a "Certificates" tab per cluster:

Certificates page

Features:

  • View all issued certificates
  • Generate new certificates
  • Revoke certificates
  • Download in various formats

Server Certificate Generation

  1. Go to Clusters > [Cluster] > Certificates
  2. Click New certificate
  3. Select Type: Server
  4. Fill in:
    • Common Name (CN): pesitwizard.example.com
    • SAN: Alternative DNS names and IPs
    • Validity: Duration in days
  5. Click Generate

Client Certificate Generation (partner)

  1. Go to Clusters > [Cluster] > Partners
  2. Select a partner
  3. Click Generate certificate
  4. Download the PKCS12 with password

REST API

Generate a Server Certificate

bash
POST /api/v1/clusters/{clusterId}/certificates/server
Content-Type: application/json

{
  "commonName": "pesitwizard.example.com",
  "subjectAlternativeNames": [
    "DNS:pesitwizard.example.com",
    "DNS:*.pesitwizard.example.com",
    "IP:192.168.1.100"
  ],
  "validityDays": 365
}

Response:

json
{
  "id": "cert-123",
  "commonName": "pesitwizard.example.com",
  "serialNumber": "1234567890",
  "notBefore": "2024-01-15T00:00:00Z",
  "notAfter": "2025-01-15T00:00:00Z",
  "fingerprint": "SHA256:abc123..."
}

Download a Certificate

bash
# PEM format (certificate only)
GET /api/v1/clusters/{clusterId}/certificates/{certId}/download?format=pem

# PKCS12 format (certificate + private key)
GET /api/v1/clusters/{clusterId}/certificates/{certId}/download?format=p12&password=secret

# JKS format (Java KeyStore)
GET /api/v1/clusters/{clusterId}/certificates/{certId}/download?format=jks&password=secret

Revoke a Certificate

bash
POST /api/v1/clusters/{clusterId}/certificates/{certId}/revoke
Content-Type: application/json

{
  "reason": "KEY_COMPROMISE"
}

Programmatic Usage

CertificateAuthorityService

java
@Autowired
private CertificateAuthorityService caService;

// Generate a server certificate
X509Certificate serverCert = caService.generateServerCertificate(
    "pesitwizard.example.com",
    List.of("DNS:*.example.com", "IP:10.0.0.1"),
    365
);

// Generate a client certificate
X509Certificate clientCert = caService.generateClientCertificate(
    "CN=Partner BANK01,O=Bank,C=FR",
    365
);

// Export as PKCS12
byte[] p12 = caService.exportPkcs12(clientCert, privateKey, "password");

Export Formats

FormatExtensionContentUsage
PEM.pem, .crtCertificate only (Base64)Linux, Nginx
PKCS12.p12, .pfxCertificate + private keyWindows, Java
JKS.jksJava KeyStoreJava applications
DER.der, .cerBinary certificateWindows

Automatic Renewal

The system can automatically renew certificates before expiration:

yaml
pesitwizard:
  pki:
    auto-renewal:
      enabled: true
      # Renew 30 days before expiration
      days-before-expiry: 30
      # Daily check
      check-cron: "0 0 2 * * *"

Notifications

Configure expiration alerts:

yaml
pesitwizard:
  pki:
    notifications:
      # Alert 60, 30, 7 days before expiration
      warning-days: [60, 30, 7]
      # Webhook or email
      webhook-url: https://alerts.example.com/pki

Security

Best Practices

  • Protect the CA keystore with a strong password
  • Regularly back up the CA keystore
  • Use an intermediate CA for signing (not the root)
  • Immediately revoke compromised certificates
  • Enable audit logging to trace operations

PKI Operations Audit

All PKI operations are traced:

json
{
  "timestamp": "2024-01-15T10:30:00Z",
  "action": "CERTIFICATE_GENERATED",
  "actor": "admin@example.com",
  "details": {
    "type": "SERVER",
    "commonName": "pesitwizard.example.com",
    "serialNumber": "1234567890",
    "validityDays": 365
  }
}

TLS Integration

PeSIT Server Configuration

Once the certificate is generated, configure the server:

yaml
pesitwizard:
  server:
    ssl:
      enabled: true
      key-store: /app/certs/server.p12
      key-store-password: ${SSL_KEYSTORE_PASSWORD}
      key-store-type: PKCS12
      # Mutual client authentication (mTLS)
      client-auth: need
      trust-store: /app/certs/truststore.p12
      trust-store-password: ${SSL_TRUSTSTORE_PASSWORD}

Distribution to Partners

  1. Export the root CA certificate (without private key)
  2. Send it to partners so they can add it to their truststore
  3. Generate one client certificate per partner
  4. Send the PKCS12 securely

PeSIT Wizard Enterprise - Console d'administration