WAF-SEC-060 – Secrets Management – No Hardcoded Credentials

Description

All secrets, API keys, passwords, database credentials, and certificates MUST be stored in a dedicated secrets management solution (AWS Secrets Manager or HashiCorp Vault). Secrets MUST NOT be hardcoded in IaC code, Terraform variable files, environment variables in task definitions, source code, or CI/CD pipeline configuration. Secrets Manager secrets MUST be encrypted with customer-managed KMS keys. Automatic rotation MUST be configured for all long-lived credentials where the target service supports it.

Rationale

Risk Description

Risk

Sensitive data is exposed if storage or transport lacks strong encryption.

Risk

Compromised keys or weak key rotation extend the blast radius of a breach.

Requirements

  • All secrets, API keys, passwords, database credentials, and certificates MUST be stored in a dedicated secrets management solution (AWS Secrets Manager or HashiCorp Vault).

  • Secrets MUST NOT be hardcoded in IaC code, Terraform variable files, environment variables in task definitions, source code, or CI/CD pipeline configuration.

  • Secrets Manager secrets MUST be encrypted with customer-managed KMS keys.

  • Automatic rotation MUST be configured for all long-lived credentials where the target service supports it.

Implementation Guidance

  1. Implement the required configuration as code in Terraform or equivalent IaC.

  2. Add an automated check to CI/CD so deviations are caught before deployment.

Maturity Levels

Level Name Criteria

L1

Ad hoc – control not consistently applied

* Manual evidence exists for some workloads, but coverage is unknown.

L2

Standardised – policy defined and communicated

* A version-controlled policy, ADR, or standard describes the requirement.

L3

Integrated – automated validation in CI/CD

* Terraform checks run automatically on pull requests and report results.

L4

Auditable – metrics and exceptions tracked

* Control coverage, failures, and approved exceptions are reported quarterly.

L5

Optimised – continuous improvement based on data

* Control effectiveness is measured and iteratively improved.

Checks

waf-sec-060.tf.aws.secrets-manager-exists

Engine: terraform | Provider: aws | Automated: Yes

Secrets Manager secrets must be defined with a recovery window

All aws_secretsmanager_secret resources must have a name attribute set and recovery_window_in_days >= 7 to prevent accidental deletion from causing immediate and irrecoverable data access loss.

Scope: resource β€” aws_secretsmanager_secret

Assertions: * name attribute exists β€” Secrets Manager secret must have an explicit name attribute. * recovery_window_in_days greater than or equal 7 β€” Secrets Manager secret recovery window must be at least 7 days to allow recovery from accidental deletion.

Remediation: Add name and recovery_window_in_days = 30 to all aws_secretsmanager_secret resources. Do not set force_overwrite_replica_secret = true or recovery_window_in_days = 0 unless in a controlled testing environment.

Compliant
resource "aws_secretsmanager_secret" "db_password" {
  name                    = "prod/app/db-password"
  description             = "RDS master password for production application database"
  kms_key_id              = aws_kms_key.secrets.arn
  recovery_window_in_days = 30
  tags = {
    owner       = "platform-team"
    environment = "production"
  }
}
Non-Compliant
resource "aws_secretsmanager_secret" "db_password" {
  # name not set                           – WAF-SEC-060 violation
  recovery_window_in_days = 0              # WAF-SEC-060 violation: no recovery window
  # kms_key_id not set                     – WAF-SEC-060 violation (check 2)
}

waf-sec-060.tf.aws.secrets-encrypted-with-cmk

Engine: terraform | Provider: aws | Automated: Yes

Secrets Manager secrets must be encrypted with a customer-managed KMS key

All aws_secretsmanager_secret resources must have a kms_key_id attribute referencing a customer-managed KMS key. Using the default AWS-managed key (aws/secretsmanager) is not acceptable for production workloads containing sensitive credentials.

Scope: resource β€” aws_secretsmanager_secret

Assertions: * kms_key_id attribute exists β€” Secrets Manager secret MUST be encrypted with a customer-managed KMS key (kms_key_id must be set).

Remediation: Create an aws_kms_key resource with enable_key_rotation = true and reference its ARN via kms_key_id = aws_kms_key.secrets.arn in the aws_secretsmanager_secret resource. Ensure the KMS key policy grants the Secrets Manager service principal permission to use the key for encryption and decryption.

