Quantum-Safe Cloud -- Part 7

The Quantum-Safe Reference Architecture

#security #post-quantum #architecture #quantumapi #azure #kubernetes #reference

The Problem

Seven articles. Three products. Field-level encryption, quantum-safe secrets, ML-DSA authentication, signed CI/CD pipelines, mTLS between services.

If you’ve followed the series, you’ve applied each piece to a specific problem. What you don’t have yet is the full picture — how all the pieces work together, where each one sits in the architecture, and what the gaps are when you take this to a real multi-service system.

Most developers apply security piece by piece, problem by problem. They add a vault when a secret leaks. They add mTLS when there’s an incident. They think about post-quantum when a compliance audit asks about it. The result is a patchwork — secure in some places, fragile in others, and with gaps where the pieces don’t connect.

A reference architecture solves this. Not a diagram you put in a slide deck and forget — a concrete description of every layer, every component, and every decision, with the ATLAS structure behind it so you can adapt it to your system.

The Solution

The quantum-safe reference architecture has five layers:

  1. Perimeter: what the outside world touches. HTTPS, QuantumID OIDC, TLS 1.3.
  2. Identity: every actor (user, service, pipeline) proves who they are. QuantumID for users and services.
  3. Secrets: no secret lives in configuration or code. QuantumVault for all secret material.
  4. Data: sensitive data encrypted before storage. QuantumAPI EaaS at the repository layer.
  5. Transport: service-to-service communication encrypted and authenticated. mTLS with ML-DSA certificates.

Each layer is independent. A failure or compromise in one layer doesn’t automatically break the others. This is defence in depth — not just as a phrase, but as a design principle.

Execute

The ATLAS document

=== QUANTUM-SAFE REFERENCE ARCHITECTURE ===

[A] ARCHITECT
  System: multi-service .NET platform on AKS (Azure Kubernetes Service).
  Services used as example: users-api, notifications service, API gateway.

  Security requirements:
  - Secrets: zero secrets in code, config, or pipeline YAML
  - Data at rest: PII fields encrypted before database storage
  - Data in transit: TLS 1.3 externally, mTLS internally
  - Authentication: quantum-safe token signing (ML-DSA)
  - Pipeline: signed images, SBOM, secrets from vault at runtime

  Post-quantum requirements:
  - All key material: QRNG-generated, ML-KEM wrapped at rest
  - All token signatures: ML-DSA-65
  - All service certificates: ML-DSA-65, 24-hour validity
  - All data encryption: ML-KEM-768 + AES-256-GCM hybrid

  Out of scope:
  - Key ceremony / root of trust (handled by QuantumAPI platform)
  - Hardware security modules (QuantumAPI manages QRNG hardware)
  - Compliance reporting automation (next series)

[T] TRACE
  External user → API request:
  1. DNS resolves to Azure Front Door (TLS termination, DDoS protection)
  2. Front Door forwards to AKS ingress (nginx)
  3. Ingress routes to API gateway pod
  4. API gateway validates QuantumID token (JWKS from QuantumID)
  5. Gateway routes to users-api pod
  6. users-api fetches DB connection string from QuantumVault (if not cached)
  7. users-api decrypts requested PII fields via QuantumAPI EaaS
  8. Response back to user

  Service-to-service (users-api → notifications):
  1. users-api calls notifications.users-api.svc.cluster.local:8080
  2. TCP allowed by NetworkPolicy (users-api → notifications)
  3. TLS handshake: both sides present ML-DSA certificate
  4. Both sides verify cert against QuantumAPI CA
  5. Request forwarded; notifications service processes it

  Pipeline (push to main):
  1. Azure DevOps: qapi CLI fetches secrets from QuantumVault
  2. Build → test → Trivy scan → docker push to ACR
  3. Cosign: fetch ML-DSA signing key from QuantumVault → sign image
  4. CycloneDX: generate SBOM → attach to image in ACR
  5. Cosign: verify signature before kubectl deploy
  6. kubectl rolling update → readiness probe gated

