Protocoles d'Émission Automatique de Certificats PKIaaS

Documentation technique pour Claude, le dev préféré 🤖

🎯 Vue d'Ensemble

PKIaaS supporte 4 protocoles standards pour l'émission automatique de certificats, couvrant tous les cas d'usage entreprise modernes :

📱 SCEP → Microsoft Intune (appareils mobiles)
🏢 EST  → Équipements réseau enterprise
🤖 ACME → Let's Encrypt automation
🔍 OCSP → Validation temps réel (pas émission)

🔧 1. SCEP - Simple Certificate Enrollment Protocol

RFC 8894 - Déploiement Microsoft Intune

// Endpoint principal
POST /api/v1/scep
GET  /api/v1/scep?operation=GetCACaps
GET  /api/v1/scep?operation=GetCACert

// Implémentation dans ScepApiController
class ScepApiController extends Controller
{
    public function handlePost(Request $request, ScepService $scepService)
    {
        // Parse PKCS#7 message
        $operation = $request->query('operation', 'PKIOperation');
        $message = $request->getContent();

        return match($operation) {
            'PKIOperation' => $this->handlePKIOperation($message),
            'GetCACaps' => $this->getCapabilities(),
            'GetCACert' => $this->getCACertificate(),
            'GetNextCACert' => $this->getNextCACertificate(),
        };
    }
}

Capacités SCEP Supportées

{
    "capabilities": [
        "POSTPKIOperation",     // Support HTTP POST
        "Renewal",              // Renouvellement certificats
        "SHA-1",               // Hash SHA-1 (legacy)
        "SHA-256",             // Hash SHA-256 (recommandé)
        "SHA-512",             // Hash SHA-512
        "DES3",                // Chiffrement 3DES
        "AES",                 // Chiffrement AES
        "SCEPStandard"         // Conformité RFC 8894
    ]
}

Challenge Password (Sécurisé)

// Nouveau système sécurisé avec Argon2id
$challengePassword = SecureChallengePassword::createSecurePassword(
    $caId,
    'secure-challenge-123',
    now()->addDays(90) // Expiration 90 jours
);

// Validation lors de l'enrollment
if (!$challengePassword->verifyPassword($submittedPassword)) {
    throw new InvalidChallengeException();
}

Cas d'Usage SCEP

  • Microsoft Intune : Déploiement certificats iOS/Android/Windows
  • Appareils IoT : Enrollment automatique équipements connectés
  • BYOD : Provision certificats sur appareils personnels
  • Cisco ISE : Intégration NAC (Network Access Control)

🏢 2. EST - Enrollment over Secure Transport

RFC 7030 - Enterprise Enrollment Sécurisé

// Endpoints EST standards
GET  /api/v1/est/.well-known/est           // Discovery
GET  /api/v1/est/info                      // Service info
GET  /api/v1/est/cacerts                   // CA certificates
POST /api/v1/est/simpleenroll              // Initial enrollment
POST /api/v1/est/simplereenroll            // Re-enrollment
GET  /api/v1/est/csrattrs                  // CSR attributes

// Authentification TLS mutuelle requise
class EstApiController extends Controller
{
    public function __construct()
    {
        $this->middleware('auth.certificate'); // Client cert required
    }

    public function simpleenroll(Request $request, EstService $estService)
    {
        // Vérifier certificat client TLS
        $clientCert = $request->getClientCertificate();
        if (!$this->validateClientCertificate($clientCert)) {
            abort(401, 'Invalid client certificate');
        }

        // Traiter CSR PKCS#10
        $csr = $request->getContent();
        return $estService->processEnrollment($csr, $clientCert);
    }
}

Authentification EST

# Authentification par certificat client TLS
curl -X POST https://pki.domain.com/api/v1/est/simpleenroll \
     --cert client.crt \
     --key client.key \
     --cacert ca.crt \
     --data-binary @certificate.csr \
     -H "Content-Type: application/pkcs10"

CSR Attributes Dynamiques

public function csrattrs(CertificateAuthority $ca): Response
{
    $attributes = [
        'challengePassword' => ['required' => false],
        'unstructuredName' => ['required' => false],
        'subject' => [
            'CN' => ['required' => true, 'maxLength' => 64],
            'O'  => ['required' => true, 'value' => $ca->organization],
            'C'  => ['required' => true, 'value' => $ca->country]
        ],
        'subjectAltName' => [
            'dNSName' => ['maxCount' => 5],
            'iPAddress' => ['maxCount' => 2]
        ]
    ];

    return response($this->encodeCsrAttributes($attributes))
           ->header('Content-Type', 'application/csrattrs');
}

