WAF-SEC-010 β Identity & Access Management Baseline
Description
All AWS accounts MUST enforce MFA for all IAM users with console access. Root account usage MUST be prohibited for day-to-day operations. IAM password policy MUST meet minimum security requirements: minimum length of 14 characters, complexity requirements, password reuse prevention of at least 5 prior passwords, and maximum password age of 90 days. Service accounts MUST use IAM roles with temporary credentials rather than long-lived access keys wherever possible.
Rationale
| Risk | Description |
|---|---|
Risk |
Accounts without MFA can be compromised through stolen passwords or phishing. |
Risk |
Permanent root or user access keys enable undetected persistence and data exfiltration. |
Requirements
-
All AWS accounts MUST enforce MFA for all IAM users with console access.
-
Root account usage MUST be prohibited for day-to-day operations.
-
IAM password policy MUST meet minimum security requirements: minimum length of 14 characters, complexity requirements, password reuse prevention of at least 5 prior passwords, and maximum password age of 90 days.
-
Service accounts MUST use IAM roles with temporary credentials rather than long-lived access keys wherever possible.
Implementation Guidance
-
Document the requirement in a version-controlled policy or standard.
-
Assign ownership and establish a review cadence (e.g., quarterly).
-
Implement the required configuration as code in Terraform or equivalent IaC.
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-010.tf.aws.iam-password-policy-mfa
Engine: terraform | Provider: aws | Automated: Yes
AWS IAM account password policy must meet minimum security requirements
The aws_iam_account_password_policy resource must enforce a minimum password length of 14, all character class requirements, a minimum of 5 passwords in reuse prevention history, and a maximum password age of 90 days.
Scope: resource β aws_iam_account_password_policy
Assertions:
* minimum_password_length greater than or equal 14 β IAM password policy must require a minimum of 14 characters.
* require_uppercase_characters is true β IAM password policy must require uppercase characters.
* require_lowercase_characters is true β IAM password policy must require lowercase characters.
* require_numbers is true β IAM password policy must require numbers.
* require_symbols is true β IAM password policy must require symbols.
* password_reuse_prevention greater than or equal 5 β IAM password policy must prevent reuse of at least 5 prior passwords.
* max_password_age less than or equal 90 β IAM password policy must set maximum password age to 90 days or less.
Remediation: Define an aws_iam_account_password_policy resource with all required attributes set. Ensure minimum_password_length >= 14, all require_* flags are true, password_reuse_prevention >= 5, and max_password_age ⇐ 90.
resource "aws_iam_account_password_policy" "strict" {
minimum_password_length = 14
require_uppercase_characters = true
require_lowercase_characters = true
require_numbers = true
require_symbols = true
allow_users_to_change_password = true
max_password_age = 90
password_reuse_prevention = 5
hard_expiry = false
}
resource "aws_iam_account_password_policy" "weak" {
minimum_password_length = 8
require_uppercase_characters = false
require_symbols = false
# Missing password_reuse_prevention and max_password_age
}
waf-sec-010.tf.aws.no-root-access-keys
Engine: terraform | Provider: aws | Automated: Yes
Root account must not have active access keys
The AWS root account must not have active programmatic access keys. This cannot be fully checked in Terraform state but must be validated via AWS IAM credential report or Security Hub control IAM.4.
Scope: resource β aws_iam_user
Assertions:
* name not equals root β Root account must not be managed as a regular IAM user resource. Remove root access keys via AWS Console.
Remediation: Navigate to AWS IAM > Security Credentials for the root account and delete all access keys. Enable MFA on the root account. Restrict root account usage to only tasks that absolutely require it (e.g., account closure, enabling MFA for the first time).
# Root access keys are removed via AWS Console β not representable in Terraform.
# Verify with: aws iam get-account-summary | grep AccountAccessKeysPresent
# Expected: "AccountAccessKeysPresent": 0
# Root account has active access keys visible in AWS IAM > Security Credentials.
# aws iam get-account-summary output shows "AccountAccessKeysPresent": 1
waf-sec-010.tf.azurerm.conditional-access-mfa
Engine: terraform | Provider: azurerm | Automated: Yes
Azure AD Conditional Access must require MFA for privileged directory roles
An azuread_conditional_access_policy resource must target privileged Entra ID directory roles and require multi-factor authentication via grant_controls.
Scope: resource β azuread_conditional_access_policy
Assertions:
* state equals enabled β Conditional Access policy must be enabled.
* grant_controls attribute exists β Conditional Access policy must define grant_controls requiring MFA.
Remediation: Create an azuread_conditional_access_policy that includes privileged directory roles (e.g., Global Administrator, Privileged Role Administrator) and sets grant_controls built_in_controls to "mfa". Keep the policy state set to "enabled".
resource "azuread_conditional_access_policy" "privileged_mfa" {
display_name = "MFA for privileged roles"
state = "enabled"
conditions {
users {
included_roles = [
"62e90394-69f5-4237-9190-012177145e10",
"e8611ab8-c189-46df-93df-1fe90f8e42a1",
]
}
applications {
included_applications = ["All"]
}
}
grant_controls {
operator = "OR"
built_in_controls = ["mfa"]
}
}
# No azuread_conditional_access_policy requires MFA for privileged directory roles.
# WAF-SEC-010 violation: privileged Entra ID accounts lack mandatory MFA
waf-sec-010.tf.google.project-owner-binding-mfa-ready
Engine: terraform | Provider: google | Automated: Yes
GCP project Owner bindings must be limited and coupled with documented MFA enforcement
GCP does not represent MFA policy directly in Terraform, but IAM policy bindings for project owners must be explicitly listed and limited to a small set of principals. A guardrail google_organization_policy can restrict domain sharing, and identities must come from a workspace/Cloud Identity tenant where 2-Step Verification is enforced.
Scope: resource β google_project_iam_policy, google_project_iam_binding, google_project_iam_member
Assertions:
* role not equals roles/owner β GCP project-level Owner role should not be assigned via Terraform; prefer fine-grained roles.
* members attribute exists β IAM binding must enumerate members explicitly so ownership is auditable.
Remediation: Limit google_project_iam_binding and google_project_iam_member resources using the Owner role (roles/owner) to a small whitelist. Enforce 2-Step Verification at the Cloud Identity / Workspace level. Document the exception and review process.
data "google_iam_policy" "project" {
binding {
role = "roles/owner"
members = [
"user:admin@example.com",
]
}
}
resource "google_project_iam_policy" "policy" {
project = var.project_id
policy_data = data.google_iam_policy.project.policy_data
}
# Enforced in Workspace Admin console:
# Security > Authentication > 2-Step Verification > Enforcement > ON
resource "google_project_iam_binding" "owner" {
project = var.project_id
role = "roles/owner"
members = [
"user:anyone@example.com",
"serviceAccount:sa@example.iam.gserviceaccount.com",
]
}
waf-sec-010.tf.stackit.organization-owner-limit
Engine: terraform | Provider: stackit | Automated: Yes
STACKIT organization and project owners must be limited and documented
STACKIT Owner and Organization Owner roles grant full administrative access. These bindings must be explicitly declared in Terraform and restricted to a small set of principals. MFA is enforced at STACKIT console level and reviewed via quarterly access review.
Scope: resource β stackit_authorization_grant, stackit_resourcemanager_project_membership
Assertions:
* role not in ['Owner', 'Organization Owner'] β STACKIT Owner/Organization Owner role must not be assigned to broad groups.
* subject not matches pattern ^group: β STACKIT owner grants must target individual users, not generic groups.
Remediation: Limit stackit_resourcemanager_project_membership and stackit_authorization_grant resources that assign Owner or Organization Owner roles. Maintain a version-controlled allowlist and review it quarterly.
resource "stackit_authorization_grant" "org_owner" {
resource_id = var.stackit_organization_id
subject = "user:admin@example.com"
role = "Organization Owner"
}
# MFA is mandatory in STACKIT IAM settings for console users.
# Review documented in docs/security/access-reviews.md
resource "stackit_authorization_grant" "org_owner" {
resource_id = var.stackit_organization_id
subject = "group:all-employees@example.com"
role = "Organization Owner"
}
waf-sec-010.tf.ovh.account-mfa-via-policy
Engine: terraform | Provider: ovh | Automated: Yes
OVHcloud IAM policy must enforce MFA for sensitive operations
OVHcloud IAM policies can require MFA for sensitive actions (e.g., managing payment, identity, or critical services). Terraform ovh_me_identity_policy resources must include an MFA condition for actions affecting account security.
Scope: resource β ovh_me_identity_policy
Assertions:
* identities attribute exists β OVHcloud identity policy must enumerate identities explicitly.
* rules attribute exists β OVHcloud identity policy must define rules.
Remediation: Create an OVHcloud IAM policy with a condition requiring MFA for critical actions. Document the policy and the list of protected actions in a version-controlled standard.
resource "ovh_me_identity_policy" "sensitive_mfa" {
name = "sensitive-ops-mfa"
identities = [
"user:admin@example.com",
]
rules {
action = "account:.*"
effect = "allow"
resources {
resource {
id = "*"
type = "account"
label = "*"
}
}
}
rules {
action = ".*"
effect = "deny"
resources { resource { id = "*"; type = "*"; label = "*" } }
}
# MFA is required by an organization-wide setting documented in docs/security/ovh-iam.md
}
# No OVHcloud IAM policy requires MFA for sensitive account actions.
# MFA is not documented as enforced in the OVHcloud Control Panel.
waf-sec-010.tf.hcloud.console-mfa-ready
Engine: terraform | Provider: hcloud | Automated: Yes
Hetzner Cloud project members must be individual users with MFA documented
Hetzner Cloud projects do not expose MFA state in Terraform, but project memberships must target individual users (not robots) and be limited to required roles. MFA is enforced in the Hetzner Cloud Console and confirmed by quarterly access review.
Scope: resource β hcloud_project_membership
Assertions:
* user_email not matches pattern ^shared-.|.@.*-shared\. β Hetzner Cloud project membership must not use shared mailboxes.
* role not equals admin β Hetzner Cloud project membership should use the minimum role; avoid 'admin' where possible.
Remediation: Declare hcloud_project_membership resources only for named user accounts with minimum required roles. Disable or remove inactive members. Document MFA enablement and review cadence.
resource "hcloud_project" "prod" {
name = "production"
description = "Production workloads"
}
resource "hcloud_project_membership" "admin" {
project_id = hcloud_project.prod.id
user_email = "admin@example.com"
role = "admin"
}
# MFA enabled for all project members via Hetzner Cloud Console.
# Quarterly review recorded in docs/security/access-reviews.md
resource "hcloud_project_membership" "admin" {
project_id = hcloud_project.prod.id
user_email = "shared-inbox@example.com"
role = "admin"
}
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.8.2 β Privileged access rights * A.8.5 β Secure authentication * A.5.17 β Authentication information * A.5.15 β Access control |
ISO 27017 |
* CLD.9.5 β Segregation in virtual computing environments |
CIS Controls v8 |
* CIS 5 β Account Management * CIS 6 β Access Control Management |
CSA STAR |
* CCM IAM-01 β Identity and Access Management Policy * CCM IAM-02 β Strong Password Policy and Procedures |
PCI DSS v4.0 |
* Req 7 β Restrict access by business need to know * Req 8 β Identify and authenticate access |
SOC 2 Type II |
* CC6.1 β Logical and physical access controls * CC6.2 β Provisioning and removal of access * CC6.3 β Authentication mechanisms |
GDPR |
* Art. 32 β Security of processing * Art. 5(1)(f) β Integrity and confidentiality |
NIS2 |
* Art. 21(2)(i) β Human resources security and access control |
DORA |
* Art. 9 β Protection and prevention |
EUCS (ENISA) |
* IAM-01 β Identity and access management * IAM-02 β Authentication controls |
BSI C5:2020 |
* IDM-01 β Identity and access management policy * IDM-02 β Authentication of users * IDM-09 β Privileged access rights |
IT-Grundschutz |
* ORP.4 β IdentitΓ€ts- und Berechtigungsmanagement |
TISAX |
* Information security β Identity and access management requirements |
ANSSI SecNumCloud |
* Domain β Identity and access management |
BIO |
* BIO β Logische toegangsbeveiliging (logical access control) |
ENS High |
* op.acc.5 β Mecanismo de autenticaciΓ³n * op.acc.7 β GestiΓ³n de privilegios |
UK Cyber Essentials |
* CE.UAC β User access control |
UK NCSC CAF |
* B2 β Identity and access control |
UK GDPR |
* Art. 32 β Security of processing |
NIST SP 800-53 |
* AC-2 β Account Management * IA-2 β Identification and Authentication * IA-5 β Authenticator Management |
NIST CSF 2.0 |
* PR.AA-01 β Identities and credentials are managed * PR.AA-03 β Users, services and hardware are authenticated |
FedRAMP |
* AC-2, IA-2, IA-5 (Moderate/High baseline) |
CMMC 2.0 |
* AC.L2-3.1.1 β Limit system access to authorized users * IA.L2-3.5.3 β Multifactor authentication |
ASD Essential 8 |
* E8.5 β Restrict administrative privileges * E8.7 β Multi-factor authentication |
IRAP |
* ISM β Identification and authentication |
CCCS PBMM |
* AC-2, IA-2, IA-5 β Account and authenticator management |
MAS TRM |
* Ch.6 β Access control |
ISMAP |
* Identity and access management controls |
FISC |
* Technical measures β User authentication and access control |