PCI DSS v4.0.1 — Requirement 2 AWS Gap Analysis

"Apply Secure Configurations to All System Components" — read-only assessment (compare only, no remediation performed)
Generated: 2026-06-10  ·  Method: AWS CLI read-only (describe / list / get)  ·  Region focus: us-east-2 (Config & Security Hub also checked in us-east-1)  ·  Accounts: three environments (identifiers withheld)
Dev
Development environment
Stg
Staging / UAT environment
Prod
Production environment

This report compares each PCI DSS v4.0.1 Requirement 2 sub-requirement against the current state of the three AWS environments above (labelled Dev, Stg and Prod; the underlying AWS account IDs are intentionally withheld). AWS is Infrastructure-as-a-Service, so many Requirement 2 items (OS hardening inside EC2, wireless access points, SNMP on physical gear) are either managed inside the customer's instances or are not applicable to a pure cloud account. Where that is the honest answer it is stated plainly rather than forced into a match.

How to read the status labels.
MATCH AWS config evidence shows the control is met. PARTIAL Partly met / depends on architecture or in-instance config. GAP Evidence shows it is NOT met. MANUAL Cannot be proven from AWS APIs (policy / process / docs). N/A Does not apply to the AWS-managed layer.

1. Executive Summary

Counts are across the 11 assessed sub-requirements (2.1.1, 2.1.2, 2.2.1–2.2.7, 2.3.1, 2.3.2) per environment.

Dev Development

0Match
2Partial
5Gap
2Manual
2N/A

Stg Staging / UAT

0Match
4Partial
2Gap
3Manual
2N/A

Prod Production

0Match
5Partial
1Gap
3Manual
2N/A
Headline: Good across all three: root accounts have no access keys and MFA is on; no Telnet anywhere; custom VPCs with public/private subnets exist. The biggest single problem is the Dev environment, where security groups expose SSH (22), MySQL (3306) and other ports to the entire internet (0.0.0.0/0), including on the default security group attached to a database instance. Common to all three: AWS Config and Security Hub are completely disabled (no automated configuration-standard enforcement), and account-level S3 Block Public Access is not set. Stg and Prod restrict their database ingress to specific office/VPN IPs and are in materially better shape than Dev.

2. Per-Sub-Requirement Assessment