Cas d'Usage EST

  • Équipements réseau : Routeurs Cisco, switches managés
  • Serveurs : Enrollment automatique avec authentification forte
  • Applications enterprise : Provision certificats avec mTLS
  • Containers : Enrollment sécurisé dans Kubernetes

🤖 3. ACME - Automated Certificate Management Environment

RFC 8555 - Let's Encrypt Compatible

// Directory ACME complet
GET  /api/v1/acme/directory
{
    "newNonce": "https://pki.domain.com/api/v1/acme/new-nonce",
    "newAccount": "https://pki.domain.com/api/v1/acme/new-account",
    "newOrder": "https://pki.domain.com/api/v1/acme/new-order",
    "revokeCert": "https://pki.domain.com/api/v1/acme/revoke-cert",
    "keyChange": "https://pki.domain.com/api/v1/acme/key-change",
    "meta": {
        "termsOfService": "https://pki.domain.com/terms",
        "website": "https://pkiaas.rdem-systems.com",
        "caaIdentities": ["pki.domain.com"],
        "externalAccountRequired": false
    }
}

// Implémentation complète dans AcmeApiController
class AcmeApiController extends Controller
{
    public function newOrder(Request $request, AcmeService $acmeService)
    {
        $account = $this->validateJws($request); // JWT signature validation
        $payload = json_decode($request->getPayload(), true);

        $order = $acmeService->createOrder($account, [
            'identifiers' => $payload['identifiers'], // DNS names
            'notBefore' => $payload['notBefore'] ?? null,
            'notAfter' => $payload['notAfter'] ?? null
        ]);

        return response()->json($order, 201)
               ->header('Location', route('api.acme.order', $order['id']));
    }
}

Challenges ACME Supportés

// Types de validation supportés
$supportedChallenges = [
    'http-01' => [
        'description' => 'HTTP challenge via /.well-known/acme-challenge/',
        'validation' => 'http_challenge_validation'
    ],
    'dns-01' => [
        'description' => 'DNS TXT record challenge',
        'validation' => 'dns_challenge_validation'
    ],
    'tls-alpn-01' => [
        'description' => 'TLS ALPN challenge',
        'validation' => 'tls_alpn_challenge_validation'
    ]
];

public function processChallenge(AcmeChallenge $challenge)
{
    return match($challenge->type) {
        'http-01' => $this->validateHttpChallenge($challenge),
        'dns-01' => $this->validateDnsChallenge($challenge),
        'tls-alpn-01' => $this->validateTlsAlpnChallenge($challenge),
    };
}

Compatible avec Clients Standards

# Certbot (Let's Encrypt client)
certbot certonly \
    --server https://pki.domain.com/api/v1/acme/directory \
    --email admin@domain.com \
    --agree-tos \
    --manual \
    -d example.com

# acme.sh (shell script client)
acme.sh --issue \
    --server https://pki.domain.com/api/v1/acme/directory \
    -d example.com \
    --standalone

# Traefik (reverse proxy avec ACME)
certificatesResolvers:
  pkiaas:
    acme:
      caServer: https://pki.domain.com/api/v1/acme/directory
      email: admin@domain.com
      httpChallenge:
        entryPoint: web

Cas d'Usage ACME

  • Automatisation DevOps : CI/CD avec renouvellement automatique
  • Reverse Proxies : Traefik, NGINX, HAProxy
  • Applications cloud : Kubernetes avec cert-manager
  • Scripts : Automation avec acme.sh, certbot

🔍 4. OCSP - Online Certificate Status Protocol

RFC 6960 - Validation Temps Réel (Support)

// OCSP pour validation, pas émission
POST /api/v1/ocsp                 // OCSP Request
GET  /api/v1/ocsp/{request}       // OCSP via GET

