PKI URL Management Architecture

This document describes the comprehensive URL management system for PKI services in PKIaaS, including dynamic URL generation, configuration optimization, and standards compliance.

Overview

PKIaaS implements a centralized URL management system that automatically generates all PKI service URLs from a single base configuration, ensuring consistency, maintainability, and standards compliance across all certificate-related protocols.

Architecture Principles

Single Source of Truth

All PKI URLs are generated from one configuration parameter:

PKI_PUBLIC_URL=https://pki.your-domain.com

This eliminates configuration redundancy and ensures consistency across all services.

Dynamic Generation

URLs are generated dynamically based on context: - CA-specific URLs for CRL distribution points - Protocol-specific URLs for OCSP, SCEP, EST, ACME - Resource-specific URLs for certificates, orders, authorizations

Standards Compliance

All generated URLs follow RFC specifications: - RFC 5280: Certificate extensions with proper distribution points - RFC 6960: OCSP responder URLs - RFC 8894: SCEP service endpoints - RFC 7030: EST service discovery - RFC 8555: ACME directory structure

URL Generation System

Core Helper Class

The PkiUrlHelper class provides centralized URL generation:

class PkiUrlHelper
{
    // Base URL management
    public static function getBaseUrl(): string

    // Protocol-specific URLs
    public static function getCrlUrl(CertificateAuthority $ca): string
    public static function getOcspUrl(): string
    public static function getScepUrl(): string
    public static function getEstUrl(string $operation = ''): string
    public static function getAcmeDirectoryUrl(): string

    // Dynamic resource URLs
    public static function getAcmeOrderUrl(string $orderId): string
    public static function getAcmeChallengeUrl(string $challengeId): string

    // Service discovery
    public static function getServiceUrls(): array
}

URL Patterns

Certificate Lifecycle URLs

Service Pattern Example Context
CRL per CA {base}/api/v1/crl/{ca_id} https://pki.domain.com/api/v1/crl/123 CA-specific revocation lists
OCSP {base}/api/v1/ocsp https://pki.domain.com/api/v1/ocsp Certificate validation
AIA {base}/api/v1/ca/{ca_id}/certificate https://pki.domain.com/api/v1/ca/123/certificate CA certificate access

Enrollment Protocol URLs

Protocol Pattern Example Purpose
SCEP {base}/api/v1/scep https://pki.domain.com/api/v1/scep Device enrollment
EST Base {base}/api/v1/est https://pki.domain.com/api/v1/est Enterprise enrollment
EST Operation {base}/api/v1/est/{op} https://pki.domain.com/api/v1/est/cacerts Specific EST operations

ACME Protocol URLs

Endpoint Pattern Example RFC 8555
Directory {base}/api/v1/acme/directory https://pki.domain.com/api/v1/acme/directory ✅ Required
New Nonce {base}/api/v1/acme/new-nonce https://pki.domain.com/api/v1/acme/new-nonce ✅ Required
New Account {base}/api/v1/acme/new-account https://pki.domain.com/api/v1/acme/new-account ✅ Required
New Order {base}/api/v1/acme/new-order https://pki.domain.com/api/v1/acme/new-order ✅ Required
Authorization {base}/api/v1/acme/authz/{id} https://pki.domain.com/api/v1/acme/authz/auth-123 Dynamic
Challenge {base}/api/v1/acme/chall/{id} https://pki.domain.com/api/v1/acme/chall/chall-456 Dynamic
Finalize {base}/api/v1/acme/finalize/{id} https://pki.domain.com/api/v1/acme/finalize/order-789 Dynamic

Certificate Extensions Integration

CRL Distribution Points

Automatically generated per CA:

CRL Distribution Points:
  - URI: https://pki.domain.com/api/v1/crl/123

Authority Information Access

Generated with proper CA hierarchy:

Authority Information Access:
  - OCSP: https://pki.domain.com/api/v1/ocsp
  - CA Issuers: https://pki.domain.com/api/v1/ca/456/certificate

Implementation in CryptoService

private function buildCertificateExtensions(array $config, $ca = null): array
{
    // CRL Distribution Points (generated dynamically from CA)
    if ($ca) {
        $crlUrls = PkiUrlHelper::getCrlDistributionPoints($ca);
        $extensions['id-ce-cRLDistributionPoints'] = [
            // Proper ASN.1 structure with dynamic URLs
        ];
    }

    // Authority Information Access (AIA) - generated dynamically
    if ($ca) {
        $aiaData = PkiUrlHelper::getAuthorityInfoAccess($ca);
        $extensions['id-pe-authorityInfoAccess'] = [
            // Proper AIA structure with OCSP and CA Issuer URLs
        ];
    }
}

ACME Directory Implementation

RFC 8555 Compliant Directory

The ACME directory is generated with all required endpoints:

{
  "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/api/v1/acme/terms-of-service",
    "website": "https://pki.domain.com",
    "caaIdentities": ["pki.domain.com"],
    "externalAccountRequired": false
  }
}

Dynamic Resource URLs

For ACME protocol operations that require resource-specific URLs:

