Skip to content

IAM password policies should expire passwords within 90 days or less

Passwords that never expire give attackers an unlimited window to crack or reuse stolen credentials. A 90-day maximum lifetime limits how long a compromised password stays useful, especially for IAM users who authenticate via the AWS Console. Brute-force and credential-stuffing attacks become significantly less effective when credentials rotate regularly.

This control matters most in accounts where IAM users with console access still exist. Even in organizations moving toward SSO and federation, legacy IAM users often linger. Enforcing expiration on these accounts reduces residual risk while migration completes.

Retrofit consideration

Enabling password expiration on an existing account may force password resets for all IAM console users on their next login, which can cause support tickets if not communicated in advance.

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

This control validates the aws_iam_account_password_policy resource. max_password_age must be set to 90 or lower. A value of 0 or a missing argument means passwords never expire, both of which fail. To pass, declare a single aws_iam_account_password_policy resource with max_password_age between 1 and 90. Setting max_password_age = 90 is the least restrictive passing configuration; anything above 90, or omitting the argument entirely, fails.

Common pitfalls

  • Omitting max_password_age defaults to no expiration

    Omitting max_password_age from aws_iam_account_password_policy doesn't cause an error. Terraform sends the request without that field, the API defaults to 0 (no expiration), and the control fails silently even though the resource exists.

  • Single resource per account constraint

    There can only be one aws_iam_account_password_policy per AWS account. Multiple stacks managing it will create state conflicts. Keep it in a dedicated baseline stack and use terraform import if it already exists elsewhere.

  • Federated users are not covered

    This control only applies to IAM users who sign in with a password. Users authenticating through SAML or OIDC federation bypass the IAM password policy entirely. Auditors may still require this control to be satisfied even if federation is the primary access method.

  • User disruption on retrofit

    When max_password_age is applied to an account for the first time, any IAM user whose password is already older than the configured threshold will be forced to change it at next console login. Coordinate with teams before applying.

Audit evidence

An auditor will look for the output of aws iam get-account-password-policy, confirming MaxPasswordAge is 90 or less. Config rule iam-password-policy evaluation results at COMPLIANT status provide continuous evidence. Security Hub findings for this control showing PASSED also work as audit artifacts.

For periodic reviews, a screenshot of the IAM console under Account Settings, with a timestamp, gives straightforward visual proof.

Framework-specific interpretation

GDPR: For systems processing personal data, Article 32 calls for appropriate technical measures to prevent unauthorized access. Password expiration directly addresses the scenario where stale or stolen credentials are used to reach that data.

Tool mappings

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

  • Compliance.tf Control: iam_password_policy_expire_90

  • AWS Config Managed Rule: IAM_PASSWORD_POLICY

  • Checkov Check: CKV_AWS_9

  • Powerpipe Control: aws_compliance.control.iam_password_policy_expire_90

  • Prowler Check: iam_password_policy_expires_passwords_within_90_days_or_less

  • AWS Security Hub Control: IAM.17

  • Trivy Check: AWS-0062

Last reviewed: 2026-03-09