Skip to content

Services, Wiki-Artikel, Blog-Beiträge und Glossar-Einträge durchsuchen

↑↓NavigierenEnterÖffnenESCSchließen

Cloud Key Management: AWS KMS, Azure Key Vault und HashiCorp Vault im Vergleich

Cloud Key Management Services (KMS) protect cryptographic keys in the cloud. This article compares AWS KMS, Azure Key Vault, and HashiCorp Vault: key types (CMK, DEK, KEK), envelope encryption, HSM integration, key rotation strategies, BYOK (Bring Your Own Key), HYOK (Hold Your Own Key), access policies, and compliance requirements (FIPS 140-2, BSI).

Table of Contents (5 sections)

Cloud key management is one of the most critical security disciplines in modern cloud architectures. Incorrectly configured key management leads to the most far-reaching data breaches—not because encryption was broken, but because keys were mismanaged. This article explains the most important cloud KMS solutions and best practices.

Basic Concepts

Key Hierarchy and Envelope Encryption:

Key Types:
  CMK (Customer Master Key):
  → ALWAYS remains in the KMS; never leaves it!
  → Used to encrypt DEKs
  → Can be stored on an HSM (Hardware Security Module)

  DEK (Data Encryption Key):
  → Encrypts the actual data (symmetric, AES-256)
  → Is itself encrypted with the CMK (Envelope Encryption!)
  → Plaintext DEK: only briefly in memory, then discarded
  → Encrypted DEK: stored alongside the data (ciphertext-DEK)

Envelope Encryption (AWS principle):
  1. Generate DEK (random, 256-bit)
  2. Encrypt data with DEK: Encrypted_Data = AES256(Data, DEK)
  3. Encrypt DEK with CMK: Encrypted_DEK = KMS.Encrypt(DEK, CMK)
  4. Store: Encrypted_Data + Encrypted_DEK (together!)
  5. Delete DEK (plaintext) from storage!

  Decryption:
  1. Encrypted_DEK → KMS.Decrypt → DEK (plaintext)
  2. DEK → AES256_Decrypt(Encrypted_Data) → Data
  3. Discard DEK again

Advantage:
  → CMK never leaves KMS → secure in HSM
  → KMS calls: only for DEK encryption/decryption (cost-effective!)
  → Bulk data encrypted directly (no KMS overhead per byte)

AWS KMS

AWS Key Management Service:

Key types:
  AWS-Managed Key:     automatically created/rotated by AWS
                       (e.g., aws/s3, aws/ebs, aws/rds)
  Customer-Managed Key (CMK): created and controlled by the customer
  AWS-Owned Key:       AWS internal, invisible to customers

Create a CMK:
  # AWS CLI:
  aws kms create-key \
    --description "Production database key" \
    --key-usage ENCRYPT_DECRYPT \
    --key-spec SYMMETRIC_DEFAULT  # AES-256-GCM

  # Multi-Region Key (for DR scenarios):
  aws kms create-key --multi-region \
    --description "Multi-Region Key for global app"

  # With HSM backup (FIPS 140-2 Level 3):
  aws kms create-key --origin AWS_CLOUDHSM \
    # Required: CloudHSM cluster as a custom key store

Key policy (access control):
  # JSON key policy:
  {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "Key Admin",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::123456789:role/KeyAdminRole"},
        "Action": ["kms:Create*", "kms:Describe*", "kms:Delete*",
                   "kms:Enable*", "kms:Disable*", "kms:RotateKey"],
        "Resource": "*"
      },
      {
        "Sid": "Key Usage",
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::123456789:role/AppRole"},
        "Action": ["kms:Encrypt", "kms:Decrypt",
                   "kms:GenerateDataKey", "kms:ReEncrypt*"],
        "Resource": "*"
      }
    ]
  }

  # IMPORTANT: ALWAYS include the root account in the key policy (secure account access!)

Automatic Key Rotation:
  # Enable 365-day rotation:
  aws kms enable-key-rotation --key-id alias/prod-db-key
  # → AWS automatically rotates keys annually
  # → Keep old key versions for decryption!