Sub-Req What PCI asks (short) Dev Stg Prod Notes / Evidence
2.1.1 Security policies & operational procedures documented, current, in use, known to staff. MANUAL MANUAL MANUAL Documentation / process control. AWS APIs cannot prove a written policy exists or is followed. Organizational evidence required — not claimed as a match.
2.1.2 Roles & responsibilities for Requirement 2 documented and assigned. MANUAL MANUAL MANUAL Process control. Cannot be evidenced from AWS APIs. Provide RACI / ownership documentation.
2.2.1 Configuration standards exist for all components, align to industry hardening baselines (CIS/NIST), updated for new vulnerabilities. GAP GAP GAP AWS Config: NOT enabled (zero configuration recorders) in us-east-2 and us-east-1, all three environments. Security Hub: NOT subscribed in any account — so no CIS AWS Foundations or PCI DSS standard is running. There is no automated mechanism enforcing or measuring a hardening baseline. (Whether a written standard exists is a separate MANUAL item.)
2.2.2 Vendor default accounts & default settings managed (defaults removed/changed before use). GAP PARTIAL PARTIAL Root: all three environments have no root access keys and root MFA enabled (good). Default security groups in use: Dev's default SGs allow MySQL 3306 from 0.0.0.0/0 (and ::/0) and one is attached to the mongodb-dev instance → GAP. Stg & Prod still use the default SG for workloads but restrict it to specific /32 IPs → PARTIAL (default SG should ideally be empty/unused). A default VPC also still exists in every environment.
2.2.3 Primary functions with different security levels isolated (don't mix public-facing and sensitive on one component). PARTIAL PARTIAL PARTIAL Custom VPCs (10.****/16) with both public and private subnets exist — segmentation is present. But the MongoDB database instances carry public IPs and sit in public subnets in all three environments, so the sensitive data tier is internet-addressable. This is an architectural judgement — evidence presented, marked PARTIAL.
2.2.4 Only necessary services, protocols, daemons enabled; unnecessary ones disabled. GAP PARTIAL PARTIAL Assessed via network surface (in-instance daemons cannot be confirmed via AWS API). Dev exposes 22, 80, 443, 3306, 8082, 9000 to 0.0.0.0/0 across launch-wizard SGs and default SGs → GAP. Stg & Prod have NO world-open ingress — DB ports restricted to specific /32 addresses → network surface is clean, but in-instance services remain unverifiable, so PARTIAL.
2.2.5 If insecure services/protocols are present, document them with business justification & extra security controls. GAP MANUAL MANUAL Dev exposes cleartext HTTP (80) and broadly-open SSH/MySQL to the internet with no evidence of documented justification → GAP. Stg/Prod show no world-exposed insecure protocols; whether any in-use insecure protocol is documented & justified is a MANUAL doc control.
2.2.6 System security parameters configured to prevent misuse. GAP GAP PARTIAL S3 account-level Block Public Access: NOT configured in any environment (NoSuchPublicAccessBlockConfiguration). EBS default encryption: Dev OFF, Stg OFF, Prod ON. IAM password policy: Dev min-length 6 (PCI needs ≥12), Stg min-length 6 with NO complexity and no expiry, Prod min-length 12 + full complexity + 90-day expiry. Prod is strong on passwords & EBS but still misses account-level S3 BPA → PARTIAL; Dev & Stg fail multiple parameters → GAP. (Bucket-level S3 BPA was not assessed.)
2.2.7 All non-console administrative access encrypted with strong cryptography. PARTIAL PARTIAL PARTIAL AWS management-plane console access is TLS by default (MATCH for the AWS layer). No Telnet (23) exposed anywhere — admin path uses SSH (encrypted). However SSM Session Manager only covers the MongoDB instance in each environment; other instances are not SSM-managed, and in-instance SSH/RDP configuration cannot be verified via API. Dev additionally exposes SSH to 0.0.0.0/0. Marked PARTIAL.
2.3.1 Wireless vendor defaults changed (keys, SNMP strings, etc.) before/at install. N/A N/A N/A Not applicable — there is no AWS-managed Wi-Fi. Applies only if the CDE includes on-prem wireless, which is out of scope for this AWS scan.
2.3.2 Wireless encryption keys rotated on personnel change / when compromised. N/A N/A N/A Not applicable to the AWS-managed layer (no wireless in AWS scope).

3. Key Gaps to Fix (most critical first)

Only the red GAP items are listed here. This report does not change anything — these are findings for your team to act on.

  1. Dev — Database / admin ports open to the entire internet. Security group launch-wizard-1 (sg-0****, attached to "DB Schema Visualizer") exposes 22, 80, 443, 3306, 8082, 9000 to 0.0.0.0/0; launch-wizard-2 (sg-0****, "Revique-Doc-Instance") exposes 22, 80, 443 to 0.0.0.0/0. World-open SSH and MySQL are a direct exposure of admin and data services. 2.2.4 / 2.2.5 / 2.2.7 · Dev
  2. Dev — Default security groups allow MySQL 3306 from 0.0.0.0/0. The default SG sg-0**** (default VPC) and sg-0**** (custom VPC, attached to mongodb-dev) both permit 3306 from the world (and IPv6 ::/0). Vendor-default security groups should be locked down and unused. 2.2.2 · Dev
  3. All environments — AWS Config and Security Hub are disabled. Zero configuration recorders in us-east-2 and us-east-1; Security Hub not subscribed in any account. There is no automated mechanism enforcing or measuring a CIS/NIST hardening baseline. 2.2.1 · Dev, Stg, Prod
  4. All environments — S3 account-level Block Public Access is not configured. get-public-access-block returns NoSuchPublicAccessBlockConfiguration for all three. Without the account-level guardrail, an individual bucket can be made public. 2.2.6 · Dev, Stg, Prod
  5. Dev & Stg — EBS default encryption is OFF. New EBS volumes are not encrypted by default (EbsEncryptionByDefault: false). Prod has it enabled. 2.2.6 · Dev, Stg
  6. Stg — Weak IAM password policy. Minimum length 6, no complexity requirements (no upper/lower/number/symbol), and no password expiry. 2.2.6 · Stg
  7. Dev — IAM password minimum length is 6 (below PCI's 12). Complexity and 90-day expiry are set, but the minimum length is too short. 2.2.6 · Dev
  8. Dev — Cleartext HTTP (80) exposed to the world without documented justification. Exposing port 80 to 0.0.0.0/0 needs either TLS offload/justification docs or removal. 2.2.5 · Dev

4. Cannot Verify From AWS (needs manual / organizational evidence)

5. Raw Evidence Appendix

Relevant read-only CLI output snippets the findings rely on. All calls were describe/list/get only (plus iam generate-credential-report, which produces a read-only report and changes no configuration). Account IDs and IAM user names have been redacted; only the environment label is shown.

Identity — aws sts get-caller-identity
# Dev  identity confirmed   (account ID redacted)
# Stg  identity confirmed   (account ID redacted)
# Prod identity confirmed   (account ID redacted)
2.2.1 — AWS Config & Security Hub (all environments, us-east-2 + us-east-1)
describe-configuration-recorders  -> ConfigurationRecorders: []   (every environment, both regions)
describe-config-rules            -> []
describe-conformance-packs       -> []
securityhub describe-hub         -> InvalidAccessException: "Account is not subscribed to AWS Security Hub"
securityhub get-enabled-standards -> InvalidAccessException (not subscribed)
2.2.2 / 2.2.6 — Root, password policy, S3 BPA, EBS encryption
# Account summary (root credentials) — all three environments
AccountAccessKeysPresent: 0      (root has NO access keys, all 3 environments)
AccountMFAEnabled: 1             (root MFA on, all 3 environments)
credential-report <root_account> -> access_key_1_active=false, mfa_active=true (all 3)

# IAM password policy
Dev  : MinLength 6,  RequireSymbols/Numbers/Upper/Lower=true,  MaxAge 90, Reuse 5
Stg  : MinLength 6,  RequireSymbols/Numbers/Upper/Lower=FALSE, ExpirePasswords=FALSE
Prod : MinLength 12, RequireSymbols/Numbers/Upper/Lower=true,  MaxAge 90, Reuse 5

# S3 account-level Block Public Access
Dev / Stg / Prod -> NoSuchPublicAccessBlockConfiguration (NOT configured)

# EBS encryption by default (us-east-2)
Dev : false      Stg : false      Prod : true
2.2.4 / 2.2.5 — Security group ingress (open-to-world & full rules)
# Dev — OPEN TO 0.0.0.0/0 (and ::/0)
sg-0**** (default, default-VPC)          tcp/3306  <- 0.0.0.0/0, ::/0    [MySQL]
sg-0**** (default, custom-VPC)  tcp/3306  <- 0.0.0.0/0          [MySQL]  (on mongodb-dev)
sg-0**** (launch-wizard-2)      tcp/80,22,443 <- 0.0.0.0/0      [HTTP,SSH]
sg-0**** (launch-wizard-1)      tcp/80,9000,22,8082,3306,443 <- 0.0.0.0/0  [HTTP,SSH,MySQL]

# Stg — NO world-open ingress; restricted to specific /32
sg-0**** (default)              tcp/3306 <- <4 specific /32 office/VPN IPs>
sg-0**** (MongoDB-Stack SG)     tcp/27017 <- <1 specific /32>
sg-4**** (default, default-VPC)          self-reference only

# Prod — NO world-open ingress; restricted to specific /32
sg-0**** (MongoDB-Stack SG)     tcp/22 <- <1 /32> ; tcp/27017 <- <3 specific /32 IPs>
sg-0**** (default, custom-VPC)  tcp/3306 <- <4 specific /32 office/VPN IPs>   (on mongodb-prod, ProxyTest)
sg-8**** (default, default-VPC)          self-reference only

# No Telnet (23) exposed in any environment.
2.2.3 — VPCs, subnets & instances (segmentation / public exposure)
# Dev
VPCs: custom 10.****/16, custom 172.****/16, default 172.****/16
Instances:
  mongodb-dev          has PUBLIC IP   public subnet (MapPublicIp=true)
  DB Schema Visualizer has PUBLIC IP   (default VPC)
  Revique-Doc-Instance has PUBLIC IP   (default VPC)

# Stg
VPCs: custom 10.****/16, default 172.****/16
Instances:
  mongodb-stg          has PUBLIC IP   public subnet (MapPublicIp=true)

# Prod
VPCs: custom 10.****/16, default 172.****/16
Instances:
  mongodb-prod         has PUBLIC IP   public subnet (MapPublicIp=true)
  ProxyTest            has PUBLIC IP   public subnet

# Note: a default VPC still exists in every environment; DB instances are publicly addressable.
2.2.7 — SSM managed instances (encrypted admin path coverage)
# ssm describe-instance-information (us-east-2)
Dev  : mongodb-dev  Online  Amazon Linux   -> 2 of 3 instances NOT in SSM
Stg  : mongodb-stg  Online  Amazon Linux   -> only instance, covered
Prod : mongodb-prod Online  Amazon Linux   -> 1 of 2 instances NOT in SSM (ProxyTest absent)