Skip to main content
Career Paths
Concepts
Secrets Encryption Vault
The Simplified Tech

Role-based learning paths to help you master cloud engineering with clarity and confidence.

Product

  • Career Paths
  • Interview Prep
  • Scenarios
  • AI Features
  • Cloud Comparison
  • Pricing

Community

  • Join Discord

Account

  • Dashboard
  • Credits
  • Updates
  • Sign in
  • Sign up
  • Contact Support

Stay updated

Get the latest learning tips and updates. No spam, ever.

Terms of ServicePrivacy Policy

© 2026 TheSimplifiedTech. All rights reserved.

BackBack
Interactive Explainer

Secrets Encryption: etcd at Rest and Vault Integration

Kubernetes Secrets are base64 by default -- not encrypted. Enabling etcd encryption at rest closes the disk-level exposure. HashiCorp Vault provides enterprise-grade secret lifecycle management, dynamic credentials, and lease-based rotation that Kubernetes native Secrets cannot match.

Relevant for:SeniorStaff
Why this matters at your level
Senior

Configure EncryptionConfiguration on kube-apiserver. Understand AES-GCM vs KMS provider. Rotate the encryption key. Understand what encryption at rest does and does not protect.

Staff

Design enterprise secret management with Vault: dynamic database credentials (no static passwords), PKI secrets engine (auto-issue TLS certs), Vault Agent Injector for zero-secret-in-pod patterns, lease renewal for credential rotation.

Secrets Encryption: etcd at Rest and Vault Integration

Kubernetes Secrets are base64 by default -- not encrypted. Enabling etcd encryption at rest closes the disk-level exposure. HashiCorp Vault provides enterprise-grade secret lifecycle management, dynamic credentials, and lease-based rotation that Kubernetes native Secrets cannot match.

~4 min read
Be the first to complete!
LIVEetcd Snapshot Exfiltration -- Database Credentials Exposed -- 2021
Breaking News
T-3mo

etcd snapshots backed up to S3 with public-read ACL; encryption at rest not enabled

T+0

Security researcher finds public S3 bucket containing etcd snapshots

T+30m

All 47 Secrets decoded from base64 in etcd snapshot -- plaintext credentials

T+2h

Responsible disclosure; incident response begins; all credentials rotated

T+1w

EncryptionConfiguration with AES-GCM deployed; S3 bucket ACL fixed; Vault integration planned

—Secrets in plaintext etcd snapshot
—Time to decode all credentials
—ACL misconfiguration that exposed etcd backups

The question this raises

What does etcd encryption at rest actually protect against -- and what does it not protect against?

Test your assumption first

You enable etcd encryption at rest with EncryptionConfiguration. An attacker compromises a node running kube-apiserver and has root access to the node. What Kubernetes Secrets can they access?

Lesson outline

What etcd Encryption Solves

The Disk Exposure Threat Model

Kubernetes Secrets are base64-encoded in etcd -- trivially decodable. If an attacker gets the etcd data files or backups, they have all your Secrets. Encryption at rest means those files contain ciphertext, not plaintext. But the kube-apiserver still decrypts Secrets on every read -- so the API server itself remains a trust boundary.

EncryptionConfiguration (AES-GCM)

Use for: Configure via kube-apiserver --encryption-provider-config flag. AES-GCM key stored in config file on API server. Encrypts new Secrets on write; existing Secrets must be re-encrypted with: kubectl get secrets --all-namespaces -o json | kubectl replace -f -

KMS Envelope Encryption

Use for: API server generates per-Secret data encryption key (DEK); DEK encrypted by AWS KMS / GCP KMS / Vault key (KEK). Even if etcd + API server is compromised, master key is in external KMS. Two separate access paths required.

Vault Dynamic Credentials

Use for: Vault database secrets engine creates short-lived DB users on demand (TTL: 1h). Pod requests credential via Vault Agent sidecar; credential injected as file. No static password ever stored in K8s Secret.

The System View: Encryption Architecture

Option A: AES-GCM (simpler, weaker)
kubectl create secret db-pass --from-literal=password=hunter2
  -> kube-apiserver encrypts with AES-GCM key from config file
  -> etcd stores: k8s:enc:aescbc:v1:key1:BASE64_CIPHERTEXT
  -> kube-apiserver config file on disk holds the AES key
  !! Root access to API server node = decrypt all secrets

