Skip to content

IAM password policies should have strong configurations

Weak password policies let credential-stuffing and brute-force attacks succeed at scale. A reuse prevention count of 24 blocks users from cycling through a small set of passwords to get back to a favorite, which is the most common workaround when reuse limits are low.

Without enforcing complexity, length, and rotation at the account level, IAM users default to AWS minimums: 8 characters, no character-type mandate, no expiration, and zero reuse memory. A single compromised console password with no rotation requirement can persist for years.

Retrofit consideration

Existing IAM users will be required to comply on their next password change. If max_password_age is newly introduced, users who have never rotated may be locked out immediately on next login.

Implementation

Choose the approach that matches how you manage Terraform.

Use AWS provider resources directly. See docs for the resources involved: aws_iam_account_password_policy.

resource "aws_iam_account_password_policy" "this" {
  max_password_age             = 90
  minimum_password_length      = 14
  password_reuse_prevention    = 24
  require_lowercase_characters = true
  require_numbers              = true
  require_symbols              = true
  require_uppercase_characters = true
}

What this control checks

The policy engine evaluates the aws_iam_account_password_policy resource. A configuration passes when the following arguments are set:

  • password_reuse_prevention must equal 24 (the AWS maximum). Any value below 24, or omitting the argument entirely, fails.
  • minimum_password_length should be at least 14.
  • require_uppercase_characters must be true.
  • require_lowercase_characters must be true.
  • require_numbers must be true.
  • require_symbols must be true.
  • max_password_age should be set (commonly 90 days or fewer) to enforce periodic rotation.
  • allow_users_to_change_password must be true so users can self-service rotations.

Omitting aws_iam_account_password_policy entirely leaves the account on AWS defaults, which fail every check. Each AWS account has exactly one password policy, so only a single resource block is needed.

Common pitfalls

  • Default password policy has no reuse prevention

    No aws_iam_account_password_policy resource means AWS runs on built-in defaults: 8-character minimum, no complexity, no expiration, and password_reuse_prevention of 0. The control fails silently because there is no resource to evaluate.

  • password_reuse_prevention set below 24

    Older configurations commonly set password_reuse_prevention = 12. This control requires exactly 24. Any value from 1 to 23 fails, and there is no partial credit for being close.

  • max_password_age unset negates reuse prevention benefit

    Get this wrong and reuse prevention becomes theater: if users are never forced to rotate, a prevention count of 24 has no practical effect on someone who keeps the same password indefinitely. Some policy checks treat a missing max_password_age as a failure in its own right.

  • Terraform import required for existing policies

    A password policy configured through the console already exists in AWS. Running terraform apply on a new aws_iam_account_password_policy resource will fail with a conflict. Run terraform import aws_iam_account_password_policy.strict iam-account-password-policy before applying.

  • SSO users bypass IAM password policy

    This policy only governs IAM users with console passwords. Users authenticating through IAM Identity Center (SSO) or federated identity providers are not subject to it. Auditors may still require it as a defense-in-depth measure for any remaining IAM users.

Audit evidence

Auditors expect output from aws iam get-account-password-policy showing PasswordReusePrevention equal to 24, MinimumPasswordLength of 14 or more, all four Require* flags set to true, and a defined MaxPasswordAge. The AWS Config rule iam-password-policy showing COMPLIANT works as continuous evidence.

IAM console screenshots under Account Settings confirming each parameter, combined with historical Config compliance timelines, demonstrate sustained enforcement rather than a point-in-time fix.

Framework-specific interpretation

SOC 2: A password policy with 24-generation reuse prevention is evidence that the entity actively manages credential controls, which is what CC6.1 expects when evaluating logical access restrictions.

PCI DSS v4.0: Requirement 8.3.7 prohibits reuse of any of the last four passwords. Setting prevention to 24 exceeds that minimum by a wide margin, which examiners view as stronger evidence of intent than the bare minimum.

HIPAA Omnibus Rule 2013: 45 CFR 164.312(a) and 164.312(d) require covered entities to implement technical safeguards for access control and person or entity authentication. An IAM password policy with reuse prevention and complexity rules is a direct mechanism for meeting both requirements.

GDPR: Unauthorized access to systems processing personal data is a security incident under Article 32. Password reuse prevention and complexity requirements reduce that exposure by limiting the viability of credential-based attacks against IAM console users.

NIST Cybersecurity Framework v2.0: PR.AA (Identity Management, Authentication, and Access Control) asks for credentials to be managed throughout their lifecycle. Complexity rules, reuse limits, and expiration settings are what that lifecycle management looks like in practice for IAM console users.

FedRAMP Moderate Baseline Rev 4: IA-5 (Authenticator Management) governs password complexity, rotation, and reuse restrictions. At the Moderate baseline, FedRAMP explicitly requires preventing reuse of the last 24 passwords, so password_reuse_prevention = 24 satisfies that requirement directly.

Tool mappings

Use these identifiers to cross-reference this control across tools, reports, and evidence.

  • Compliance.tf Control: iam_account_password_policy_strong_min_reuse_24

  • AWS Config Managed Rule: IAM_PASSWORD_POLICY

  • Checkov Checks: CKV_AWS_10, CKV_AWS_11, CKV_AWS_12, CKV_AWS_13, CKV_AWS_14, CKV_AWS_15, CKV_AWS_9

  • Powerpipe Control: aws_compliance.control.iam_account_password_policy_strong_min_reuse_24

  • Prowler Checks: iam_password_policy_expires_passwords_within_90_days_or_less, iam_password_policy_lowercase, iam_password_policy_minimum_length_14, iam_password_policy_number, iam_password_policy_reuse_24, iam_password_policy_symbol, iam_password_policy_uppercase

  • AWS Security Hub Controls: IAM.10, IAM.11, IAM.13, IAM.14, IAM.15, IAM.16, IAM.17, IAM.7

  • Trivy Checks: AWS-0056, AWS-0062, AWS-0063

Last reviewed: 2026-03-09