Amazon SAA-C03: 安全、IAM、KMS 与治理 — 学习指南
属于 AWS SAA-C03 — 完整学习指南. 使用经过验证的答案练习: Amazon 考试中心, 或参加限时模拟考试: ExamRoll.io.
身份认证基础:用户、根用户、组和角色
身份和访问管理是每个工作负载都必须经过的控制平面,其治理原则是最小权限:仅授予所需的权限,且仅在需要的时间内授予,并优先选择生成短期凭证的身份,而不是持有静态密钥的身份。
根用户拥有账户,持有不受限制的权限,并且不能被 IAM 策略或 SCP 约束。这使其成为环境中唯一最敏感的凭证,应被视为紧急访问(break-glass)凭证。在一个新账户上:为根用户启用硬件或虚拟 MFA 设备,设置一个长且唯一的密码,删除任何历史上的根访问密钥,并注册备用的账单/运营/安全联系人以便能够进行恢复。在初始设置——创建 IAM 管理员身份、配置账单和设置账户别名——之后,除了 AWS 明确要求使用它的少数任务(关闭账户、更改账户名称、恢复已删除的 IAM 权限、启用 MFA Delete,以及少数几个 S3/CloudFront 的根签名操作)外,不再使用根用户。使用根用户进行日常工作是错误的,因为它不能被策略限定范围,在共享时很难在 CloudTrail 中追溯责任,而且一次泄露就会授予不可撤销的控制权。
人类的日常访问通过由最小权限策略限定范围的 IAM 身份进行。将托管策略附加到组,而不是单个用户:一个附加了 AdministratorAccess 的 Administrators 组,并将指定用户放入其中,这样就提供了一个单一的变更点,并避免了将相同策略粘贴到每个用户上的反模式。使用明确的 ARN 而不是 * 来限定资源范围。
角色则完全用于不同的目的。它们由委托人(principal)——服务、EC2 实例、Lambda 函数、联合身份用户、跨账户调用者——代入,并生成自动轮换的临时 STS 凭证。因为这些凭证不会在 Git 提交中泄露,并且在几分钟到几小时内过期,而不是一直持续到手动轮换,所以角色是所有非人类实体的默认身份。
每个角色的两个策略:权限和信任
每个角色都由两个独立的文档管理,忘记其中任何一个都是一个典型的失败模式。
权限策略(基于身份的)声明了角色被代入后可以做什么。信任策略(基于资源的,附加到角色本身)声明了谁可以代入它。如果没有任何委托人被允许对角色调用 sts:AssumeRole,那么将 AmazonS3ReadOnlyAccess 附加到该角色也毫无意义;反之,一个宽松的信任策略如果没有权限策略,会产生一个可以被代入但做不了任何有用事情的角色。
Lambda 执行角色展示了服务委托人(service-principal)模式——调用者是服务本身,而不是账户所有者:
AssumeRolePolicyDocument: # trust policy
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal: { Service: lambda.amazonaws.com }
Action: sts:AssumeRole
Policies: # permissions
- PolicyName: ReadOrders
PolicyDocument:
Statement:
- Effect: Allow
Action: dynamodb:GetItem
Resource: arn:aws:dynamodb:*:*:table/Orders
工作负载身份:实例配置文件、任务角色、IRSA、Roles Anywhere
存在于模板、环境变量或笔记本电脑上的每一个凭证都是未来的安全漏洞。典型的 AWS 模式是用通过角色分发的、自动轮换的短期凭证来取代静态访问密钥。
对于 EC2,分发机制是实例配置文件 (instance profile)——一个将 IAM 角色绑定到实例的轻量级容器,以便实例元数据服务 (IMDSv2) 可以向 SDK 提供临时凭证。默认凭证提供程序链无需配置即可找到它们,因此 boto3.client('s3') 可以直接工作,应用程序代码永远不会接触到凭证。应强制执行 IMDSv2 (HttpTokens: required) 以防止基于 SSRF 的凭证窃取。凭证大约每六小时轮换一次,撤销只需简单地编辑角色即可。
AppRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal: { Service: ec2.amazonaws.com }
Action: sts:AssumeRole
Policies:
- PolicyName: S3DocAccess
PolicyDocument:
Statement:
- Effect: Allow
Action: [s3:GetObject, s3:PutObject]
Resource: arn:aws:s3:::docs-bucket/*
AppInstanceProfile:
Type: AWS::IAM::InstanceProfile
Properties:
Roles: [!Ref AppRole]
对于 ECS,类似的是任务角色 (task role);对于 Lambda,是执行角色 (execution role);对于 EKS Pod,是 IRSA (IAM Roles for Service Accounts) 或 EKS Pod Identity。在每种情况下,都是 AWS 自身基于角色来代理凭证,工作负载永远不会接触到长期密钥。
将访问密钥硬编码到 AMI、用户数据脚本或 .env 文件中是错误的,原因有三:密钥永远不会自动轮换,它们无法像源 VPC 端点那样被限定在会话上下文中,而且如果实例被攻破或 AMI 被无意中共享,凭证将永久泄露。
对于 AWS 外部的工作负载——本地服务器、其他云、CI/CD 运行器——如果需要临时 AWS 凭证而又不想嵌入密钥,IAM Roles Anywhere 使用来自私有 CA(AWS Private CA 或您自己的 CA)的 X.509 证书作为信任锚。工作负载出示其客户端证书,并接收短期的 STS 凭证:
aws_signing_helper credential-process \
--certificate /etc/pki/client.pem \
--private-key /etc/pki/client.key \
--trust-anchor-arn arn:aws:rolesanywhere:...:trust-anchor/... \
--profile-arn arn:aws:rolesanywhere:...:profile/... \
--role-arn arn:aws:iam::111122223333:role/OnPremWorkload
这解决了与 AWS 内部的实例角色和 Secrets Manager 所解决的相同的反模式。
大规模的人员访问:Identity Center、SAML、Directory Service
在任何规模下,为每个账户配置 IAM 用户都是无法管理的。AWS IAM Identity Center(AWS SSO 的后继者)是推荐的员工访问入口:一个可以联合到 Organization 中每个账户的单一目录,通过权限集 (permission sets)——即映射到 IdP 组的 IAM 角色模板——来发放临时的、基于角色的会话。用户在 Identity Center 门户进行一次身份验证,然后就可以代入分配给他们的任何账户中的权限集。
Identity Center 通过 SAML 2.0 和 SCIM 与外部 IdP(Okta、Entra ID/Azure AD、Google Workspace、ADFS)集成,以实现自动化的员工入职/调动/离职流程,并通过 AWS Directory Service AD Connector(一个代理)或 AWS Managed Microsoft AD(一个在 AWS 中的完整副本)与本地 Active Directory 集成。对于需要从未经身份验证或第三方身份验证的用户调用 AWS 的移动或 Web 应用程序,Amazon Cognito 将外部身份交换为临时的 STS 凭证,同样避免了嵌入长期密钥。
跨账户访问
跨账户访问是通过角色而非共享用户来实现的,并且需要双方都同意。目标账户(B)创建一个角色,其信任策略中指定账户 A(或其中的特定主体),同时账户 A 中的调用者也必须拥有针对该角色 ARN 的 sts:AssumeRole 权限。任何单方面的设置都是不够的。这种方式会生成短期凭证,并在两个账户中都留下清晰的 CloudTrail 审计跟踪记录。
当第三方(例如 SaaS 供应商)是代入角色的主体时,应添加一个 ExternalId 条件来防范混淆代理人问题,并考虑要求使用 MFA:
{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::222222222222:root" },
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": { "sts:ExternalId": "a1b2c3-unique-token" },
"Bool": { "aws:MultiFactorAuthPresent": "true" }
}
}
对于服务到服务的跨账户调用,则由资源策略来完成。要让账户 A 中的一个 SNS 主题能够调用账户 B 中的一个 Lambda:
aws lambda add-permission \
--function-name ProcessNotification \
--statement-id AllowSNSInvoke \
--action lambda:InvokeFunction \
--principal sns.amazonaws.com \
--source-arn arn:aws:sns:us-east-1:111111111111:my-topic
--principal sns.amazonaws.com 是服务主体(即 SNS 服务本身调用 Lambda),而 --source-arn 则将信任范围限定到特定的主题,以防止混淆代理人问题。
对于跨 Organizations 的 S3 共享,那种在存储桶策略中列出每个账户 ARN 的简单方法扩展性很差,并且每当有新账户加入时就会失效。正确的模式是使用 aws:PrincipalOrgID:
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::reports-bucket/*",
"Condition": {
"StringEquals": { "aws:PrincipalOrgID": "o-abcd1234ef" }
}
}
该组织中任何账户的任何主体都被允许;其他任何人则被拒绝。请注意,如果没有这个条件,Principal: "*" 会使存储桶变为公共存储桶——正是这个条件键限制了范围。身份侧的策略同样重要:成员账户中的用户还需要通过他们自己的 IAM 策略授予 s3:GetObject 权限(除非他们是账户根用户),因为跨账户访问要求双方都允许该调用。
具体到 S3,自 2023 年起,默认的对象所有权设置 存储桶拥有者强制 会完全禁用 ACL,使存储桶策略成为该存储桶唯一的授权机制。当对象之前是由其他账户上传时,历史对象 ACL 或 bucket-owner-full-control 预设 ACL 可能仍然有效。
Organizations 和服务控制策略
AWS Organizations 将多个账户聚合到一个以管理账户为根的 OU(组织单元)树状结构中。服务控制策略 (SCP) 是附加到根、OU 或单个账户上的护栏。它们适用于账户中的每个 IAM 用户和角色——包括账户根用户——但不适用于管理账户本身,这就是为什么工作负载永远不应该在管理账户中运行的原因。
关键的心智模型是:SCP 从不授予权限。它们定义了一个账户中允许执行的最大操作集合。一个操作只有在被身份策略或资源策略授予并且没有被该账户路径上的任何 SCP 阻止时,才被允许。如果一个开发人员拥有 AdministratorAccess 权限,但 SCP 禁止在 ap-southeast-2 区域之外执行 ec2:RunInstances,那么在 us-east-1 中启动实例就会失败。反之,一个允许 s3:* 的 SCP 本身不起任何作用——用户仍然需要一个授予 s3:* 的 IAM 策略。SCP 过滤的是 IAM 已经允许的操作;它们是权限的上限,而非下限。
SCP 的典型用途包括区域锁定、禁止禁用 CloudTrail 或 GuardDuty、禁止在紧急访问角色之外删除 KMS 密钥,以及强制加密。要强制在启动时加密 EBS,可以结合两种机制:在该区域启用默认 EBS 加密(这是一项每个区域的账户设置,这样用户就无需更改脚本),外加一个 SCP 作为可审计的护栏:
{
"Effect": "Deny",
"Action": "ec2:RunInstances",
"Resource": "arn:aws:ec2:*:*:volume/*",
"Condition": { "Bool": { "ec2:Encrypted": "false" } }
}
由于 SCP 应用于整个账户,因此它们无法被成员账户中被攻陷的管理员绕过。标签策略强制执行标准化的标签键和大小写(例如 CostCenter,而不是 costcenter),以确保成本分配和 ABAC 可靠地工作。Organizations 还支持委托管理:您可以将一个成员账户(例如“安全”或“审计”账户)委托为 GuardDuty、Security Hub、IAM Access Analyzer 或 Config 的管理员,而不是从管理账户运行这些安全服务——这保留了职责分离的原则。
KMS:密钥、密钥策略和所有权模型
KMS 根据所有权和控制权来区分密钥材料:
| 模型 | 密钥材料 | 轮换 | 可审计 | 使用场景 |
|---|---|---|---|---|
| SSE-S3 / AWS 自有 | AWS,隐藏 | 自动,不透明 | 不可见 | 简单的“静态加密” |
AWS 托管的 CMK (aws/service) | AWS | 每年自动 | 是 | 默认,无需控制 |
| 客户管理的 CMK | AWS KMS,您拥有策略 | 可选每年(需启用),可配置 90–2560 天 | 是 | 您需要禁用、审计、限定范围或共享 |
| 导入的密钥材料 | 您生成,导入到 KMS | 手动重新导入;从不自动 | 是 | 监管要求在本地生成密钥 |
| 外部密钥存储 (XKS) | 通过 XKS 代理连接您的本地 HSM | 您在外部控制 | 是 | 数据主权;密钥永不离开本地 |
| SSE-C | 客户按请求提供 | 手动 | 有限 | 客户坚持持有密钥材料 |
CMK 由密钥策略(key policy)管理——一种附加到密钥上的基于资源的策略。与几乎所有其他 AWS 资源不同,仅凭 IAM 策略无法授予对 KMS 密钥的访问权限,除非密钥策略首先将权限委托给 IAM:
{
"Sid": "EnableIAMPolicies",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
}
没有这条语句,任何 IAM 策略都无法使该密钥可用。密钥策略和调用者的 IAM 策略都必须允许该操作——这是最常见的加密错误。在 IAM 策略中授予 kms:Decrypt 是必要但不充分的;如果密钥策略没有委托给 IAM 或没有指定主体,即使是管理员,解密也会失败并返回 AccessDenied。
对于代表您使用 KMS 的服务(EBS、S3、RDS、Lambda),调用角色通常需要 kms:GenerateDataKey、kms:Decrypt,并且经常需要 kms:CreateGrant。对于使用 CMK 加密 EBS 卷的 EKS 托管节点组,Auto Scaling 的服务相关角色必须出现在密钥策略中并拥有 kms:CreateGrant 权限,否则实例启动会静默失败。
客户管理的 CMK 需要显式启用轮换——许多从业者错误地认为所有 KMS 密钥都会自动轮换:
aws kms enable-key-rotation --key-id alias/my-cmk
aws kms get-key-rotation-status --key-id alias/my-cmk
轮换会保留相同的密钥 ID 和别名;底层密钥材料会改变,但过去的密文仍然可以解密,因为 KMS 会保留旧的密钥材料来解密现有的密文,而新的写入操作则使用新的密钥材料。导入的密钥材料永远不会自动轮换。KMS 强制执行 7-30 天的待删除等待期;可将其与匹配 CloudTrail 中 ScheduleKeyDeletion 或 DisableKey 事件的 EventBridge 规则结合,并将 SNS 主题作为目标,以实现无服务器、免轮询的警报模式:
{
"source": ["aws.kms"],
"detail-type": ["AWS API Call via CloudTrail"],
"detail": { "eventName": ["ScheduleKeyDeletion", "DisableKey"] }
}
当监管机构要求密钥材料必须物理存放在客户控制的 HSM 中时,外部密钥存储 (External Key Stores, XKS) 扩展了此模型。KMS 将加密操作转发给与本地 HSM 通信的 XKS 代理;如果 HSM 离线,解密将失败——可用性成为客户的责任。
多区域密钥 (Multi-Region Keys, MRK) 在多个区域间共享相同的密钥 ID 和密钥材料,因此在 us-east-1 中生成的密文可以直接在 eu-west-1 中解密。这对于 DynamoDB 全局表、使用 SSE-KMS 的 S3 跨区域复制以及备用区域必须读取加密备份的灾难恢复 (DR) 场景来说,是正确的模式。标准的单区域密钥则需要在复制时进行解密再重新加密。
跨账户加密资源共享
加密 AMI 和 EBS 快照的共享是最常见的跨账户失败模式之一,因为它需要四个协调的操作:(1) 使用客户管理的 CMK——AWS 托管的密钥无法共享;(2) 在密钥策略中将目标账户添加为主体,并授予 kms:Decrypt、kms:DescribeKey、kms:CreateGrant 和 kms:ReEncrypt* 权限;(3) 修改 AMI 或快照的启动/共享权限以包含该账户;以及 (4) 确保目标账户中的 IAM 主体也拥有这些 KMS 操作权限。如果跳过第 2 步,共享操作表面上会成功,但接收方账户无法解密。认为仅共享 AMI 就足够了,这是一个典型的陷阱。
S3 服务器端加密模式
| 模式 | 密钥所有者 | 轮换 | CloudTrail 审计 | 成本 |
|---|---|---|---|---|
| SSE-S3 (AES-256) | AWS 托管,隐藏 | 自动,不透明 | 不可见 | 无密钥成本 |
使用 aws/s3 的 SSE-KMS | AWS | 每年自动 | 是 | 无密钥成本,但收取 API 调用费用 |
| 使用客户 CMK 的 SSE-KMS | 客户 | 可选,需启用 | 是 | 每密钥每月 1 美元 + API 费用 |
| DSSE-KMS | 客户 | 与 CMK 相同 | 是 | 更高;适用于受监管工作负载的双层加密 |
| SSE-C | 客户按请求提供 | 手动 | 有限 | 无密钥成本 |
| CSE-KMS / CSE-C | 客户,上传前加密 | 手动 | 仅 KMS 调用 | 不等 |
当需求指定自动年度轮换、CloudTrail 可审计性 以及 最小化密钥成本时,答案是使用 AWS 托管的 aws/s3 密钥的 SSE-KMS——它每年免费轮换,并且每次 GenerateDataKey/Decrypt 调用都会被记录。SSE-S3 更便宜,但不会留下密钥使用记录。客户管理的 CMK 每月会增加 1 美元的成本,并且只有在您启用轮换后才会轮换。
混淆 SSE-S3 和 SSE-KMS 是典型的 PHI 陷阱。SSE-S3 会加密数据,但不提供密钥策略、没有 CloudTrail 可见性,合规团队也无法管理密钥——因此它无法满足任何提及“管理”、“控制”、“审计”或“撤销访问”密钥的要求。反之,当需求仅仅是“以最少的管理工作实现静态加密”时,选择 SSE-KMS 则是过度设计。
启用 SSE-KMS 本身并不能阻止未经授权的读取。如果存储桶策略允许 s3:GetObject 并且密钥策略向同一主体授予了 kms:Decrypt 权限,则对象是可读的。静态加密可以防御物理介质泄露,并通过密钥策略增加第二层授权检查——但它不能替代范围适当的存储桶策略、IAM 策略、VPC 端点策略和 aws:PrincipalOrgID 条件。
在 S3 上强制执行加密和 TLS
将存储桶设置为“默认加密”是不够的——客户端可以省略或覆盖加密标头。必须分层设置两个护栏:默认存储桶加密(如果客户端省略了标头,则填充标头)和一个基于拒绝的存储桶策略(拒绝没有必需标头的 PutObject 请求),再加上一条拒绝非 TLS 访问的语句:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyUnEncryptedObjectUploads",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::phi-bucket/*",
"Condition": {
"StringNotEquals": { "s3:x-amz-server-side-encryption": "aws:kms" }
}
},
{
"Sid": "DenyInsecureTransport",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": ["arn:aws:s3:::phi-bucket", "arn:aws:s3:::phi-bucket/*"],
"Condition": { "Bool": { "aws:SecureTransport": "false" } }
}
]
}
aws:SecureTransport 条件强制使用 HTTPS,满足“传输中加密”的要求。结合使用合规团队拥有的 CMK 进行 SSE-KMS 加密,这是存储 PHI(受保护的健康信息)的典型模式。
传输中加密 vs. 静态加密
静态加密(KMS 加密的 EBS、RDS 存储、S3 对象)和传输中加密(网络传输中的 TLS)是独立的控制措施,用于应对不同的威胁——分别是磁盘盗窃和网络拦截。在 RDS 实例上启用 KMS 可以保护底层存储;但它对客户端到数据库的会话没有任何作用,该会话默认可能是未加密的。对于 RDS MySQL,传输中保护需要下载 RDS CA 证书包,在参数组中设置 require_secure_transport=ON,并使用 --ssl-ca=rds-combined-ca-bundle.pem 连接客户端。将“已开启静态加密”视为足够是一种常见的审计失败点。
Secrets Manager 和 Parameter Store
配置文件、环境变量或 CloudFormation 参数中的静态数据库密码是凭证泄露的主要途径。AWS Secrets Manager 使用 KMS 加密存储密钥,通过受 IAM 控制的 GetSecretValue API 公开它们,并且——最关键的是——通过 Lambda 轮换函数自动轮换它们。对于 RDS、Aurora、Redshift 和 DocumentDB,AWS 提供了一个托管的轮换 Lambda,它可以连接到数据库,生成新密码,原子性地更新密钥和数据库用户,并支持单用户或多用户策略。对于其他系统,您需要编写一个 Lambda 来实现四步生命周期:createSecret、setSecret、testSecret、finishSecret。
import boto3, json
secret = json.loads(
boto3.client('secretsmanager')
.get_secret_value(SecretId='prod/aurora/app')['SecretString'])
conn = pymysql.connect(host=secret['host'],
user=secret['username'],
password=secret['password'])
应用程序会短暂缓存该值(使用 AWS SDK 缓存库),并在身份验证失败时重新连接。轮换过程是无感知的,更改密码无需进行部署。
当不需要轮换且成本是主要考虑因素时,SSM Parameter Store SecureString 是一个替代方案:
| 功能 | Secrets Manager | SSM Parameter Store |
|---|---|---|
| 自动轮换 | 是;为 RDS/Aurora/Redshift/DocumentDB 提供原生支持 | 无原生轮换(高级版可以触发 EventBridge) |
| 成本 | $0.40/密钥/月 + API 调用费用 | 标准版免费;高级版付费 |
| 大小限制 | 64 KB | 标准版 4 KB,高级版 8 KB |
| 跨账户共享 | 资源策略 | 不支持原生共享 |
| 跨区域复制 | 是 | 否 |
| 加密 | 必须使用 KMS | 仅 SecureString 类型使用 KMS |
检索 SecureString 参数的调用者需要同时拥有对密钥的 ssm:GetParameter 和 kms:Decrypt 权限。忘记 KMS 权限是最常见的配置错误之一——IAM 策略看起来是正确的,但 API 调用在解密时失败。
在 EC2、ECS、EKS 和 Lambda 上,代码应代入一个 IAM 角色来调用 GetSecretValue 或 GetParameter;不应在磁盘上存放长期凭证。将 IAM 用户访问密钥直接嵌入应用程序代码中——即使是加密的——也违反了最小权限原则,并使轮换变得复杂。
审计和取证工具
CloudTrail 记录每一次 AWS API 调用:谁、做了什么、何时、从何处调用。从管理账户启用的**组织跟踪(organization trail)**会将所有账户的事件捕获到单个 S3 存储桶中,理想情况下,该存储桶应位于一个锁定的安全专用账户中,并启用了 S3 Object Lock 和 MFA Delete。这提供了一个不可变的取证时间线——哪个主体删除了卷,哪个角色修改了安全组,哪个访问密钥在 UTC 时间 03:17 调用了 ec2:RunInstances。可通过 CloudWatch Logs 和警报(例如根用户登录、IAM 策略更改)以及用于获取时间点资源状态和合规包的 AWS Config 来进行补充。使用 SCP 拒绝 cloudtrail:StopLogging 和 cloudtrail:DeleteTrail 权限,以防止篡改。
S3 存储桶上的 MFA Delete 强制要求根用户在永久删除对象版本或禁用版本控制时提供 MFA 令牌。它只能由根用户通过 CLI 启用,并为防范勒索软件和内部人员删除提供了强有力的保护。
Amazon Macie 使用托管的机器学习(ML)在 S3 中发现 PII(个人身份信息)、PHI(受保护的健康信息)、凭证和财务数据,并生成按严重性排序的发现结果。它是一个发现工具,而不是加密工具。
威胁检测:GuardDuty、Security Hub、Detective
Amazon GuardDuty 持续分析 VPC Flow Logs、DNS 日志以及 CloudTrail 管理和数据事件,并为 EKS 审计日志、S3 数据事件、EBS 恶意软件扫描、Lambda 网络活动和 RDS 登录事件提供专门的保护计划。GuardDuty RDS Protection 功能可以发现针对 Aurora 和 RDS 的异常或暴力破解身份验证尝试——这种行为安全组无法捕获,因为在 L4 层,连接是合法的。发现结果会流入 EventBridge、Security Hub 和 Detective 的控制面板。
安全组仅在 L3–L4 层运行。一个允许 0.0.0.0/0 访问 443 端口的安全组在转发 SQL 注入载荷时,它正在履行其职责——而这正是 WAF 存在的目的。纵深防御意味着安全组、WAF、Shield 和 GuardDuty 的组合,每个组件都覆盖其他组件无法看到的层面。
DDoS:Shield Standard 和 Advanced
AWS Shield Standard 是自动且免费的,可以保护每个账户免受常见的 L3/L4 攻击(如 SYN 洪水攻击、反射攻击)。它在后台静默运行,没有可见性,不支持自定义缓解措施,也没有人工干预途径。
AWS Shield Advanced(每个组织每月 3000 美元,外加数据传输费用)是当场景中提到主动参与、专属响应、DDoS 攻击引发的扩缩成本保护或近乎实时的攻击可见性时所必需的服务。它覆盖 CloudFront、Global Accelerator、ALB、CLB、Route 53 和 Elastic IP,并提供对 Shield Response Team (SRT) 的 24/7 访问——通过 IAM 角色预先授权——以便在主动攻击期间代表您编写 WAF 规则。当一个位于 ALB 和 Route 53 后端的设计需要托管式检测和人工响应时,仅有 Shield Standard 是不够的;这是一个反复出现的陷阱。Advanced 还为因攻击触发的扩缩提供成本保护。当提到“最少实施工作量”且架构中已包含 Global Accelerator 或 ALB 时,答案通常是启用 Shield Advanced 并附加 AWS 托管的 WAF 规则组,而不是构建自定义的 Lambda@Edge 或迁移 CDN。
应用层保护:AWS WAF
AWS WAF 可附加到 CloudFront、Application Load Balancer、API Gateway、AppSync、App Runner 和 Cognito 用户池。它不直接保护 Network Load Balancer(需要将 CloudFront 置于其前)。它检查 L7 流量并应用规则来防御 SQL 注入、XSS,以及实施大小限制、地理封锁、IP 信誉和速率限制。AWS 托管规则提供了精选的规则组,例如 AWSManagedRulesCommonRuleSet 和 AWSManagedRulesSQLiRuleSet,无需用户编写正则表达式。
基于速率的规则是防御 HTTP 洪水攻击和凭证填充攻击的主要手段——它们计算每个源 IP(或每个转发的标头)在五分钟窗口内的请求数,并自动阻止违规者:
Rules:
- Name: RateLimitPerIP
Priority: 1
Statement:
RateBasedStatement:
Limit: 2000 # per 5-min window per IP
AggregateKeyType: IP
Action: { Block: {} }
VisibilityConfig:
CloudWatchMetricsEnabled: true
MetricName: RateLimitPerIP
SampledRequestsEnabled: true
WAF 不是 DDoS 服务——那是 Shield 的职责。WAF 是对资源策略(如拒绝非 TLS 连接的 S3 存储桶策略、限制可访问存储桶的 VPC 端点策略)和网络控制(安全组、NACL)的补充——任何单一层的错误配置都绝不能导致数据暴露。
网络隔离:安全组、NACL、Network Firewall
在 VPC 内部,防御是分层的:
- 安全组是状态化的,应用于 ENI,只支持允许规则,并会评估所有规则。返回流量被自动允许,因此无需显式开放临时端口。
- 网络 ACL 是无状态的,应用于子网,同时支持允许和拒绝规则,并按数字顺序进行评估。因为它们是无状态的,如果您允许入站 443 端口,您必须同时允许出站临时端口 1024–65535 以便响应流量通过。忘记这一点会导致所有回复被悄无声息地丢弃。安全组没有这个问题。
- AWS Network Firewall 提供深度包检测、与 Suricata 兼容的 IPS 规则以及基于域名的出口过滤,它位于子网和 IGW/TGW 之间,用于集中式检查。
假设仅有安全组就足够,会忽略子网级别的威胁和爆炸半径控制;假设仅有 NACL 就足够,则会忽略其无状态性和粗粒度的缺点。
陷阱目录
忘记信任策略。 角色的权限策略授予能力;只有信任策略才授予被代入的能力。对于跨账户或服务到服务的访问,两者都必须开放才能生效——无论身份策略多么宽松,调用者在 sts:AssumeRole 上都会收到 AccessDenied。
IAM 策略没有匹配的密钥策略。 IAM 中的 kms:Decrypt 权限是必要的,但不是充分的。密钥策略必须要么指明主体,要么通过 Principal: {"AWS": "arn:aws:iam::ACCOUNT:root"} 委托给 IAM。当只完成了 AMI 共享而未更新密钥策略时,加密 AMI/快照的共享会失败。
将 SCP 视为授权。 SCP 只是设定上限,从不授予权限。如果没有匹配的身份策略,Allow s3:* 的 SCP 不起任何作用。反之,一个宽松的身份策略会受到该账户路径上任何 SCP Deny 规则的限制。
假设 KMS 自动轮换。 客户管理的 CMK 在启用之前不会轮换;导入的密钥材料永远不会自动轮换。
为受合规控制的数据选择 SSE-S3。 SSE-S3 没有密钥策略,没有 CloudTrail 可见性,也没有撤销路径——它无法满足任何提及“管理”、“控制”、“审计”或“撤销”密钥的要求。
认为静态加密就足够了。 静态加密和传输中加密是相互独立的。使用 KMS 的 RDS 仍然需要设置 require_secure_transport=ON 和客户端 CA 验证。
存储桶策略中单独指定账户。 这种方式无法扩展,并且在组织变更时会中断。应使用 aws:PrincipalOrgID。
任何地方都硬编码访问密钥。 在用户数据、.env 文件、CloudFormation 参数、Git 中——永远都是错误的。应使用实例配置文件、任务角色、执行角色、IRSA/Pod Identity 或 Roles Anywhere。
使用根用户进行日常工作或附加策略。 根用户不受 IAM 或 SCP 的约束;为根用户添加策略是毫无意义的。任何这样做地答案从根本上就是错误的。
使用 IAM 用户进行跨账户访问。 IAM 用户不能被跨账户代入;应在目标账户中创建一个角色,并让源账户的主体代入该角色。
NLB 置于 WAF 之后。 WAF 不支持附加到 NLB。如果需要 L7 过滤,请在 NLB 前面放置 CloudFront。
NACL 缺少出站临时端口规则。 无状态的 NACL 需要明确的回程路径规则。缺少 1024–65535 出站规则会悄无声息地中断所有入站 443 端口的响应。
使用 Shield Standard 进行托管式响应。 Standard 是被动的,无法访问 SRT;只有 Advanced 才能满足“主动托管式响应”或“成本保护”的要求。
← 应用集成、消息传递与流处理 · 所有领域 · 管理、运维、可观测性与成本 →
练习这些题目 → · 在 ExamRoll.io 上限时练习 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
通过考试 →