Option B: KMS Envelope (stronger, 2-party)
  kubectl create secret db-pass --from-literal=password=hunter2
  -> kube-apiserver requests DEK from KMS plugin (gRPC)
  -> KMS plugin calls AWS KMS to encrypt DEK with CMK
  -> etcd stores: k8s:enc:kms:v2:ENCRYPTED_DEK + ENCRYPTED_DATA
  -> compromising etcd alone is not enough (encrypted DEK needs CMK)
  -> compromising API server alone is not enough (cannot get CMK without KMS auth)

Option C: Vault Dynamic (no static secret at all)
  DB: no static users; Vault leases control access
  Pod startup -> Vault Agent -> Vault DB secrets engine
  -> Vault generates: username=vault-pod-xyz-1234, password=<random>
  -> Injected as /vault/secrets/db.env  (TTL: 1h)
  -> Lease expires -> Vault revokes DB user
  -> No static password ever in K8s Secret

Three tiers of secret protection: each requires compromising an additional system to gain credential access

Secret Security Architecture Evolution

Situation
Before
After

Production cluster with base64 Secrets and etcd backups in S3

“etcd backup leaked to public S3; all 47 credentials decoded in 30 seconds; full breach”

“KMS encryption at rest; etcd backups encrypted; even if S3 bucket is exposed, ciphertext is useless without KMS access”

Database password rotated on compromise

“Static password in K8s Secret; rotation requires: update Secret, rolling restart all pods that use it; downtime window”

“Vault dynamic credentials; revoke all leases immediately (break glass); all DB connections fail within TTL; new credentials issued on next pod startup; no K8s Secret to update”

How etcd Encryption at Rest Works

Enabling etcd encryption at rest (AES-GCM)

→

01

1. Create EncryptionConfiguration YAML with resources: [secrets] and AES-GCM key (32-byte base64)

→

02

2. Store config on all control plane nodes at /etc/kubernetes/enc/encryption-config.yaml

→

03

3. Add --encryption-provider-config flag to kube-apiserver manifest

→

04

4. Restart kube-apiserver; NEW Secret writes are encrypted; existing Secrets remain plaintext

→

05

5. Re-encrypt existing Secrets: kubectl get secrets --all-namespaces -o json | kubectl replace -f -

06

6. Verify: etcdctl get /registry/secrets/default/my-secret | hexdump -- should show k8s:enc prefix not readable text

1

1. Create EncryptionConfiguration YAML with resources: [secrets] and AES-GCM key (32-byte base64)

2

2. Store config on all control plane nodes at /etc/kubernetes/enc/encryption-config.yaml

3

3. Add --encryption-provider-config flag to kube-apiserver manifest

4

4. Restart kube-apiserver; NEW Secret writes are encrypted; existing Secrets remain plaintext

5

5. Re-encrypt existing Secrets: kubectl get secrets --all-namespaces -o json | kubectl replace -f -

6

6. Verify: etcdctl get /registry/secrets/default/my-secret | hexdump -- should show k8s:enc prefix not readable text

encryption-config.yaml
1apiVersion: apiserver.config.k8s.io/v1
2kind: EncryptionConfiguration
3resources:
4- resources:
5 - secrets
6 providers:
7 - aescbc:
8 keys:
9 - name: key1
10 secret: <32-byte-base64-encoded-key>
identity: {} fallback -- allows reading Secrets written before encryption was enabled
11 - identity: {} # fallback for reading pre-encryption secrets
After re-encrypting all Secrets, remove identity: {} to prevent plaintext fallback
12 # For KMS (stronger):
13 # - kms:
14 # name: aws-kms
15 # endpoint: unix:///var/run/kmsplugin/socket.sock
16 # cachesize: 1000
17 # timeout: 3s

What Breaks in Production: Blast Radius

Encryption misconfiguration failure modes

  • Encryption key loss = all Secrets irrecoverable — If the AES-GCM key file is lost and Secrets are encrypted with it, all encrypted Secrets become undecipherable. Back up the key separately from etcd. Rotate keys gradually (add new key, re-encrypt, remove old key).
  • Pre-existing Secrets not re-encrypted — Enabling EncryptionConfiguration only encrypts NEW Secrets. Old Secrets remain plaintext. Run the re-encrypt command explicitly after enabling encryption.
  • KMS plugin unavailable blocks Secret reads — If KMS plugin (gRPC) is down, API server cannot decrypt Secrets. All workloads that mount Secrets will fail to start. KMS plugin must be highly available and its failure mode must be tested.
  • Vault lease expiry causes auth failure — Dynamic credentials expire at TTL. Application must handle credential renewal (Vault Agent handles this automatically). If Vault Agent fails to renew, next DB connection after TTL expiry fails. Monitor Vault Agent sidecar health separately.

