Audit Readiness
What auditors actually do — not a theory exercise, but what happens in the room.
Type I vs. Type II — What You're Proving
| SOC 2 Type I | SOC 2 Type II | |
|---|---|---|
| What it proves | Controls are designed and in place at a point in time | Controls operated effectively over a period (typically 6–12 months) |
| Audit duration | 2–6 weeks of fieldwork | 3–6 months of observation period + fieldwork |
| Evidence | Configuration screenshots, policy docs, architecture diagrams | Logs, ticket history, access review records, alert response records |
| When to pursue | Fast path for new customers; first-time SOC 2 | Required for enterprise procurement; higher trust signal |
| Cost (typical) | $15,000–$30,000 | $25,000–$60,000 |
Start with Type I to clear procurement blockers quickly. Begin the Type II observation period immediately after — overlap is valid.
What Happens During Fieldwork
Day 1–2: Kickoff and population requests
The auditor sends a population request — a list of everything they want to see. Typical items:
- List of all AWS accounts in scope
- List of all employees with AWS access (as of audit date)
- List of all employees who joined or left during the period
- Incident log for the period
- Access review records for the period
- List of all third-party vendors with access to customer data
Have these ready before Day 1. Scrambling to gather populations signals poor control maturity.
Day 3–10: Evidence review and sampling
Auditors sample from your populations. If you had 200 employees, they might test 25. If you had 12 incidents, they test all of them. For each sample:
- They ask for the original evidence artifact (screenshot, log export, ticket)
- They verify it matches the control description in your policy documents
- They look for exceptions — any sample where the control was not followed
The evidence must exist at the time the control was supposed to operate. You cannot go back and create it after the fact. Auditors check document creation dates and git history.
Day 11–15: Walkthroughs
Auditors schedule 30–60 minute calls with the people who operate each control:
| Control owner | What they're asked |
|---|---|
| Security engineer | "Walk me through what happens when GuardDuty fires a HIGH finding" |
| SRE/DevOps | "Show me how a new engineer gets access to AWS" |
| Engineering manager | "How do you verify an engineer's access is removed when they leave?" |
| CISO/Security lead | "Walk me through the last incident from alert to post-incident review" |
Prepare your team. People who actually do the work answer — not the person who wrote the policy. Auditors will probe: "What if that person is on vacation?" "Who reviews it?" "Where is that decision documented?"
Final: Management representation letter
Before issuing the report, auditors ask management to sign a letter confirming no undisclosed incidents, no material changes, and that evidence provided is accurate. This is a legal document.
The 10 Most Common SOC 2 Findings on AWS
These are the issues that generate the most findings in practice. Fix these before scheduling your audit.
1. IAM users without MFA (CC6.1)
The credential report will show it. Auditors always pull the credential report. Even one user without MFA on an account in scope is a finding.
Fix: Enable the mfa-enabled-for-iam-console-access Config rule and enforce the MFA-deny IAM policy from the IAM page.
2. Access keys older than 90 days (CC6.2)
The credential report shows access_key_1_last_rotated. Anything over 90 days is flagged. Auditors calculate the age from the rotation date to the last day of the audit period.
Fix: Set the access-keys-rotated Config rule and run the key audit script before the audit window opens.
3. Terminated employee still has AWS access (CC6.3)
Auditors cross-reference your HR termination list with IAM Identity Center assignments or IAM users. If a terminated employee still appears with active access after their last day, it's a finding — even if they never logged in.
Fix: Automate deprovisioning via SCIM. If manual, run a deprovisioning check on every offboarding ticket before closing it.
4. GuardDuty findings with no documented response (CC7.3)
HIGH and CRITICAL GuardDuty findings must have evidence of investigation and resolution. If a finding sat in the console unacknowledged for weeks, auditors treat it as evidence the monitoring process is not operating effectively.
Fix: Any finding at severity ≥ 7 must have a corresponding ticket. The ticket must show: who investigated, what they found, what action was taken. Archive the ticket for 3 years.
5. No evidence of incident response testing (CC7.4)
Having a runbook is not enough. Auditors ask: "When did you last test this?" If you can't point to a tabletop exercise or a live incident with a post-incident review in the past 12 months, this is a finding.
Fix: Run an annual tabletop exercise. Document it. Retain the agenda, attendees, and outcomes.
6. CloudTrail not covering all regions (CC7.2)
A single-region trail misses API activity in other regions. Auditors check IsMultiRegionTrail: false and ask about workloads in other regions.
Fix: Use a multi-region trail. Verify with aws cloudtrail describe-trails --include-shadow-trails.
7. Overly permissive IAM policies (CC6.1)
Auditors sample 10–20 IAM policies. Action: "*" or Resource: "*" on non-admin roles is an immediate finding. Inline policies on users are also flagged.
Fix: Run IAM Access Analyzer before the audit. Remediate any policy with * on sensitive resources.
8. No quarterly access review records (CC6.3)
SOC 2 requires evidence that access is reviewed periodically. "We informally review access" is not evidence. The review must be documented: who reviewed it, when, and what was changed as a result.
Fix: Export the IAM credential report quarterly. Put the review in a ticketing system. Retain it.
9. S3 buckets without encryption or public access block (CC6.1, CC6.7)
If any S3 bucket in scope has ServerSideEncryptionConfigurationNotFound or BlockPublicAcls: false, it's a finding — even if the bucket contains no sensitive data. Auditors look at the configuration, not the contents.
Fix: Enable account-level public access block and default encryption. Run the Config rules s3-bucket-server-side-encryption-enabled and s3-bucket-public-access-prohibited.
10. Vendor without a signed BAA or security review (CC9.2)
SOC 2 CC9.2 requires vendor risk management. If you use third-party services that process customer data (Datadog, Sentry, PagerDuty, Slack, etc.) and have no record of reviewing their security posture, it's a finding.
Fix: Maintain a vendor list. For each vendor with access to customer data: note their SOC 2 status, review date, and whether a DPA/BAA is in place.
Evidence Package Structure
Organize evidence before the audit starts. A well-structured package signals maturity and makes fieldwork faster.
soc2-evidence-2024/
├── README.md ← index of every artifact + what control it covers
│
├── CC6-access-control/
│ ├── iam-credential-report-2024-09-30.csv
│ ├── mfa-enforcement-policy.json
│ ├── password-policy.json
│ ├── access-review-Q1-2024.pdf
│ ├── access-review-Q2-2024.pdf
│ ├── access-review-Q3-2024.pdf
│ ├── offboarding-tickets/
│ │ ├── ENG-1234-jane-smith-offboard.pdf
│ │ └── ENG-1456-john-doe-offboard.pdf
│ └── identity-center-assignments-export.csv
│
├── CC7-monitoring/
│ ├── cloudtrail-trail-config.json
│ ├── cloudtrail-log-validation-status.json
│ ├── guardduty-detector-config.json
│ ├── guardduty-findings-resolved-2024.csv
│ ├── security-hub-summary-report.pdf
│ ├── config-rule-compliance-2024-09-30.csv
│ └── cloudwatch-alarms-config.json
│
├── CC6-encryption/
│ ├── kms-key-list.json
│ ├── kms-rotation-status.json
│ ├── s3-encryption-config.json
│ ├── ebs-encryption-default.json
│ └── rds-encryption-status.json
│
├── CC6-network/
│ ├── vpc-config.json
│ ├── security-group-rules.json
│ ├── waf-web-acl.json
│ └── alb-tls-policy.json
│
├── CC7-incident-response/
│ ├── incident-response-policy-v2.3.pdf
│ ├── incident-runbook-v1.1.md
│ ├── tabletop-exercise-2024-03-15.pdf
│ ├── incidents/
│ │ ├── INC-2024-001-post-incident-review.pdf
│ │ └── INC-2024-002-post-incident-review.pdf
│ └── guardduty-finding-responses/
│ ├── finding-abc123-ticket-ENG-2001.pdf
│ └── finding-def456-ticket-ENG-2089.pdf
│
├── CC9-vendor-management/
│ ├── vendor-inventory-2024.xlsx
│ └── vendor-soc2-reports/
│ ├── aws-soc2-type2-2023.pdf ← from AWS Artifact
│ ├── datadog-soc2-2023.pdf
│ └── pagerduty-soc2-2023.pdf
│
└── policies/
├── information-security-policy-v3.0.pdf
├── access-control-policy-v2.1.pdf
├── incident-response-policy-v2.3.pdf
├── change-management-policy-v1.4.pdf
└── vendor-management-policy-v1.2.pdf
Version-control your policies. Auditors ask "has this policy changed during the period?" If you can't show a version history (Git, Google Docs revision history, Confluence page history), it's a gap.
Evidence Collection Script
Run this before the audit to bulk-export AWS configuration evidence:
#!/bin/bash
# export-soc2-evidence.sh
# Run from a role with SecurityAudit managed policy attached
ACCOUNT=$(aws sts get-caller-identity --query Account --output text)
REGION=$(aws configure get region)
DATE=$(date +%Y-%m-%d)
OUT="soc2-evidence-${DATE}"
mkdir -p "$OUT"/{iam,cloudtrail,guardduty,config,network,encryption,securityhub}
echo "[1/9] IAM credential report..."
aws iam generate-credential-report > /dev/null 2>&1
sleep 5
aws iam get-credential-report --query Content --output text | base64 -d \
> "$OUT/iam/credential-report-${DATE}.csv"
echo "[2/9] IAM password policy..."
aws iam get-account-password-policy > "$OUT/iam/password-policy.json"
echo "[3/9] Root account summary..."
aws iam get-account-summary > "$OUT/iam/account-summary.json"
echo "[4/9] CloudTrail configuration..."
aws cloudtrail describe-trails --include-shadow-trails > "$OUT/cloudtrail/trails.json"
aws cloudtrail get-trail-status --name org-trail > "$OUT/cloudtrail/trail-status.json" 2>/dev/null
echo "[5/9] GuardDuty detector config..."
DETECTOR=$(aws guardduty list-detectors --query 'DetectorIds[0]' --output text)
aws guardduty get-detector --detector-id "$DETECTOR" > "$OUT/guardduty/detector.json"
echo "[6/9] Config rule compliance..."
aws configservice describe-compliance-by-config-rule \
--query 'ComplianceByConfigRules[*].[ConfigRuleName,Compliance.ComplianceType]' \
--output table > "$OUT/config/rule-compliance-${DATE}.txt"
echo "[7/9] Security group audit (SSH/RDP open)..."
aws ec2 describe-security-groups \
--filters "Name=ip-permission.from-port,Values=22" "Name=ip-permission.cidr,Values=0.0.0.0/0" \
--query 'SecurityGroups[*].[GroupId,GroupName]' --output table \
> "$OUT/network/open-ssh-security-groups.txt"
echo "[8/9] KMS key rotation status..."
aws kms list-keys --query 'Keys[*].KeyId' --output text | tr '\t' '\n' | while read KEY; do
STATUS=$(aws kms get-key-rotation-status --key-id "$KEY" --query 'KeyRotationEnabled' --output text 2>/dev/null)
echo "$KEY: $STATUS"
done > "$OUT/encryption/kms-rotation-status.txt"
echo "[9/9] S3 public access block (account level)..."
aws s3control get-public-access-block --account-id "$ACCOUNT" \
> "$OUT/encryption/s3-public-access-block.json"
echo ""
echo "Evidence exported to: $OUT/"
echo "Account: $ACCOUNT | Region: $REGION | Date: $DATE"
Auditor Walkthrough Questions — Prepare Your Team
These are representative questions auditors ask in walkthroughs. Practice answering them before the audit.
Access control:
- "Walk me through how a new engineer gets access to the production AWS account."
- "What happens to that access when they move to a different team?"
- "How do you know they don't still have access to the old team's resources?"
- "Show me where the quarterly access review is documented."
Monitoring:
- "Walk me through what happens when GuardDuty fires a HIGH severity finding at 2am."
- "Who gets paged? How do you know they acknowledged it?"
- "Show me the last HIGH finding and the ticket that was opened for it."
- "If CloudTrail stopped logging right now, how long before someone noticed?"
Incident response:
- "Walk me through the last security incident from detection to post-incident review."
- "Where is the post-incident review document?"
- "What action items came out of it? Are they closed?"
- "When did you last run a tabletop exercise? Show me the documentation."
Change management:
- "How do code changes get to production?"
- "Is there a change that went to production without a code review in the past 6 months?"
- "How do infrastructure changes get approved?"
Vendor management:
- "Which third-party services have access to customer data?"
- "Do you have their SOC 2 reports? When did you last review them?"
Compensating Controls
Sometimes a control cannot be implemented as described — legacy systems, technical constraints, cost. Auditors accept compensating controls when properly documented.
| Primary control | Example constraint | Compensating control |
|---|---|---|
| Encrypt existing RDS instance | Encryption requires recreation; downtime window not feasible | Network isolation (private subnet, SG restricted to app only) + encrypted backups + WAF + enhanced monitoring |
| MFA for all IAM users | Legacy CI/CD service account cannot use MFA | Key rotation every 30 days + IP allowlist + CloudTrail alert on any non-CI usage |
| 90-day access key rotation | Vendor integration with no key rotation support | Read-only policy + IP restriction + quarterly manual review with documented sign-off |
Document the constraint, the compensating control, and who approved it. Auditors want to see that you identified the gap, reasoned about risk, and implemented an alternative — not that you ignored it.
90-Day Pre-Audit Timeline
| Weeks before audit | Action |
|---|---|
| 12 | Confirm audit scope (which accounts, which TSC criteria). Assign control owners. |
| 10 | Run evidence collection script. Identify gaps in the evidence. |
| 8 | Remediate top findings (MFA gaps, key rotation, unencrypted resources). |
| 6 | Run tabletop exercise. Document it. |
| 4 | Finalize evidence package. Version-control all policy documents. |
| 2 | Walkthrough practice with control owners. Brief the team on what to expect. |
| 1 | Send completed evidence package to auditor. Confirm fieldwork schedule. |
| 0 | Audit begins. Have a single point of contact for all auditor requests. |
Official reference: AWS Audit Manager SOC 2 Framework → · AWS Artifact (SOC reports) →