Back

Security Architecture

How QuantumDeploy handles your cloud credentials

QuantumDeploy never permanently possesses customer cloud credentials or infrastructure state. It borrows just enough power to execute one deployment, under constraints, and then lets it go.

Core Principle

The agent does not permanently own cloud power. It borrows scoped, time-bounded authority at execution time via native cloud trust primitives — then lets it go.

What we never store

Zero customer secrets in our systems

Cloud access keys / secret keys / tokensNever storedResolved at runtime, held only in process memory
Service principal secretsNever storedFetched from your Key Vault at deploy time
Service account key filesNever storedImpersonation tokens generated at deploy time
Terraform state filesNever storedState lives in your Azure Blob, S3, or GCS bucket
Backend auth credentialsNever storedAuth flows through workload identity and env vars

What we store by reference

References only — never the actual secrets

Azure credentialsKey Vault URI + secret namesNot the client ID, secret, or tenant ID values
AWS credentialsRole ARN + External IDNot the access keys, secret keys, or session tokens
GCP credentialsService account email + projectNot key files or OAuth tokens
State backendBucket / container / account namesNot access keys, SAS tokens, or auth credentials

Cloud identity paths

Native cloud trust, not invented security

AzureAKS Workload Identity → Key Vault → Terraform

Pod has Managed Identity. Key Vault Secrets User role (read-only). Fetches SP credentials by secret name. ARM_* env vars for Terraform.

AWSIRSA → STS AssumeRole → Terraform

Pod has IAM Role via IRSA. AssumeRole with ExternalId (confused deputy protection). Session tags for CloudTrail attribution. Temporary credentials (max 1hr).

GCPWorkload Identity → SA Impersonation → Terraform

Pod has GCP SA binding. IAM Credentials API generateAccessToken on customer's SA. Short-lived OAuth token. No key files anywhere.

Execution architecture

One disposable runner per deploy

Control Plane

  • Stores references only
  • Issues signed runner tokens (HMAC-SHA256)
  • Creates K8s Jobs via client-go
  • Never resolves or transmits actual secrets
  • Records immutable evidence after each deploy

Runner Pod

  • Resolves credentials itself (workload identity)
  • Secrets exist only in process memory
  • Self-destructs after completion (TTL: 300s)
  • Non-root, bounded workspace, resource limits
  • No K8s API access (SA token not mounted)

Runner authentication

Signed, scoped, one-time-use tokens

HMAC-SHA256 signed

Cannot be forged without server secret

Deployment-scoped

Token for deploy A cannot access deploy B

Tenant-scoped

Token for tenant X cannot access tenant Y

Time-limited

Expires after deploy timeout + buffer

Replay-protected

Each nonce consumed once (Redis SET NX)

Key rotation

Current + previous key accepted during rotation

Secret redaction

Every output scrubbed before persistence

All Terraform output is pattern-matched and redacted before it reaches logs, databases, or your screen:

  • Azure connection strings (AccountKey=, SharedAccessSignature=)
  • AWS key IDs (AKIA*, ASIA*) and secret keys
  • GCP OAuth tokens (ya29.*)
  • Generic secret assignments (key = "...", password = "...")
  • Environment variable patterns (ARM_CLIENT_SECRET=, AWS_SECRET_ACCESS_KEY=)

The ExecutionCredentials.Env field is tagged json:"-" — it cannot be serialized by the standard library. This prevents accidental persistence through JSON marshaling, debug logging, or audit record creation.

Deploy evidence

Tamper-evident records for every deployment

Every deploy produces an integrity-hashed evidence record containing:

Deployment + tenant IDs
Who initiated + method
Credential reference (ID only)
Cloud identity path used
State backend type + location
Execution mode (local / K8s)
Runner image + digest
Artifact count + SHA-256 hash
Start/end times + duration
Success / failure mode
Correlation ID
Record integrity hash

State ownership

Your Terraform state stays in your cloud account

Azure deploysazurerm backendYour storage account + container
AWS deploysS3 backendYour bucket + optional DynamoDB locking
GCP deploysGCS backendYour bucket + prefix

Backend config values are passed via -backend-config CLI flags (non-sensitive location only). Sensitive backend keys like access_key, sas_token, and secret_key are rejected by the validation layer.

Preflight validation

Insecure setups blocked before first deploy

Vault / role / SA accessibleValidate endpoint tests connectivityChecked
ExternalId present (AWS)Required — blocks deploy without itEnforced
Subscription / region / project constraintsValidated before credential resolutionChecked
State backend has required fieldsBlocks deploy without required configEnforced
No sensitive keys in backend configRejects access_key, sas_token, etc.Enforced
Credential ref formatRegex validation, no path traversalEnforced

Questions about our security architecture?

Contact security team