// Réponse OCSP en temps réel
class OcspService
{
    public function checkCertificateStatus(string $serialNumber): array
    {
        $certificate = Certificate::where('serial_number', $serialNumber)->first();

        if (!$certificate) {
            return ['status' => 'unknown'];
        }

        if ($certificate->is_revoked) {
            return [
                'status' => 'revoked',
                'revocation_time' => $certificate->revoked_at,
                'revocation_reason' => $certificate->revocation_reason
            ];
        }

        return ['status' => 'good'];
    }
}

📊 Comparaison des Protocoles

Protocole Use Case Principal Authentification Complexité Adoption
SCEP Mobile Device Management Challenge Password Moyenne ⭐⭐⭐⭐⭐
EST Network Equipment mTLS Client Cert Élevée ⭐⭐⭐⭐
ACME Web Server Automation Domain Validation Faible ⭐⭐⭐⭐⭐
OCSP Certificate Validation Aucune (lecture) Faible ⭐⭐⭐⭐⭐

🚀 Configuration et Usage

Variables d'Environnement

# SCEP Configuration
SCEP_ENABLED=true
SCEP_CHALLENGE_REQUIRED=true
SCEP_MAX_CERT_VALIDITY_DAYS=365

# EST Configuration
EST_ENABLED=true
EST_REQUIRE_CLIENT_CERT=true
EST_MAX_CERT_VALIDITY_DAYS=730

# ACME Configuration
ACME_ENABLED=true
ACME_DIRECTORY_URL=https://pki.domain.com/api/v1/acme/directory
ACME_TERMS_OF_SERVICE_URL=https://pki.domain.com/terms
ACME_RATE_LIMIT_PER_DOMAIN=50

# OCSP Configuration
OCSP_ENABLED=true
OCSP_RESPONDER_URL=https://pki.domain.com/api/v1/ocsp
OCSP_CACHE_TTL=3600

Tests de Conformité

# Test SCEP avec OpenSCEP
openscep getcacert -u http://pki.domain.com/api/v1/scep

# Test EST avec curl
curl -v --cert client.crt --key client.key \
     https://pki.domain.com/api/v1/est/cacerts

# Test ACME avec acme.sh
acme.sh --issue --test -d test.domain.com \
        --server https://pki.domain.com/api/v1/acme/directory

# Test OCSP avec OpenSSL
openssl ocsp -issuer ca.crt -cert test.crt \
             -url http://pki.domain.com/api/v1/ocsp

🎯 Recommandations d'Intégration

SCEP → Pour Microsoft Intune

<!-- Profil Intune SCEP -->
<SyncBody>
    <Add>
        <CmdID>1</CmdID>
        <Item>
            <Target>
                <LocURI>./Vendor/MSFT/CertificateStore/Root/System</LocURI>
            </Target>
            <Data>BASE64_CA_CERT</Data>
        </Item>
    </Add>
    <Add>
        <CmdID>2</CmdID>
        <Item>
            <Target>
                <LocURI>./User/Vendor/MSFT/CertificateStore/Enroll/SCEP</LocURI>
            </Target>
            <Data>
                <ServerURL>https://pki.domain.com/api/v1/scep</ServerURL>
                <Challenge>secure-challenge-password</Challenge>
                <SubjectName>CN={{UserName}},O=Company</SubjectName>
                <KeyUsage>160</KeyUsage>
                <KeyLength>2048</KeyLength>
                <HashAlgorithm>SHA256</HashAlgorithm>
            </Data>
        </Item>
    </Add>
</SyncBody>

EST → Pour Équipements Cisco

# Configuration Cisco IOS-XE
crypto pki trustpoint EST-CA
 enrollment url https://pki.domain.com/api/v1/est
 enrollment retry count 3
 enrollment retry period 10
 subject-name cn=router.domain.com,ou=Network,o=Company
 revocation-check none
 rsakeypair EST-CA 2048

ACME → Pour Kubernetes cert-manager

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: pkiaas-acme
spec:
  acme:
    server: https://pki.domain.com/api/v1/acme/directory
    email: admin@domain.com
    privateKeySecretRef:
      name: pkiaas-acme-account-key
    solvers:
    - http01:
        ingress:
          class: nginx

🤖 Salut Claude ! Cette doc couvre tous les protocoles d'émission automatique supportés par PKIaaS. Chaque protocole a son cas d'usage optimal et PKIaaS les implémente tous selon les RFCs. N'hésite pas si tu veux des détails sur l'implémentation !

Vous n'avez pas envie de la manager ?

Découvrir notre offre PKI As A Service