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
-
Implement the required configuration as code in Terraform or equivalent IaC.
-
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.
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"
}
}
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.
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
}
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.
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"
}
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.
resource "google_secret_manager_secret" "db_password" {
secret_id = "db-password"
replication {
auto {}
}
}
# 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.
resource "stackit_secret_manager_secret" "db_password" {
project_id = var.stackit_project_id
name = "db-password"
# value managed via STACKIT Secret Manager; rotation automated
}
# 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.
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).
# `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.
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).
# `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 |
|---|---|---|
|
Required |
Terraform configuration implementing the control. |
|
Required |
Policy, ADR, or standard documenting the requirement. |
|
Optional |
Cloud console or API output confirming runtime state. |
Related Controls
-
WAF-AGN-010 == Regulatory Mapping
| 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 |