// Order management
$orderUrl = PkiUrlHelper::getAcmeOrderUrl($orderId);
// -> https://pki.domain.com/api/v1/acme/order/12345

// Challenge handling
$challengeUrl = PkiUrlHelper::getAcmeChallengeUrl($challengeId);
// -> https://pki.domain.com/api/v1/acme/chall/http-01-67890

// Certificate retrieval
$certUrl = PkiUrlHelper::getAcmeCertificateUrl($orderId);
// -> https://pki.domain.com/api/v1/acme/cert/12345

Configuration Management

Simplified Configuration

Before (Redundant)

PKI_PUBLIC_URL=https://pki.domain.com
CRL_DISTRIBUTION_BASE_URL=https://pki.domain.com/api/v1/crl  # Redundant
PKI_OCSP_RESPONDER_URL=https://pki.domain.com/api/v1/ocsp   # Redundant

After (Optimized)

PKI_PUBLIC_URL=https://pki.domain.com
# All other URLs generated automatically

Fallback Strategy

public static function getBaseUrl(): string
{
    $baseUrl = config('pki.public_base_url');

    if (!$baseUrl) {
        $baseUrl = config('app.url');  // Fallback to APP_URL
    }

    return rtrim($baseUrl, '/');
}

Service Discovery

Comprehensive Service URLs

The system provides complete service discovery:

$serviceUrls = PkiUrlHelper::getServiceUrls();
/*
[
    'base_url' => 'https://pki.domain.com',
    'ocsp' => 'https://pki.domain.com/api/v1/ocsp',
    'scep' => 'https://pki.domain.com/api/v1/scep',
    'est' => 'https://pki.domain.com/api/v1/est',
    'acme' => 'https://pki.domain.com/api/v1/acme/directory',
    'acme_directory' => [/* Full ACME directory structure */],
    'api' => 'https://pki.domain.com/api/v1'
]
*/

Testing and Validation

Comprehensive Testing Commands

Test All PKI URLs

php artisan pki:test-urls

Output:

=== Base Service URLs ===
base_url: https://pki.domain.com
ocsp: https://pki.domain.com/api/v1/ocsp
scep: https://pki.domain.com/api/v1/scep
est: https://pki.domain.com/api/v1/est
acme: https://pki.domain.com/api/v1/acme/directory

=== URLs for CA: Root CA (ID: 1) ===
CRL URL: https://pki.domain.com/api/v1/crl/1
Authority Info Access:
  - OCSP: https://pki.domain.com/api/v1/ocsp

Test ACME Directory

php artisan acme:test-directory --test-connectivity

Output:

=== ACME Directory Structure ===
✓ 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

=== RFC 8555 Compliance ===
✓ RFC 8555 Compliance: PASSED
All required ACME directory endpoints are present.

Security Considerations

HTTPS Enforcement

private static function normalizeUrl(string $url): string
{
    // Ensure HTTPS in production
    if (app()->environment('production') && !str_starts_with($url, 'https://')) {
        $url = str_replace('http://', 'https://', $url);
    }

    return rtrim($url, '/');
}

URL Validation

All generated URLs are validated for: - Proper URI format - HTTPS enforcement in production - Consistent base URL usage - Path normalization

Benefits

Operational Benefits

  1. Single Configuration Point: Only PKI_PUBLIC_URL needs to be configured
  2. Consistency: All URLs generated from the same base, eliminating conflicts
  3. Maintainability: Domain changes require only one configuration update
  4. Standards Compliance: All URLs follow RFC specifications automatically

Development Benefits

  1. Centralized Management: All URL logic in one helper class
  2. Type Safety: Strong typing for all URL generation methods
  3. Testing: Comprehensive test coverage for all URL patterns
  4. Documentation: Self-documenting URL structures

Deployment Benefits

  1. Environment Flexibility: Easy transition between environments
  2. Load Balancer Ready: URLs work correctly behind load balancers
  3. CDN Compatible: Proper URL structures for CDN integration
  4. Multi-Instance: Supports multi-instance Docker deployments

Integration Examples

Certificate Generation

// Generate certificate with proper extensions
$ca = CertificateAuthority::find(1);
$config = [
    'subject' => ['CN' => 'example.com'],
    'ca' => $ca  // URLs generated automatically
];

$extensions = $this->buildCertificateExtensions($config, $ca);
// CRL Distribution Points and AIA automatically populated

ACME Client Integration

// ACME client discovers all endpoints
$directory = PkiUrlHelper::getAcmeDirectory();
$client = new AcmeClient($directory['newAccount'], $directory['newOrder']);

Certificate Validation

// Certificate includes proper validation URLs
$ocspUrl = PkiUrlHelper::getOcspUrl();
$crlUrl = PkiUrlHelper::getCrlUrl($certificate->certificateAuthority);
// Client can validate certificate using generated URLs

This comprehensive URL management system ensures PKIaaS provides consistent, maintainable, and standards-compliant URLs for all PKI operations while minimizing configuration complexity and operational overhead.

Vous n'avez pas envie de la manager ?

Découvrir notre offre PKI As A Service