EncryptionConfiguration without re-encrypting existing Secrets

Bug
# Step 1: Add EncryptionConfiguration to kube-apiserver ✓
# Step 2: Restart kube-apiserver ✓
# FORGOT Step 3: re-encrypt existing Secrets

# Result: NEW secrets encrypted, OLD secrets still plaintext
# etcd backup still exposes old secrets
# kubectl get secret old-secret -o yaml shows plaintext data
Fix
# After enabling encryption, re-encrypt ALL existing Secrets:
kubectl get secrets --all-namespaces -o json | kubectl replace -f -

# Verify a specific secret is now encrypted:
# etcdctl get /registry/secrets/default/old-secret | strings
# Should show: k8s:enc:aescbc:v1:key1:...  (not readable text)

# Only after verification, remove identity: {} fallback from config

Enabling encryption does not retroactively encrypt existing Secrets. The kubectl replace command reads and re-writes all Secrets, triggering the API server to encrypt them with the new config. Must be done before removing the identity fallback provider.

Decision Guide: Secret Encryption Level

Do you have compliance requirements (PCI-DSS, HIPAA, SOC 2) for data-at-rest encryption?
YesEnable etcd encryption at rest -- KMS provider for key separation; document key management
NoAt minimum, enable AES-GCM to protect etcd backups
Do you need to eliminate static credentials entirely?
YesVault dynamic credentials + Vault Agent Injector -- no static passwords anywhere in K8s
NoExternal Secrets Operator (sync from AWS SM/Vault) reduces attack surface while keeping simpler architecture
Is the threat model insider threat (rogue admin with etcd access)?
YesKMS envelope encryption -- API server + KMS must both be compromised; separate access controls
NoAES-GCM encryption protects against external etcd exposure (stolen disk, public backup)

Cost and Complexity: Secret Protection Tiers

TierProtects againstDoes NOT protect againstComplexity
Base64 (default)NothingAny access to etcd dataNone
AES-GCM encryptionetcd disk theft, backup exposureAPI server compromise, key file theftLow
KMS envelopeetcd + API server compromise (separate keys)Compromise of both API server + KMS authMedium
Vault dynamic credsCredential leak (TTL-limited)Active session until TTL expiryHigh
KMS + Vault + RBAC + AuditMost practical threat vectorsCoordinated multi-system breachVery high

Exam Answer vs. Production Reality

1 / 3

What etcd encryption at rest protects

📖 What the exam expects

Encrypts Secret data before writing to etcd disk. Protects against: etcd backup exposure, etcd disk theft, unauthorized etcd server access.

Toggle between what certifications teach and what production actually requires

How this might come up in interviews

Security architecture questions about protecting sensitive credentials and compliance questions about data-at-rest encryption.

Common questions:

  • What is etcd encryption at rest and what does it protect against?
  • What is the difference between AES-GCM and KMS provider for etcd encryption?
  • How does Vault dynamic credential generation work?
  • How would you ensure no static credentials exist in Kubernetes Secrets?

Strong answer: Mentions KMS envelope encryption for key separation, Vault dynamic credentials to eliminate static passwords, and Vault Agent Injector for zero-secret-in-pod patterns.

Red flags: Thinking encryption at rest prevents all Secret exposure, or not knowing that the kube-apiserver holds the key for AES-GCM encryption.

Related concepts

Explore topics that connect to this one.

  • ConfigMaps & Secrets: Config Without Rebuilding
  • Secrets Management
  • etcd Deep Dive: The Brain of Every Kubernetes Cluster

Suggested next

Often learned after this topic.

Image Security & Supply Chain: From Build to Runtime

Ready to see how this works in the cloud?

Switch to Career Paths for structured paths (e.g. Developer, DevOps) and provider-specific lessons.

View role-based paths

Discussion

Questions? Discuss in the community or start a thread below.

Join Discord

In-app Q&A

Sign in to start or join a thread.

Sign in to track your progress and mark lessons complete.

Continue learning

Image Security & Supply Chain: From Build to Runtime

Discussion

Questions? Discuss in the community or start a thread below.

Join Discord

In-app Q&A

Sign in to start or join a thread.