Skip to main content
selectAWSlast verified 2026-07-29
Servicesiam
CredentialsAWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
Permissionsiam:GetAccountPasswordPolicy

IAM account password policy vs CIS benchmark

Assesses the account's IAM password policy against the CIS AWS Foundations Benchmark password controls in a single query: each control returns a PASS/FAIL verdict with the raw configured values alongside as audit evidence. IAM is global, so this is one query per account, no fan-out.

Query

SELECT
minimum_password_length,
password_reuse_prevention,
require_uppercase_characters,
require_lowercase_characters,
require_symbols,
require_numbers,
expire_passwords,
max_password_age,
allow_users_to_change_password,
hard_expiry,
CASE WHEN minimum_password_length >= 14 THEN 'PASS' ELSE 'FAIL' END as cis_minimum_length_14,
CASE WHEN password_reuse_prevention >= 24 THEN 'PASS' ELSE 'FAIL' END as cis_reuse_prevention_24,
CASE WHEN require_uppercase_characters IN (1, 'true') THEN 'PASS' ELSE 'FAIL' END as cis_require_uppercase,
CASE WHEN require_lowercase_characters IN (1, 'true') THEN 'PASS' ELSE 'FAIL' END as cis_require_lowercase,
CASE WHEN require_symbols IN (1, 'true') THEN 'PASS' ELSE 'FAIL' END as cis_require_symbols,
CASE WHEN require_numbers IN (1, 'true') THEN 'PASS' ELSE 'FAIL' END as cis_require_numbers,
CASE WHEN expire_passwords IN (1, 'true') AND max_password_age <= 90 THEN 'PASS' ELSE 'FAIL' END as cis_max_age_90
FROM aws.iam.account_password_policies
WHERE region = 'us-east-1';

Notes

An empty result means the account has no password policy at all (the API returns NoSuchEntity): treat every control as failing, and creating a policy is the first remediation. Current benchmark versions (v1.4.0 through v3.0) retain two password controls - the 14-character minimum (control 1.8) and 24-password reuse prevention (1.9); the complexity and 90-day expiry checks come from CIS v1.2.0 and remain common organizational baselines, so failing them is a finding to report, not necessarily a current-benchmark violation. A null in password_reuse_prevention or max_password_age means the setting is not configured and its check correctly fails. IAM is global: region = 'us-east-1' is endpoint routing, never a parameter. Boolean policy fields are stored as 1/0 on the default SQLite backend; the IN (1, 'true') predicate keeps the checks robust across backends.

Related queries

  • IAM users enumeration - Enumerates IAM users in the account; IAM is global and always served from us-east-1, so the query takes no parameters.