Compliant
resource "aws_kms_key" "secrets" {
  description         = "CMK for Secrets Manager encryption"
  enable_key_rotation = true
}
resource "aws_secretsmanager_secret" "api_key" {
  name       = "prod/app/external-api-key"
  kms_key_id = aws_kms_key.secrets.arn
}
Non-Compliant
resource "aws_secretsmanager_secret" "api_key" {
  name = "prod/app/external-api-key"
  # kms_key_id not set – using default aws/secretsmanager key
  # WAF-SEC-060 violation: CMK encryption required for production secrets
}

waf-sec-060.tf.azurerm.key-vault-secret-expiration

Engine: terraform | Provider: azurerm | Automated: Yes

Azure Key Vault secrets must have an expiration date

All azurerm_key_vault_secret resources storing workload secrets must have expiration_date set to enforce rotation and lifecycle.

Scope: resource β€” azurerm_key_vault_secret

Assertions: * expiration_date attribute exists β€” Key Vault secret must have an expiration_date for lifecycle management.

Remediation: Set expiration_date on every azurerm_key_vault_secret resource and establish a rotation workflow that refreshes the secret before expiration.

Compliant
resource "azurerm_key_vault_secret" "db_password" {
  name         = "db-password"
  value        = var.db_password
  key_vault_id = azurerm_key_vault.main.id
  expiration_date = "2026-01-01T00:00:00Z"
}
Non-Compliant
resource "azurerm_key_vault_secret" "db_password" {
  name         = "db-password"
  value        = var.db_password
  key_vault_id = azurerm_key_vault.main.id
  # expiration_date not set
}

waf-sec-060.tf.google.secret-manager-exists

Engine: terraform | Provider: google | Automated: Yes

Google Secret Manager secrets must be defined for workload secrets

All workload secrets must be stored in google_secret_manager_secret resources rather than plain text or local state.

Scope: resource β€” google_secret_manager_secret

Assertions: * secret_id attribute exists β€” Workload secrets must be stored in Google Secret Manager.

Remediation: Create google_secret_manager_secret resources for all sensitive configuration values. Reference secret versions via data sources rather than storing values in Terraform state.

Compliant
resource "google_secret_manager_secret" "db_password" {
  secret_id = "db-password"
  replication {
    auto {}
  }
}
Non-Compliant
# Secret value stored in plain text or Terraform variable
# Use google_secret_manager_secret instead

waf-sec-060.tf.stackit.secret-manager-rotation

Engine: terraform | Provider: stackit | Automated: Yes

STACKIT secrets must be stored in Secret Manager and rotated

Credentials, API keys, and other secrets used by STACKIT workloads must be stored in stackit_secret_manager_secret resources and rotated regularly. Hard-coded secrets in Terraform are prohibited.

Scope: resource β€” stackit_secret_manager_secret

Assertions: * name attribute exists β€” STACKIT secrets must be stored in Secret Manager resources.

Remediation: Create stackit_secret_manager_secret resources for all sensitive values. Reference them via data sources in application configuration. Implement rotation via automation or documented process.

Compliant
resource "stackit_secret_manager_secret" "db_password" {
  project_id = var.stackit_project_id
  name       = "db-password"
  # value managed via STACKIT Secret Manager; rotation automated
}
Non-Compliant
# Database password hard-coded in Terraform or plain text.
# WAF-SEC-060 violation: secrets not managed in Secret Manager

waf-sec-060.config.ovh.ovh-identity-access

Engine: config | Provider: ovh | Automated: Yes

OVHcloud workloads must store secrets in a managed vault or secret store

A version-controlled policy document must exist at docs/security/waf-sec-060-ovh-identity-access.md and document the OVHcloud implementation of this control. The checker validates that the file exists and contains a normative requirement statement (MUST/SHALL/required/mandatory).

Scope: file β€” docs/security/waf-sec-060-ovh-identity-access.md

Assertions: * content matches pattern (?i)MUST|SHALL|required|mandatory|enforced|documented β€” Policy file docs/security/waf-sec-060-ovh-identity-access.md must contain a normative requirement statement.

Remediation: Create or update docs/security/waf-sec-060-ovh-identity-access.md. State the requirement, how it is implemented for OVHcloud, the review cadence, and the owner.