[L] LINK
  | Component          | Connects to      | Protocol         | Auth                     |
  | ------------------ | ---------------- | ---------------- | ------------------------ |
  | Browser            | API Gateway      | HTTPS / TLS 1.3  | QuantumID OIDC token     |
  | API Gateway        | users-api        | mTLS             | ML-DSA cert from QA CA   |
  | users-api          | PostgreSQL       | Npgsql / TLS     | Conn string from Vault   |
  | users-api          | QuantumAPI EaaS  | HTTPS            | X-Api-Key (env var)      |
  | users-api          | QuantumVault     | HTTPS            | X-Api-Key (env var)      |
  | users-api          | QuantumID (JWKS) | HTTPS (read-only)| None (public endpoint)   |
  | users-api          | notifications    | mTLS             | ML-DSA cert from QA CA   |
  | ADO pipeline       | QuantumVault     | HTTPS            | Service account API key  |
  | ADO pipeline       | ACR              | HTTPS            | Service connection       |
  | Cosign             | ACR              | OCI / HTTPS      | ACR credentials          |
  | K8s pods           | QuantumAPI CA    | HTTPS            | X-Api-Key (K8s Secret)   |

  Failure modes:
  - QuantumAPI unreachable: secrets cached in memory for one request lifetime.
    If unavailable at startup, pod fails readiness check → old pods stay up.
  - QuantumID JWKS unreachable: .NET caches signing keys. Short outage handled.
  - Certificate expired: CertificateRotationService renews at -4h before expiry.
  - mTLS handshake failure: request rejected → 503 logged → alert triggers.

[A] ASSEMBLE
  Phase 1: Foundation (applies once per environment)
    - QuantumAPI account + tenant setup
    - QuantumVault: create secrets for each service
    - QuantumID: register each service as an application
    - ACR: create signing key in QuantumVault, distribute CA cert to cluster

  Phase 2: Service hardening (per service)
    - Add QuantumAPI.Client NuGet
    - IEncryptionService → QuantumApiEncryptionService
    - ISecretProvider → QuantumVaultSecretProvider
    - IServiceCertificateProvider → fetches ML-DSA cert from QuantumAPI CA
    - Kestrel: ClientCertificateMode.RequireCertificate for internal endpoints
    - HttpClient "internal": attach service cert, verify peer against CA

  Phase 3: Pipeline (per repository)
    - Install qapi CLI in pipeline
    - Replace variable group secrets with QuantumVault IDs
    - Add Cosign signing + verification stages
    - Add CycloneDX SBOM generation

  Phase 4: Cluster configuration
    - NetworkPolicy per namespace
    - Distribute QuantumAPI CA public cert to cluster ConfigMap
    - RBAC: service accounts with minimum permissions

[S] STRESS-TEST
  Scenario 1: Compromised pod
    - Pod A is compromised. Attacker has pod A's ML-DSA certificate.
    - Can they call services that pod A isn't allowed to call?
    - NetworkPolicy blocks TCP. Even if they forge a cert, TCP is rejected first.
    - Can they read data from PostgreSQL directly?
    - NetworkPolicy: only users-api pods can reach the DB namespace.
    - Attacker would need to compromise a users-api pod and use its cert.

  Scenario 2: Leaked API key
    - A QuantumAPI API key is leaked (committed to a public repo).
    - Attacker calls QuantumVault: can read secrets that key has access to.
    - Mitigation: scope API keys per service (minimum permissions).
    - Recovery: revoke the key in QuantumVault dashboard. Issue new key.
    - Damage: limited to what that key could read (not all tenants, not all secrets).

  Scenario 3: Malicious image pushed to ACR
    - Attacker with ACR write access pushes a malicious image with the same tag.
    - Pipeline: Cosign verify step fails → deploy stage never runs.
    - Manual deploy: engineer runs kubectl with the malicious image tag.
    - Mitigation: Kubernetes admission webhook (Ratify) rejects unsigned images.
    - This webhook is the missing piece — covered in the next series.

  Scenario 4: Database backup leaked
    - An unencrypted database backup ends up in a public storage container.
    - Users table: EmailCiphertext, PhoneNumberCiphertext → ML-KEM ciphertext.
    - Attacker needs the QuantumAPI private key to decrypt. That never leaves QA.
    - Password hashes: Argon2id. Not decryptable.
    - Non-PII fields (FirstName, LastName): plaintext. These should be assessed
      for encryption too in regulated environments.

The reference diagram

