Links#
- AWS Organizations
- AWS Organizations SCP examples
- Amazon GuardDuty Organizations
- AWS CloudTrail organization trail
- IAM Identity Center
1. When To Use#
如果 Control Tower + AWS Config + Security Hub 对非常早期的 startup 太重,可以先用这个 Lite 方案。它不是最终状态,但比单账号安全很多。
use Lite when:
team <= 5 engineers
no compliance audit yet
AWS monthly cost must stay very low
production is small but already customer-facing
do not use Lite when:
customer asks for SOC2 / ISO27001 / security questionnaire
production handles regulated data
multiple teams share AWS
you need repeatable account vending2. Minimal Accounts#
| Account | Purpose |
|---|---|
| management | Organizations, billing, IAM Identity Center |
| security-log | GuardDuty delegated admin, CloudTrail logs, security read-only |
| dev | development workloads |
| uat | pre-production workloads |
| prod | production workloads |
Lite 版本把 security-tooling 和 log-archive 合并成 security-log,减少账号和运维成本。公司进入合规阶段后再拆开。
AWS Organizations
├── Security
│ └── security-log
├── Workloads
│ ├── Dev
│ │ └── dev
│ ├── UAT
│ │ └── uat
│ └── Prod
│ └── prod
└── Suspended3. Setup Order#
1. create management account
2. enable root MFA
3. enable AWS Organizations all features
4. enable IAM Identity Center
5. create Security / Workloads / Suspended OUs
6. create security-log / dev / uat / prod accounts
7. create organization CloudTrail to security-log S3 bucket
8. delegate GuardDuty admin to security-log
9. attach baseline SCP
10. create GitHub OIDC deploy roles
11. create budgets and root-login alerts4. Must-Have Controls#
| Control | Lite Default |
|---|---|
| Human access | IAM Identity Center only |
| Machine access | IAM Role / OIDC only |
| CloudTrail | organization trail, multi-region |
| GuardDuty | all accounts, all active regions |
| Security Hub | optional first month, enable before customer review |
| AWS Config | optional, enable for prod if budget allows |
| Logs | CloudTrail central S3 bucket |
| SCP | root deny, leave org deny, security baseline deny, prod IAM user deny |
5. Baseline SCP#
Use the same SCP examples from AWS Startup Landing Zone:
attach to Workloads OU:
DenyRootUser
DenyLeaveOrganization
DenyDisableSecurityBaseline
RequireIMDSv2
RequireEBSEncryption
attach to Workloads/Prod:
DenyIAMUsersAndAccessKeysInProd
DenyPublicS3Policy
attach to Suspended:
QuarantineAccountAttach to Workloads OU: workloads-baseline-lite.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyRootUser",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"StringLike": {
"aws:PrincipalArn": "arn:aws:iam::*:root"
}
}
},
{
"Sid": "DenyLeaveOrganization",
"Effect": "Deny",
"Action": "organizations:LeaveOrganization",
"Resource": "*"
},
{
"Sid": "DenyDisableSecurityBaseline",
"Effect": "Deny",
"Action": [
"cloudtrail:StopLogging",
"cloudtrail:DeleteTrail",
"cloudtrail:UpdateTrail",
"cloudtrail:PutEventSelectors",
"config:DeleteConfigurationRecorder",
"config:StopConfigurationRecorder",
"config:DeleteDeliveryChannel",
"guardduty:DeleteDetector",
"guardduty:DisassociateFromAdministratorAccount",
"securityhub:DisableSecurityHub",
"securityhub:DisassociateFromAdministratorAccount",
"access-analyzer:DeleteAnalyzer"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/OrganizationSecurityAdmin",
"arn:aws:iam::*:role/AWSReservedSSO_BreakGlassAdmin_*"
]
}
}
},
{
"Sid": "RequireIMDSv2",
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringNotEquals": {
"ec2:MetadataHttpTokens": "required"
}
}
},
{
"Sid": "RequireEBSEncryption",
"Effect": "Deny",
"Action": [
"ec2:CreateVolume",
"ec2:RunInstances"
],
"Resource": "*",
"Condition": {
"Bool": {
"ec2:Encrypted": "false"
}
}
}
]
}Attach to Workloads/Prod: prod-baseline-lite.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyIAMUsersAndAccessKeysInProd",
"Effect": "Deny",
"Action": [
"iam:CreateUser",
"iam:CreateLoginProfile",
"iam:CreateAccessKey",
"iam:UpdateAccessKey",
"iam:AttachUserPolicy",
"iam:PutUserPolicy"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/OrganizationSecurityAdmin",
"arn:aws:iam::*:role/AWSReservedSSO_BreakGlassAdmin_*"
]
}
}
},
{
"Sid": "DenyPublicS3PolicyAndAclInProd",
"Effect": "Deny",
"Action": [
"s3:PutBucketPolicy",
"s3:PutBucketAcl",
"s3:PutObjectAcl"
],
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/OrganizationSecurityAdmin",
"arn:aws:iam::*:role/AWSReservedSSO_BreakGlassAdmin_*"
]
}
}
}
]
}Attach to Suspended: quarantine-account.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "QuarantineAccount",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"ArnNotLike": {
"aws:PrincipalArn": [
"arn:aws:iam::*:role/AWSReservedSSO_BreakGlassAdmin_*",
"arn:aws:iam::*:role/OrganizationSecurityAdmin"
]
}
}
}
]
}6. Organization CloudTrail#
Create the bucket in security-log account:
aws s3api create-bucket \
--bucket org-cloudtrail-logs-o-exampleorgid \
--region ap-east-1 \
--create-bucket-configuration LocationConstraint=ap-east-1
aws s3api put-public-access-block \
--bucket org-cloudtrail-logs-o-exampleorgid \
--public-access-block-configuration \
BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true
aws s3api put-bucket-versioning \
--bucket org-cloudtrail-logs-o-exampleorgid \
--versioning-configuration Status=EnabledCreate the organization trail from management account:
aws cloudtrail create-trail \
--name org-management-events \
--s3-bucket-name org-cloudtrail-logs-o-exampleorgid \
--is-organization-trail \
--is-multi-region-trail \
--enable-log-file-validation \
--region ap-east-1
aws cloudtrail start-logging \
--name org-management-events \
--region ap-east-17. GuardDuty#
export SECURITY_LOG_ACCOUNT_ID="111122223333"
export REGION="ap-east-1"
aws organizations enable-aws-service-access \
--service-principal guardduty.amazonaws.com
aws guardduty enable-organization-admin-account \
--admin-account-id "$SECURITY_LOG_ACCOUNT_ID" \
--region "$REGION"In security-log account:
DETECTOR_ID="$(aws guardduty list-detectors \
--region ap-east-1 \
--query 'DetectorIds[0]' \
--output text)"
aws guardduty update-organization-configuration \
--detector-id "$DETECTOR_ID" \
--auto-enable-organization-members ALL \
--region ap-east-18. IAM Roles#
| Role | Account | Purpose |
|---|---|---|
| OrganizationSecurityAdmin | security-log | manage GuardDuty, read logs |
| SecurityAuditRole | dev/uat/prod | allow security-log read-only audit |
| GitHubDeployRole | dev/uat/prod | CI/CD deploy |
| BreakGlassAdmin | all accounts | emergency access |
SecurityAuditRole should attach:
SecurityAudit
ViewOnlyAccessGitHubDeployRole must restrict:
aud:
sts.amazonaws.com
sub:
repo:<GITHUB_ORG>/<REPO>:environment:<ENV>
prod:
GitHub Environment approval required
role policy cannot create IAM users
role policy can pass only application task roles9. Startup Defaults#
network:
one VPC per environment account
no VPC peering at first
SSM Session Manager instead of bastion
no public database
compute:
ECS Fargate is simpler than EKS for most early startups
use EKS only when Kubernetes skill already exists
database:
RDS encrypted, private, automated backup
prod deletion protection on
storage:
S3 block public access on
CloudFront OAC for public static content
secrets:
Secrets Manager for prod app secrets
SSM Parameter Store SecureString acceptable for low-frequency dev secrets10. Upgrade Path To Full Landing Zone#
when:
first enterprise customer security review
SOC2 / ISO27001 preparation
production team grows beyond 5-8 engineers
more than one product team shares AWS
upgrade:
create separate log-archive account
keep security-log as security-tooling account
enable Control Tower
enroll existing accounts
enable Security Hub and AWS Config
add shared-services account
add stronger region deny and proactive controls11. Checklist#
must finish before production:
[ ] management root MFA
[ ] no IAM users for humans
[ ] dev / uat / prod separated by account
[ ] organization CloudTrail logging
[ ] GuardDuty organization auto-enable
[ ] root login alert
[ ] monthly budget alert
[ ] prod database private and encrypted
[ ] prod secrets outside source code
[ ] GitHub OIDC deploy role, no static AWS keys
[ ] break-glass access tested
do next:
[ ] Security Hub
[ ] AWS Config
[ ] VPC Flow Logs for prod
[ ] Macie for sensitive S3 buckets
[ ] Control Tower migration