AWS Connector
Complete reference for collecting SOC 2 evidence from AWS using the evidence SDK.
Overview
Controls supported:
- CC6.1 - Logical Access Controls (IAM password policy)
- CC7.2 - Change Management (CloudTrail audit logging, log retention)
What it collects:
- IAM account password policy
- CloudTrail trail status and configuration
- CloudWatch Logs log group retention settings
What it does NOT collect:
- ❌ EC2 instance configurations or code
- ❌ Database data or schemas
- ❌ S3 bucket contents
- ❌ Secrets from Secrets Manager or Parameter Store
- ❌ IAM user passwords or access keys
- ❌ Application logs content (only retention settings)
Configuration Schema
Required Fields
| Field | Type | Description | Example |
|---|---|---|---|
mode | enum | Authentication mode: env or assume_role | env |
region | string | AWS region | us-east-1 |
Optional Fields
| Field | Type | Default | Description |
|---|---|---|---|
regions | array | - | Multiple regions for multi-region collection |
role_arn | string | - | IAM role ARN (required if mode: assume_role) |
external_id | string | - | External ID for assume role (recommended) |
log_groups | array | [] | CloudWatch log groups to check retention |
cloudtrail | object | - | CloudTrail configuration |
cloudtrail.trails | array | [] | CloudTrail trail names to verify |
session_duration | number | 3600 | Session duration for assume role (seconds) |
timeout_seconds | number | 60 | Request timeout in seconds |
Authentication Modes
Environment Variables (env mode)
Use AWS credentials from environment variables:
sources:
aws:
mode: env
region: us-east-1Required environment variables:
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1 # Optional, uses config value if not setUse cases:
- Local development
- CI/CD with static credentials
- Simple setup
Assume Role (assume_role mode)
Assume an IAM role for collection:
sources:
aws:
mode: assume_role
role_arn: arn:aws:iam::123456789012:role/evidence-collector
external_id: evidence-sdk
region: us-east-1Environment variables:
export AWS_ACCESS_KEY_ID=AKIA... # Source credentials
export AWS_SECRET_ACCESS_KEY=... # Source credentialsProcess:
- SDK authenticates with source credentials
- SDK assumes specified role
- SDK uses temporary role credentials for collection
- Temporary credentials expire after
session_duration
Use cases:
- Cross-account collection
- Enhanced security (temporary credentials)
- Multi-organization setups
Basic Configuration
Minimal (IAM Only)
framework: soc2_type1
controls:
- CC6.1
sources:
aws:
mode: env
region: us-east-1Collects:
- ✅ IAM account password policy
Requires:
- AWS credentials in environment variables
With CloudTrail
sources:
aws:
mode: env
region: us-east-1
cloudtrail:
trails:
- production-audit-trailCollects:
- ✅ IAM account password policy
- ✅ CloudTrail trail status and configuration
With CloudWatch Logs
sources:
aws:
mode: env
region: us-east-1
log_groups:
- /aws/lambda/production-api
- /aws/lambda/production-worker
- /aws/ecs/backendCollects:
- ✅ IAM account password policy
- ✅ CloudWatch log group retention settings
Complete Configuration
sources:
aws:
mode: env
region: us-east-1
log_groups:
- /aws/lambda/production-*
- /aws/ecs/backend
cloudtrail:
trails:
- production-audit-trail
- security-trailCollects:
- ✅ IAM password policy
- ✅ CloudTrail configuration
- ✅ CloudWatch log retention
Multi-Region Configuration
Explicit Regions
sources:
aws:
mode: env
regions:
- us-east-1
- us-west-2
- eu-west-1
cloudtrail:
trails:
- production-audit-trailBehavior:
- Collects IAM password policy once (global)
- Checks CloudTrail in each region
- Checks CloudWatch log groups in each region
Wildcard Log Groups
sources:
aws:
mode: env
region: us-east-1
log_groups: '*' # All log groupsWarning: May collect many log groups, check bundle size limits
Artifacts Collected
| Filename | API Call | Controls | Description |
|---|---|---|---|
iam_password_policy.json | iam:GetAccountPasswordPolicy | CC6.1 | Account-wide password complexity requirements |
cloudtrail_trail_{name}_status.json | cloudtrail:GetTrailStatus | CC7.2 | CloudTrail logging status (active/inactive) |
cloudtrail_trail_{name}_config.json | cloudtrail:DescribeTrails | CC7.2 | CloudTrail configuration (S3 bucket, encryption) |
cloudwatch_log_group_{name}.json | logs:DescribeLogGroups | CC7.2 | Log retention settings |
Artifact Details
IAM Password Policy (iam_password_policy.json)
Purpose: Verify password complexity requirements
Sample artifact:
{
"MinimumPasswordLength": 14,
"RequireSymbols": true,
"RequireNumbers": true,
"RequireUppercaseCharacters": true,
"RequireLowercaseCharacters": true,
"AllowUsersToChangePassword": true,
"ExpirePasswords": true,
"MaxPasswordAge": 90,
"PasswordReusePrevention": 12,
"HardExpiry": false
}Control mapping:
- CC6.1: Password policy must meet NIST standards
Pass criteria:
- ✅
MinimumPasswordLength≥ 12 (recommended: 14+) - ✅
RequireSymbols: true - ✅
RequireNumbers: true - ✅
RequireUppercaseCharacters: true - ✅
RequireLowercaseCharacters: true - ✅
ExpirePasswords: truewithMaxPasswordAge≤ 90 - ✅
PasswordReusePrevention≥ 12
Remediation if failing:
- Go to AWS Console → IAM → Account settings → Password policy
- Set minimum length to 14 characters
- Require uppercase, lowercase, numbers, and symbols
- Enable password expiration (90 days)
- Prevent password reuse (12 passwords)
CloudTrail Status (cloudtrail_trail_{name}_status.json)
Purpose: Verify audit logging is active
Sample artifact:
{
"IsLogging": true,
"LatestDeliveryAttemptTime": "2026-01-09T12:30:00Z",
"LatestDeliveryAttemptSucceeded": "2026-01-09T12:30:00Z",
"LatestNotificationAttemptTime": "",
"LatestNotificationAttemptSucceeded": "",
"StartLoggingTime": "2025-06-01T00:00:00Z",
"TimeLoggingStarted": "2025-06-01T00:00:00Z",
"TimeLoggingStopped": ""
}Control mapping:
- CC7.2: CloudTrail must be actively logging
Pass criteria:
- ✅
IsLogging: true - ✅
LatestDeliveryAttemptSucceededis recent (< 24 hours) - ✅
TimeLoggingStoppedis empty (not stopped)
Remediation if failing:
- Go to AWS Console → CloudTrail → Trails
- Select trail
- If logging stopped, click "Start logging"
- Verify S3 bucket is accessible
- Check IAM permissions for CloudTrail service
CloudTrail Configuration (cloudtrail_trail_{name}_config.json)
Purpose: Verify CloudTrail settings
Sample artifact:
{
"Name": "production-audit-trail",
"S3BucketName": "acme-cloudtrail-logs",
"IncludeGlobalServiceEvents": true,
"IsMultiRegionTrail": true,
"HomeRegion": "us-east-1",
"TrailARN": "arn:aws:cloudtrail:us-east-1:123456789012:trail/production-audit-trail",
"LogFileValidationEnabled": true,
"KmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/abc-123",
"IsOrganizationTrail": false
}Control mapping:
- CC7.2: CloudTrail configuration best practices
Pass criteria:
- ✅
IsMultiRegionTrail: true(recommended) - ✅
LogFileValidationEnabled: true(tamper detection) - ✅
KmsKeyIdset (encryption at rest) - ✅
IncludeGlobalServiceEvents: true
Remediation if failing:
- Go to CloudTrail trail settings
- Enable "Multi-region trail"
- Enable "Log file validation"
- Enable "SSE-KMS encryption" with KMS key
CloudWatch Log Group (cloudwatch_log_group_{name}.json)
Purpose: Verify log retention settings
Sample artifact:
{
"logGroupName": "/aws/lambda/production-api",
"creationTime": 1640995200000,
"retentionInDays": 90,
"metricFilterCount": 0,
"arn": "arn:aws:logs:us-east-1:123456789012:log-group:/aws/lambda/production-api:*",
"storedBytes": 12456789
}Control mapping:
- CC7.2: Logs must be retained for audit purposes
Pass criteria:
- ✅
retentionInDays≥ 90 (recommended) - ✅
retentionInDaysset (notnull= indefinite)
Remediation if failing:
- Go to CloudWatch → Log groups
- Select log group
- Click "Actions" → "Edit retention setting"
- Set retention to 90 days or longer
- Consider cost vs. compliance requirements
Required Permissions
IAM Policy (Minimal)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EvidenceCollectionMinimal",
"Effect": "Allow",
"Action": [
"iam:GetAccountPasswordPolicy"
],
"Resource": "*"
}
]
}Collects: IAM password policy only
IAM Policy (Complete)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EvidenceCollection",
"Effect": "Allow",
"Action": [
"iam:GetAccountPasswordPolicy",
"cloudtrail:DescribeTrails",
"cloudtrail:GetTrailStatus",
"logs:DescribeLogGroups"
],
"Resource": "*"
}
]
}Collects: All AWS artifacts
Assume Role Trust Policy
If using assume_role mode:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::SOURCE_ACCOUNT:user/evidence-collector"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"sts:ExternalId": "evidence-sdk"
}
}
}
]
}External ID: Prevents "confused deputy" attacks
Environment Variables
Basic Environment Mode
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1Assume Role Mode
export AWS_ACCESS_KEY_ID=AKIA... # Source credentials
export AWS_SECRET_ACCESS_KEY=... # Source credentials
# AWS SDK will assume role specified in configAWS Profile
export AWS_PROFILE=evidence-collection~/.aws/credentials:
[evidence-collection]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
region = us-east-1Collection Process
Step 1: Authenticate
Authenticating with AWS...
→ STS GetCallerIdentity
✓ Account: 123456789012
✓ User: arn:aws:iam::123456789012:user/evidence-collector
✓ Region: us-east-1Step 2: Fetch IAM Password Policy
Fetching IAM password policy...
→ iam:GetAccountPasswordPolicy
✓ Minimum length: 14 characters
✓ Complexity requirements: enabled
✓ Expiration: 90 daysStep 3: Fetch CloudTrail Status
Fetching CloudTrail trails...
→ cloudtrail:DescribeTrails
✓ Found 2 trails
Checking trail status...
→ production-audit-trail
✓ Logging: active
✓ Last delivery: 2 minutes ago
→ security-trail
✓ Logging: active
✓ Last delivery: 5 minutes agoStep 4: Fetch CloudWatch Log Groups
Fetching CloudWatch log groups...
→ logs:DescribeLogGroups
✓ /aws/lambda/production-api (retention: 90 days)
✓ /aws/lambda/production-worker (retention: 90 days)
✓ /aws/ecs/backend (retention: 365 days)
✓ 3 log groups checkedCommon Patterns
Minimal IAM Only
sources:
aws:
mode: env
region: us-east-1Use case: Quick start, CC6.1 only
Production Single-Region
sources:
aws:
mode: env
region: us-east-1
log_groups:
- /aws/lambda/production-*
cloudtrail:
trails:
- production-audit-trailUse case: Standard production setup
Multi-Region with Assume Role
sources:
aws:
mode: assume_role
role_arn: arn:aws:iam::123456789012:role/evidence-collector
external_id: evidence-sdk
regions:
- us-east-1
- us-west-2
- eu-west-1
cloudtrail:
trails:
- global-audit-trailUse case: Multi-region deployments, cross-account access
Troubleshooting
Access Denied (IAM Permissions)
Symptom:
✗ AWS connector failed
Error: User is not authorized to perform: iam:GetAccountPasswordPolicy (HTTP 403)Cause: IAM user/role lacks required permissions
Solution:
-
Check current permissions:
aws iam get-user-policy --user-name evidence-collector --policy-name EvidenceCollection -
Attach required policy:
aws iam put-user-policy --user-name evidence-collector \ --policy-name EvidenceCollection \ --policy-document file://evidence-policy.json -
Verify permissions:
aws iam get-account-password-policy
Invalid Credentials
Symptom:
✗ AWS connector failed
Error: The security token included in the request is invalid (HTTP 403)Causes:
- Access key ID incorrect
- Secret access key incorrect
- Credentials expired (temporary credentials)
Solutions:
-
Verify credentials are set:
echo $AWS_ACCESS_KEY_ID echo $AWS_SECRET_ACCESS_KEY -
Test credentials:
aws sts get-caller-identity -
Rotate credentials:
- Create new access key in IAM console
- Update environment variables
- Delete old access key
CloudTrail Not Found
Symptom:
✗ AWS connector failed
Error: Trail 'production-audit-trail' not found in region us-east-1Causes:
- Trail name incorrect
- Trail in different region
- Trail doesn't exist
Solutions:
-
List all trails:
aws cloudtrail describe-trails -
Check trail name:
cloudtrail: trails: - production-audit-trail # Exact name required -
Check trail region:
- CloudTrail trails are regional
- Use
regionsto check multiple regions - Multi-region trails visible in home region only
Log Group Not Found
Symptom:
Warning: Log group '/aws/lambda/production-api' not foundNot an error, but indicates misconfiguration
Solutions:
-
List log groups:
aws logs describe-log-groups --log-group-name-prefix /aws/lambda -
Check log group name:
- Names are case-sensitive
- Must match exactly
- Use wildcard:
/aws/lambda/production-*
-
Verify log group exists:
- Application must have created logs
- Check CloudWatch Logs console
Assume Role Failed
Symptom:
✗ AWS connector failed
Error: User is not authorized to perform: sts:AssumeRole on resource: arn:aws:iam::123456789012:role/evidence-collectorCauses:
- Trust policy doesn't allow source user
- External ID mismatch
- Role doesn't exist
Solutions:
-
Verify role exists:
aws iam get-role --role-name evidence-collector -
Check trust policy:
aws iam get-role --role-name evidence-collector --query 'Role.AssumeRolePolicyDocument' -
Update trust policy:
- Allow source user ARN in
Principal - Match
ExternalIdwith config - Ensure
sts:AssumeRoleaction allowed
- Allow source user ARN in
Best Practices
1. Use Dedicated IAM User
Create dedicated IAM user for evidence collection:
User name: evidence-collector
Permissions: Minimal IAM policy (read-only)
Access keys: Rotate annually
Don't use:
- ❌ Admin users
- ❌ Personal users
- ❌ Root account
2. Enable CloudTrail in All Regions
Organization trail:
- Enable multi-region trail
- Enable in all accounts (AWS Organizations)
- Enable log file validation
- Encrypt with KMS
3. Set CloudWatch Log Retention
Standard retention:
- Production logs: 90 days minimum (recommended: 365 days)
- Development logs: 30 days
- Security logs: 365+ days
Balance:
- Compliance requirements
- Storage costs
- Query performance
4. Use External ID for Assume Role
Always set external_id:
sources:
aws:
mode: assume_role
role_arn: arn:aws:iam::123456789012:role/evidence-collector
external_id: evidence-sdk-production-2026Benefits:
- Prevents "confused deputy" attacks
- Adds extra authentication layer
- Best practice for cross-account access
5. Rotate Access Keys Annually
Schedule:
- Create new access key (January 1st)
- Update environment variables
- Test collection with new key
- Delete old access key
See Also
- Sources Configuration - AWS source configuration schema
- SOC 2 Controls Guide - CC6.1, CC7.2 details
- Connectors Overview - All available connectors
- Credential Management - IAM best practices