graph TB
    subgraph External["External"]
        User["Browser / Client"]
        Pipeline["Azure DevOps Pipeline"]
    end

    subgraph Azure["Azure"]
        AFD["Azure Front Door\nTLS 1.3"]
        ACR["Azure Container\nRegistry"]
    end

    subgraph QuantumAPI["quantumapi.eu"]
        QV["QuantumVault\nML-KEM secrets"]
        QE["EaaS\nML-KEM + AES-GCM"]
        QI["QuantumID\nML-DSA OIDC"]
        QCA["Certificate Authority\nML-DSA-65"]
    end

    subgraph AKS["AKS Cluster"]
        subgraph NS_GW["namespace: gateway"]
            GW["API Gateway\nmTLS client"]
        end
        subgraph NS_USERS["namespace: users-api"]
            UA["users-api\nML-DSA cert"]
            PG["PostgreSQL\nencrypted PII"]
        end
        subgraph NS_NOTIF["namespace: notifications"]
            NOTIF["notifications\nML-DSA cert"]
        end
        subgraph NS_SYSTEM["namespace: system"]
            NP["NetworkPolicy\nper namespace"]
        end
    end

    User -->|"HTTPS + QuantumID token"| AFD
    AFD -->|"route"| GW
    GW -->|"mTLS\nML-DSA cert"| UA
    UA -->|"mTLS\nML-DSA cert"| NOTIF
    UA -->|"Npgsql TLS"| PG

    UA -->|"X-Api-Key\nencrypt/decrypt PII"| QE
    UA -->|"X-Api-Key\nget secrets"| QV
    UA -->|"JWKS\nvalidate tokens"| QI
    UA -->|"X-Api-Key\nget cert"| QCA
    GW -->|"X-Api-Key\nget cert"| QCA
    NOTIF -->|"X-Api-Key\nget cert"| QCA

    Pipeline -->|"qapi CLI\nfetch secrets"| QV
    Pipeline -->|"push image"| ACR
    Pipeline -->|"Cosign sign\nML-DSA key from Vault"| ACR
    GW -->|"pull image\nCosign verify"| ACR

    NP -.->|"controls TCP"| NS_USERS
    NP -.->|"controls TCP"| NS_NOTIF

    style QuantumAPI fill:#1e3a5f,color:#fff
    style QV fill:#2563eb,color:#fff
    style QE fill:#2563eb,color:#fff
    style QI fill:#2563eb,color:#fff
    style QCA fill:#2563eb,color:#fff
    style AKS fill:#0f172a,color:#fff
    style External fill:#1f2937,color:#fff
    style Azure fill:#1c3a5e,color:#fff

The GOTCHA prompt for the complete system

=== GOALS ===
Harden an existing .NET 10 microservices platform on AKS with:
- Post-quantum secrets management (QuantumVault)
- Field-level PII encryption (QuantumAPI EaaS, ML-KEM-768)
- Quantum-safe authentication (QuantumID, ML-DSA tokens)
- mTLS between services (QuantumAPI CA, ML-DSA-65 certs)
- Quantum-safe CI/CD (QuantumVault secrets, Cosign image signing)

=== ORCHESTRATION ===
Phase 1: Foundation
  1. QuantumAPI tenant setup + service account API keys
  2. QuantumVault: migrate all secrets from variable groups + appsettings
  3. QuantumID: register all services as OIDC applications

Phase 2: Per service
  4. Add QuantumAPI.Client NuGet
  5. IEncryptionService → encrypt PII fields (Email, Phone, DOB)
  6. ISecretProvider → connection strings + API keys from Vault
  7. IServiceCertificateProvider → ML-DSA cert from QuantumAPI CA
  8. Kestrel: require client cert on internal endpoints
  9. HttpClient "internal": attach cert, verify peer

Phase 3: Pipeline
  10. Install qapi CLI in ADO pipeline
  11. Replace variable group secrets with qapi vault get calls
  12. Add Cosign signing stage after docker push
  13. Add CycloneDX SBOM stage after build

Phase 4: Cluster
  14. NetworkPolicy per namespace (restrict ingress/egress)
  15. Distribute QuantumAPI CA cert to cluster ConfigMap

=== TOOLS ===
- QuantumAPI.Client (NuGet)
- QuantumApiClient: Encryption, Vault, Certificates namespaces
- .NET 10: Kestrel, HttpClientFactory, BackgroundService
- Entity Framework Core + Npgsql (existing)
- qapi CLI (quantumapi.eu/cli)
- Cosign (image signing)
- CycloneDX (SBOM generation)
- kubectl + Azure DevOps YAML pipelines

=== CONTEXT ===
- Platform: AKS (Azure Kubernetes Service)
- Services: users-api, notifications, API gateway
- Database: PostgreSQL 16 per service
- CI/CD: Azure DevOps multi-stage YAML
- Existing: Trivy scanning, rolling deploys, variable groups (to be replaced)
- QuantumAPI tenant: quantumapi.eu (EU data residency)

=== HEURISTICS ===
DO:
- Resolve secrets at startup, cache for process lifetime (connection strings)
- Resolve certificates at startup, cache with IsExpiringSoon check
- Encrypt fields in parallel (Task.WhenAll)
- Use SHA3-256 for searchable hashes (email lookup)
- Mark all fetched secrets as issecret=true in Azure DevOps
- Verify image signature before kubectl apply