BYOK (Bring Your Own Key):
  # Import your own key into AWS KMS:
  # 1. Request a wrapping key from AWS:
  aws kms get-parameters-for-import \
    --key-id <key-id> \
    --wrapping-algorithm RSAES_OAEP_SHA_256 \
    --wrapping-key-spec RSA_2048

  # 2. Encrypt your own key material with the wrapping key
  # 3. Import:
  aws kms import-key-material \
    --key-id <key-id> \
    --encrypted-key-material fileb://encrypted_key.bin \
    --import-token fileb://import_token.bin \
    --expiration-model KEY_MATERIAL_EXPIRES \
    --valid-to 2027-12-31T23:59:59Z

S3 server-side encryption with CMK:
  # Bucket policy: Enforce SSE-KMS:
  {
    &quot;Version&quot;: &quot;2012-10-17&quot;,
    &quot;Statement&quot;: [{
      &quot;Sid&quot;: &quot;DenyUnencryptedObjectUploads&quot;,
      &quot;Effect&quot;: &quot;Deny&quot;,
      &quot;Principal&quot;: &quot;*&quot;,
      &quot;Action&quot;: &quot;s3:PutObject&quot;,
      &quot;Resource&quot;: &quot;arn:aws:s3:::my-bucket/*&quot;,
      &quot;Condition&quot;: {
        &quot;StringNotEquals&quot;: {
          &quot;s3:x-amz-server-side-encryption&quot;: &quot;aws:kms&quot;
        }
      }
    }]
  }

Azure Key Vault

Azure Key Vault - Keys, Secrets, Certificates:

Object Types:
  Keys:         Cryptographic keys (RSA, EC, AES via Premium)
  Secrets:      Passwords, API keys, connection strings
  Certificates: TLS/SSL certificates, including automatic renewal

Tiers:
  Standard: Software keys (HSM optional for secrets)
  Premium:  HSM-secured keys (FIPS 140-2 Level 2/3)

Create Key Vault (Terraform):
  resource &quot;azurerm_key_vault&quot; &quot;prod&quot; {
    name                = &quot;kv-prod-app-westeu&quot;
    resource_group_name = azurerm_resource_group.main.name
    location            = &quot;westeurope&quot;
    tenant_id           = data.azurerm_client_config.current.tenant_id
    sku_name            = &quot;premium&quot;  # HSM keys

    soft_delete_retention_days = 90
    purge_protection_enabled   = true  # CRITICAL: prevents data loss!

    network_acls {
      bypass         = &quot;AzureServices&quot;
      default_action = &quot;Deny&quot;  # Only explicitly allowed IPs!
      ip_rules       = [&quot;10.0.0.0/8&quot;]
    }
  }

  # Access Policy for App:
  resource &quot;azurerm_key_vault_access_policy&quot; &quot;app&quot; {
    key_vault_id = azurerm_key_vault.prod.id
    tenant_id    = data.azurerm_client_config.current.tenant_id
    object_id    = azurerm_user_assigned_identity.app.principal_id

    key_permissions    = [&quot;Get&quot;, &quot;WrapKey&quot;, &quot;UnwrapKey&quot;]
    secret_permissions = [&quot;Get&quot;, &quot;List&quot;]
  }

Retrieve secret from Key Vault in application (Python):
  from azure.identity import ManagedIdentityCredential
  from azure.keyvault.secrets import SecretClient

  credential = ManagedIdentityCredential()  # Managed Identity!
  vault_url = &quot;https://kv-prod-app-westeu.vault.azure.net/&quot;
  client = SecretClient(vault_url=vault_url, credential=credential)

  # Retrieve secret (no hard-coded credentials!):
  db_password = client.get_secret(&quot;database-password&quot;).value
  api_key = client.get_secret(&quot;external-api-key&quot;).value

Certificate Automation (Let&#x27;s Encrypt / DigiCert):
  # Key Vault automatically creates, renews, and deploys TLS certificates:
  resource &quot;azurerm_key_vault_certificate&quot; &quot;app_cert&quot; {
    name         = &quot;app-tls-cert&quot;
    key_vault_id = azurerm_key_vault.prod.id

    certificate_policy {
      issuer_parameters { name = &quot;DigiCert&quot; }
      key_properties {
        exportable = false  # Private key remains in Key Vault!
        key_type   = &quot;RSA&quot;
        key_size   = 4096
        reuse_key  = false
      }
      secret_properties { content_type = &quot;application/x-pkcs12&quot; }
      x509_certificate_properties {
        subject            = &quot;CN=app.example.com&quot;
        validity_in_months = 12
        key_usage = [&quot;cRLSign&quot;, &quot;dataEncipherment&quot;, &quot;digitalSignature&quot;, &quot;keyEncipherment&quot;]
      }
      lifetime_action {
        action { action_type = &quot;AutoRenew&quot; }
        trigger { days_before_expiry = 30 }
      }
    }
  }

HashiCorp Vault

HashiCorp Vault - Platform-agnostic:

Why Vault:
  → Cloud-agnostic: On-premises + AWS + Azure + GCP
  → Dynamic Secrets: Generate credentials on-demand (no static passwords!)
  → Lease system: Credentials expire automatically
  → Secret Zero problem solved: AppRole, K8s Auth, AWS IAM Auth

Start Vault server (Dev/Test):
  vault server -dev -dev-root-token-id=&quot;root&quot;
  export VAULT_ADDR=&#x27;http://127.0.0.1:8200&#x27;
  export VAULT_TOKEN=&#x27;root&#x27;

Key-Value Store (Static Secrets):
  # Write secret:
  vault kv put secret/myapp \
    db-password=&quot;s3cur3P@ss&quot; \
    api-key=&quot;abc123xyz&quot;

  # Read secret:
  vault kv get secret/myapp
  vault kv get -field=db-password secret/myapp

Dynamic Secrets (Database):
  # Enable PostgreSQL plugin:
  vault secrets enable database

  vault write database/config/postgres \
    plugin_name=postgresql-database-plugin \
    connection_url=&quot;postgresql://{{username}}:{{password}}@db:5432/appdb&quot; \
    username=&quot;vault-admin&quot; password=&quot;admin-password&quot;

  # Role: generates temporary DB user:
  vault write database/roles/app-role \
    db_name=postgres \
    creation_statements=&quot;CREATE ROLE \&quot;{{name}}\&quot; WITH LOGIN PASSWORD &#x27;{{password}}&#x27; VALID UNTIL &#x27;{{expiration}}&#x27;; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \&quot;{{name}}\&quot;;&quot;
    default_ttl=&quot;1h&quot;
    max_ttl=&quot;24h&quot;

  # App retrieves credentials (valid for 1 hour!):
  vault read database/creds/app-role
  # Key         Value
  # username    v-app-role-xyz123
  # password    randomGeneratedPassword!
  # lease_id    database/creds/app-role/abc...
  # lease_duration  1h0m0s

  # After 1h: Credentials invalid! Attacker with stolen credentials: worthless.

Transit Encryption (Encryption-as-a-Service):
  # Vault as an encryption service:
  vault secrets enable transit
  vault write transit/keys/myapp-key type=aes256-gcm96

  # Encrypt data:
  vault write transit/encrypt/myapp-key \
    plaintext=$(echo &quot;sensitive text&quot; | base64)

  # Response:
  # ciphertext: vault:v1:...encrypted...

  # Decrypt:
  vault write transit/decrypt/myapp-key \
    ciphertext=&quot;vault:v1:...encrypted...&quot;
  # plaintext: aGVsbG8=  (decode base64 for plaintext)

Kubernetes integration:
  # App in K8s authenticates without a static token:
  vault auth enable kubernetes

  vault write auth/kubernetes/config \
    token_reviewer_jwt=&quot;$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)&quot; \
    kubernetes_host=&quot;https://kubernetes.default.svc:443&quot; \
    kubernetes_ca_cert=@/var/run/secrets/kubernetes.io/serviceaccount/ca.crt

  vault write auth/kubernetes/role/myapp \
    bound_service_account_names=myapp-sa \
    bound_service_account_namespaces=production \
    policies=myapp-policy \
    ttl=1h

Key Management Best Practices

General KMS Best Practices:

Key Rotation:
  □ Automatic rotation: at least annually (AWS: enable-key-rotation)
  □ On-demand rotation: upon suspicion of compromise
  □ Rotation ≠ re-encryption of all data (DEK re-encryption required!)
  □ Old key material: retain for decryption of historical data

Least Privilege for Keys:
  → Development: no production keys
  → Read-Only Keys: only for decryption, no key management
  → Audit Role: only Describe/List, no Encrypt/Decrypt
  → Break-Glass: separate admin key for emergencies (MFA-protected)

BYOK/HYOK Decision:
  BYOK (Bring Your Own Key):
  → Import your own key material into the cloud KMS
  → More control, but: cloud provider has HSM access
  → For: regulatory compliance, auditability

  HYOK (Hold Your Own Key) / Double Encryption:
  → Key remains ON-PREMISES (HSM in your own data center)
  → Cloud provider can NEVER decrypt data
  → For: very high requirements (government agencies, state secrets)
  → Disadvantages: latency, managing your own HSM, no cloud auto-scaling for encryption

Compliance requirements:
  FIPS 140-2 Levels 1–4:
  → Level 2: physical protection (AWS KMS Standard, Azure Key Vault Premium)
  → Level 3: Tamper-evidence, critical security parameters (AWS CloudHSM)
  → Level 4: Full tamper response (rare, for government agencies)

  BSI TR-02102 (Germany):
  → RSA: ≥ 3000 bits (until 2030), 4096 bits recommended
  → EC: ≥ 250 bits, P-256/P-384 (NIST) or Brainpool P-256r1 recommended
  → AES: 256-bit in GCM mode
  → PBKDF2, bcrypt, Argon2 for password hashing

Monitoring and Alerting:
  → AWS CloudTrail: log all KMS API calls
  → Azure Monitor: Key Vault Diagnostic Logs
  → Alert: unexpected decryption requests
  → Alert: key management operations outside of business hours
  → Alert: Deny responses to key access (configuration error or attack?)
```</key-id></key-id>

Questions about this topic?

Our experts advise you free of charge and without obligation.

Free Consultation

About the Author

Chris Wojzechowski
Chris Wojzechowski

Geschäftsführender Gesellschafter

E-Mail

Geschäftsführender Gesellschafter der AWARE7 GmbH mit langjähriger Expertise in Informationssicherheit, Penetrationstesting und IT-Risikomanagement. Absolvent des Masterstudiengangs Internet-Sicherheit an der Westfälischen Hochschule (if(is), Prof. Norbert Pohlmann). Bestseller-Autor im Wiley-VCH Verlag und Lehrbeauftragter der ASW-Akademie. Einschätzungen zu Cybersecurity und digitaler Souveränität erschienen u.a. in Welt am Sonntag, WDR, Deutschlandfunk und Handelsblatt.

10 Publikationen
  • Einsatz von elektronischer Verschlüsselung - Hemmnisse für die Wirtschaft (2018)
  • Kompass IT-Verschlüsselung - Orientierungshilfen für KMU (2018)
  • IT Security Day 2025 - Live Hacking: KI in der Cybersicherheit (2025)
  • Live Hacking - Credential Stuffing: Finanzrisiken jenseits Ransomware (2025)
  • Keynote: Live Hacking Show - Ein Blick in die Welt der Cyberkriminalität (2025)
  • Analyse von Angriffsflächen bei Shared-Hosting-Anbietern (2024)
  • Gänsehaut garantiert: Die schaurigsten Funde aus dem Leben eines Pentesters (2022)
  • IT Security Zertifizierungen — CISSP, T.I.S.P. & Co (Live-Webinar) (2023)
  • Sicherheitsforum Online-Banking — Live Hacking (2021)
  • Nipster im Netz und das Ende der Kreidezeit (2017)
IT-Grundschutz-Praktiker (TÜV) IT Risk Manager (DGI) § 8a BSIG Prüfverfahrenskompetenz Ausbilderprüfung (IHK)
This article was last edited on 04.03.2026. Responsible: Chris Wojzechowski, Geschäftsführender Gesellschafter at AWARE7 GmbH. License: CC BY 4.0 - free use with attribution: "AWARE7 GmbH, https://a7.de"

Cookielose Analyse via Matomo (selbst gehostet, kein Tracking-Cookie). Datenschutzerklärung