audit-labs/audit-report
Turn audit-tools evidence packages into control-mapped, auditor-ready reports.
clone: git clone https://gitbay.org/audit-labs/audit-report.git
v0.1.0: audit_report/rulesets/aws.yaml · raw
1# Ruleset: AWS
2#
3# Evaluated against an audit-tools AWS evidence package
4# (aws_audit_<profile>_<date>/). Each rule names a CSV table, a check, and the
5# controls the signal is offered as evidence for. A "fail" means a setting is in
6# a state that does NOT support the control — an auditor still owns the verdict.
7#
8# Provenance and control-mapping rationale: see MAPPING.md. Bump `version` on any
9# change to a rule's controls, checks, or thresholds so reports stay traceable.
10name: AWS ITGC ruleset
11version: "2026.08.0"
12platform: aws
13
14rules:
15 - id: aws.iam.console-mfa
16 title: Console users have MFA enabled
17 table: iam_users
18 severity: high
19 controls: [SOC2:CC6.1, ISO:A.5.17, NIST:IA-2]
20 rationale: >
21 A user who can sign in to the console without a second factor is a single
22 stolen password away from account access. MFA is the baseline control for
23 interactive human access.
24 remediation: Enforce MFA for all IAM users with console access, or remove their console password.
25 check:
26 type: fail_rows_where
27 when:
28 all:
29 - {column: console_password, op: is_true}
30 - {column: mfa_enabled, op: is_false}
31
32 - id: aws.iam.key-rotation
33 title: Access keys are rotated within 90 days
34 table: iam_users
35 severity: medium
36 controls: [ISO:A.5.17, NIST:IA-5]
37 rationale: >
38 Long-lived access keys widen the window in which a leaked credential is
39 useful. Rotating keys bounds that exposure.
40 remediation: Rotate or delete access keys older than 90 days.
41 check:
42 type: fail_rows_where
43 when: {column: oldest_key_age_days, op: gt, value: 90}
44
45 - id: aws.root.mfa
46 title: Root account has MFA enabled
47 table: account_security
48 severity: high
49 controls: [SOC2:CC6.1, ISO:A.8.2, NIST:IA-2]
50 rationale: >
51 The root account can perform every action in the account and cannot be
52 restricted by IAM policy. MFA on root is a foundational control.
53 remediation: Enable a hardware or virtual MFA device on the root user.
54 check:
55 type: assert_row
56 require:
57 - {column: root_mfa_enabled, op: is_true}
58
59 - id: aws.root.no-access-keys
60 title: Root account has no access keys
61 table: account_security
62 severity: high
63 controls: [SOC2:CC6.1, ISO:A.8.2, NIST:AC-6]
64 rationale: >
65 Programmatic root access keys are unnecessary and dangerous — anything
66 root can do should be done through named, least-privilege identities.
67 remediation: Delete all access keys on the root user.
68 check:
69 type: assert_row
70 require:
71 - {column: root_access_keys_present, op: is_false}
72
73 - id: aws.iam.password-policy
74 title: Account password policy meets baseline strength
75 table: password_policy
76 severity: medium
77 controls: [ISO:A.5.17, NIST:IA-5]
78 rationale: >
79 A weak password policy undermines every password-based control. The
80 baseline here — length, complexity, and rotation — reflects common
81 hardening guidance.
82 remediation: Set a minimum length of 14, require symbols and numbers, and cap password age at 90 days.
83 check:
84 type: assert_row
85 require:
86 - {column: minimum_length, op: gte, value: 14}
87 - {column: require_symbols, op: is_true}
88 - {column: require_numbers, op: is_true}
89 - {column: max_age_days, op: lte, value: 90}
90
91 - id: aws.network.no-open-ssh
92 title: No security group exposes SSH to the internet
93 table: open_security_groups
94 severity: high
95 controls: [SOC2:CC6.6, ISO:A.8.20, NIST:SC-7]
96 rationale: >
97 SSH (port 22) reachable from 0.0.0.0/0 invites credential-stuffing and
98 exploitation of the host directly from the public internet.
99 remediation: Restrict inbound SSH to known CIDR ranges or a bastion, or use SSM Session Manager.
100 check:
101 type: fail_rows_where
102 when:
103 all:
104 - {column: open_to, op: equals, value: 0.0.0.0/0}
105 - {column: from_port, op: lte, value: 22}
106 - {column: to_port, op: gte, value: 22}
107
108 - id: aws.s3.no-public-access
109 title: No S3 bucket allows public access
110 table: s3_public_access
111 severity: high
112 controls: [SOC2:CC6.6, ISO:A.8.20, NIST:SC-7]
113 rationale: >
114 Publicly readable or writable buckets are a leading cause of data
115 exposure. audit-tools lists only buckets that permit public access, so any
116 row here is a finding.
117 remediation: Enable Block Public Access at the account and bucket level; remove public bucket policies and ACLs.
118 check:
119 type: fail_if_any_rows
120
121 - id: aws.cloudtrail.logging
122 title: A multi-region CloudTrail is actively logging
123 table: cloudtrail
124 severity: high
125 controls: [SOC2:CC7.2, ISO:A.8.15, NIST:AU-2]
126 rationale: >
127 Without an active trail there is no reliable record of account activity —
128 the evidence auditors and responders rely on simply does not exist.
129 remediation: Enable a multi-region CloudTrail with log file validation and confirm it is logging.
130 check:
131 type: require_any_row
132 when:
133 all:
134 - {column: is_logging, op: is_true}
135 - {column: multi_region, op: is_true}