DON'T:
- Don't write private keys or decrypted secrets to disk
- Don't log decrypted field values
- Don't put QuantumAPI key in appsettings.json (environment variable only)
- Don't use the "internal" HttpClient for external API calls
- Don't skip NetworkPolicy — mTLS alone is not enough

=== ARGS ===
ML-KEM algorithm: ML-KEM-768 (default tenant key)
ML-DSA algorithm: ML-DSA-65 (service certificates)
Certificate validity: 24 hours
Certificate renewal threshold: 4 hours before expiry
Rotation check interval: 1 hour (BackgroundService)
SearchableEmail hash: SHA3-256, lowercase+trim input
qapi CLI version: pinned in pipeline (QAPI_VERSION variable)
Cosign: --exit-code 1 on verify failure

The checklist for production readiness

=== QUANTUM-SAFE PRODUCTION CHECKLIST ===

SECRETS
[ ] Zero connection strings in appsettings.json or variable groups
[ ] Zero secrets in pipeline YAML (only QUANTUMAPI_KEY remains in ADO)
[ ] git grep -r "password\|secret\|connectionstring" --include="*.json" → 0
[ ] QuantumVault audit log: verify app reads are appearing

DATA ENCRYPTION
[ ] PII fields in all services: EmailCiphertext, PhoneNumberCiphertext, etc.
[ ] SearchableEmail: SHA3-256 hash, indexed
[ ] Existing rows: encrypted via migration script
[ ] EaaS latency: p99 < 100ms (measure in staging)

AUTHENTICATION
[ ] QuantumID: all services registered as OIDC applications
[ ] .NET AddJwtBearer: authority = QuantumID, algorithm = ML-DSA
[ ] No custom JWT issuance anywhere in codebase
[ ] Token introspection: enabled for high-sensitivity operations

PIPELINE
[ ] Cosign: every image pushed to ACR is signed
[ ] Cosign verify: passes before every deploy
[ ] SBOM: attached as OCI attestation
[ ] No ADO secrets except QUANTUMAPI_KEY

CLUSTER
[ ] NetworkPolicy: ingress/egress restricted per namespace
[ ] mTLS: all internal services require client certs
[ ] CA cert: distributed to cluster as ConfigMap
[ ] Certificate rotation: BackgroundService running, logs expiry time

MONITORING
[ ] mTLS handshake failures: alert configured
[ ] Certificate expiry: alert if < 2 hours left (below rotation threshold)
[ ] QuantumVault: alert on read failures (secret unavailable)
[ ] QuantumID: JWKS fetch failures logged

What Comes Next

This series covered the security foundations. Post-quantum cryptography as the base. Three products — QuantumVault, EaaS, QuantumID — applied to real problems in real systems. Zero trust at the service layer. A pipeline that produces signed, attested, SBOM-annotated images.

There are two things we left open that belong in a next series:

Kubernetes admission control. Scenario 3 in the stress test exposed a gap: if an engineer manually deploys an unsigned image, nothing stops them. The fix is a Kubernetes admission webhook — Ratify with Cosign integration — that rejects pods with unsigned images at the cluster level. This belongs in a dedicated series on Kubernetes security hardening.

Compliance and audit. GDPR, NIS2, eIDAS 2.0 have specific requirements: data subject access requests, right to erasure, audit trails for key operations, breach notification timelines. QuantumVault has audit logs. QuantumID has session history. But turning those logs into compliance evidence requires a framework — automated DSAR responses, key operation reports, encryption coverage reports. That’s the next series.

If you want to be notified when either series starts, subscribe below.

Final Words

Security is often treated as a feature — something you add after the system works. “We’ll add encryption later.” “We’ll fix the secrets when we have time.”

This series is about the opposite approach: security as a design decision made before the first line of code. The ATLAS checklist forces you to think about secrets, authentication, and encryption in the design phase — not after a breach. GOTCHA structures those decisions into AI prompts that produce code matching your security requirements.

quantumAPI makes the post-quantum part practical. You don’t need to implement ML-KEM yourself. You don’t need to manage a hardware security module. You call an API. You get back quantum-safe cryptography backed by real QRNG hardware and NIST-standardised algorithms.

The harvest-now-decrypt-later threat is real. The NIST deadline is not theoretical. But the tools exist, the standards are published, and the migration is manageable if you start now.

The time to build a quantum-safe system is before the attackers have a quantum computer. That time is now.

See you in the next series.

Victor

If this series helps you, consider buying me a coffee.

Comments

Loading comments...