Compliant
docs/security/waf-sec-060-ovh-identity-access.md:
- The OVHcloud implementation of WAF-SEC-060 is documented.
- Implementation status and owner are recorded.
- Review cadence is defined (e.g. quarterly).
Non-Compliant
# `docs/security/waf-sec-060-ovh-identity-access.md` is missing or does not contain a normative requirement.
# WAF-SEC-060 violation: OVHcloud control is not documented

waf-sec-060.config.hcloud.hcloud-identity-access

Engine: config | Provider: hcloud | Automated: Yes

Hetzner Cloud workloads must store secrets in a managed vault or secret store

A version-controlled policy document must exist at docs/security/waf-sec-060-hcloud-identity-access.md and document the Hetzner Cloud implementation of this control. The checker validates that the file exists and contains a normative requirement statement (MUST/SHALL/required/mandatory).

Scope: file β€” docs/security/waf-sec-060-hcloud-identity-access.md

Assertions: * content matches pattern (?i)MUST|SHALL|required|mandatory|enforced|documented β€” Policy file docs/security/waf-sec-060-hcloud-identity-access.md must contain a normative requirement statement.

Remediation: Create or update docs/security/waf-sec-060-hcloud-identity-access.md. State the requirement, how it is implemented for Hetzner Cloud, the review cadence, and the owner.

Compliant
docs/security/waf-sec-060-hcloud-identity-access.md:
- The Hetzner Cloud implementation of WAF-SEC-060 is documented.
- Implementation status and owner are recorded.
- Review cadence is defined (e.g. quarterly).
Non-Compliant
# `docs/security/waf-sec-060-hcloud-identity-access.md` is missing or does not contain a normative requirement.
# WAF-SEC-060 violation: Hetzner Cloud control is not documented

Evidence

Kind Required Description

iac

Required

Terraform configuration implementing the control.

governance

Required

Policy, ADR, or standard documenting the requirement.

config

Optional

Cloud console or API output confirming runtime state.

Framework Controls

ISO 27001:2022

* A.5.17 – Authentication information * A.8.24 – Use of cryptography * A.8.5 – Secure authentication

ISO 27017

* CLD.10.1 – Cryptographic controls in cloud services

CIS Controls v8

* CIS 5.4 – Restrict administrator privileges * CIS 16.10 – Apply secure design principles

CSA STAR

* CCM CEK-01 – Encryption and Key Management Policy * CCM IAM-15 – Strong Authentication Policy

PCI DSS v4.0

* Req 3.5 – Cryptographic keys protection * Req 8.3 – Strong authentication mechanisms

SOC 2 Type II

* CC6.1 – Logical access security * C1.1 – Confidentiality

GDPR

* Art. 32 – Security of processing

NIS2

* Art. 21(2)(h) – Cryptography and credential protection

DORA

* Art. 9 – Protection and prevention

EUCS (ENISA)

* CKM-01 – Cryptographic policy * IAM-04 – Authentication credentials

BSI C5:2020

* CRY-01 – Use of cryptography * IDM-01 – Identity and access management policy * IDM-04 – Credential management

IT-Grundschutz

* ORP.4 – IdentitΓ€ts- und Berechtigungsmanagement * CON.1 – Kryptokonzept

TISAX

* Information security – Credential and key management

ANSSI SecNumCloud

* Domain – Secret and key management

BIO

* BIO – Wachtwoord- en geheimenbeheer

ENS High

* op.acc.6 – Mecanismo de autenticaciΓ³n – credenciales * mp.info.4 – Firma electrΓ³nica

UK Cyber Essentials

* CE.UAC – User access control

UK NCSC CAF

* B2.b – Device management and credential security

UK GDPR

* Art. 32 – Security of processing

NIST SP 800-53

* IA-5 – Authenticator Management * SC-12 – Cryptographic Key Establishment * SC-28 – Protection of Information at Rest

NIST CSF 2.0

* PR.AA-01 – Identities and credentials are managed

FedRAMP

* IA-5, SC-12, SC-28 (Moderate/High baseline)

HIPAA

* Β§ 164.312(a)(2)(i) – Unique user identification * Β§ 164.312(d) – Person or entity authentication

CMMC 2.0

* IA.L2-3.5.10 – Store passwords using cryptographic protections

ASD Essential 8

* E8.7 – Multi-factor authentication and credential protection

IRAP

* ISM – Cryptography and key management

CCCS PBMM

* IA-5 – Authenticator management

MAS TRM

* Ch.6 – Access control – Credential management

ISMAP

* Cryptographic key and secret management

FISC

* Technical measures – Authentication credentials