亚马逊AWS官方博客
利用 Amazon Athena managed query results 让 AWS DevOps Agent 查询 Amazon S3 中的日志
摘要:DevOps Agent 提交的 Athena 查询能扫到数据,却每次都在把结果写回 S3 的时候失败,给 Agent Space 的 role 补上 s3:PutObject 也没有用。原因是 guardrail 是一份 session policy,里面没有任何 S3 写权限,最终生效的权限是 role 上的策略和这份 session policy 的交集。本文给出完整的配置步骤,以及几个需要注意的限制。
一、引言
在做安全运营的时候,我们需要让 AWS DevOps Agent 替我们查询并分析保存在 Amazon Simple Storage Service (Amazon S3) 里的日志。日志桶和 Amazon Athena 表都已经就绪,但是查询会失败,原因是缺少 AWS Identity and Access Management (IAM) 权限。给 Agent Space 的 role 补上 Athena 权限,再把结果桶的 s3:PutObject 也加上之后,查询能提交,也能扫到数据,却每次都在把查询结果写回 S3 的时候报错:
换一个结果桶,换一个前缀,这个报错都不会消失。
原因是 DevOps Agent 的 guardrail。它 assume Agent Space 的 role 时会带一份 session policy,最终生效的权限是 role 上的 identity policy 和这份 session policy 的交集,而 session policy 里没有任何 S3 写权限。所以在 role 上补权限没有用。
解决办法是新建一个开启了 managed query results 的 Athena workgroup,让查询结果由 Athena 自己保管,整个查询过程不需要往 S3 写任何东西。
官方文档 Limiting Agent Access in an AWS Account 的 guardrail 动作表里提到:
s3:PutObject permissions.
本文将介绍完整的 managed query results 配置过程,每一步要解决的问题,以及几个需要注意的限制。
二、现象
AWS WAF、AWS CloudTrail、Application Load Balancer 和 Amazon CloudFront 的访问日志、VPC Flow Logs,凡是存在 S3 里、用 Athena 建表来查的,DevOps Agent 查起来都会碰到同样的两层 IAM 权限限制,并且和日志通过何种方式推送到 S3 无关。下文拿 WAF 日志举例。
- 第一层:role 上没有 Athena 查询权限,
athena:StartQueryExecution直接返回 AccessDenied。 - 第二层:guardrail 截掉了
s3:PutObject,Athena 在写结果时失败。
三、第一层限制:role 上没有 Athena 查询权限
在控制台创建 Agent Space 时,默认会给 role 挂三个策略:AWS 托管的 AIDevOpsAgentAccessPolicy,再加上控制台当场生成的两个(AIDevOpsCreateServiceLinkedRolePolicy-* 和 AIDevOpsAllowSecretsManagerActionsPolicy-*)。后两者管的是 service-linked role 和 AWS Secrets Manager,跟 Athena 无关。
在托管策略 AIDevOpsAgentAccessPolicy 里,Athena 只有读类动作(athena:GetWorkGroup、athena:List* 等),没有 athena:StartQueryExecution、athena:GetQueryResults;S3 只有桶级别的 Get/List,没有读对象用的 s3:GetObject。
这一层限制好解决,在 role 上补权限就可以。
四、第二层限制:guardrail 截掉了 s3:PutObject
DevOps Agent(aidevops.amazonaws.com)assume role 的时候携带 session policy。这份 session policy 不挂在 role 上,而是 DevOps Agent 调用 AssumeRole 时当场传进来的两个请求参数:policyArns 指向几份 AWS 托管策略,policy 参数里再带一份 inline 策略。您无法修改它,也无法在 IAM 控制台里看到它。
跑 Athena 查询的那个 session,CloudTrail 里记录的 requestParameters 如下:
policy 字段就是那份 inline 策略,CloudTrail 把它记成一个 JSON 字符串,所以里面的引号都带着转义。
AIDevOpsAgentAccessPolicy 和 ReadOnlyAccess 对 S3 都只有读权限,policy 参数里那份 inline 策略只多给了 Athena 的启停查询(athena:S*QueryExecution 只能匹配到 StartQueryExecution 和 StopQueryExecution)、kms:Decrypt 等几个动作。整个 session policy 里没有任何 S3 写权限。于是:
- role 上加
s3:PutObject不起作用,交集里没有它。 - 更换 Athena 查询结果桶不起作用。
- Athena 默认要把查询结果写进 S3(workgroup 的
OutputLocation,或者调用方传的ResultConfiguration),但是 DevOps Agent 写不进去,所以查询失败。
同一个 role 还会被 assume 出别的 session,它们带的 session policy 更窄,只有 AIDevOpsAgentAccessPolicy,ReadOnlyAccess 和 inline 策略都没有,S3 写权限自然也没有。
权限限制不容易排查
IAM 控制台的 role 页面上看不到 session policy。IAM 的策略模拟器也不看 session policy。aws iam simulate-principal-policy(控制台里的 IAM Policy Simulator 用的就是这个 API)只按 role 身上挂的策略来模拟。role 上给了 s3:PutObject 时它回答 allowed,而 DevOps Agent 实际调用却被拒绝。
DevOps Agent 写查询结果失败时,Athena 的报错里没有 session policy 字样,从报错信息里看不出是因为什么原因被拒绝的。session policy 的实际内容只能在 CloudTrail 的 AssumeRole 事件里看到,而且要到 Agent Space 所在的 Region 去查:
排查过程中我们也试过 elevated role,但解决不了这个问题。配好 elevated role 并打开 elevated actions 之后,在 chat 里直接让它往 S3 写一个对象,确实会弹出审批。但 DevOps Agent 执行 Athena 查询时,既不弹审批也不换 role,仍然用普通 role 提交,仍然在写结果那一步失败。investigation 则直接拒绝做写操作。
五、解决步骤
5.1 第一步:新建一个开启 managed query results 的 workgroup
在 Athena 表所在的 Region,也就是这张表所属的 AWS Glue Data Catalog 的 Region,创建一个 workgroup。查询会在这个 Region 里跑,日志桶通常也在这里。Agent Space 在别的 Region 没有关系,我们实测过 Agent Space 和 workgroup 跨 Region 的组合,可以正常工作。
请注意: 命令里的 devops-agent 只是一个示例名字,您可以换成任意名字。下文都拿这个名字举例,您换名字之后,后面几步要跟着改成一致的。
不要去改 primary,要新建一个。 开了 managed query results 的 workgroup 不能再设 OutputLocation,也不支持 result reuse。别的客户端如果在 primary 上显式传 OutputLocation 或者开了 result reuse,改了 primary 它们会直接失败。实测:调用方传了 ResultConfiguration 的查询,在 managed workgroup 上会在 StartQueryExecution 这一步就被拒绝,报 ManagedQueryResultsConfiguration and ResultConfiguration cannot be set together. 错误,把 workgroup 的 Enforce 打开也一样。
5.2 第二步:给 Agent Space 的 role 加一份自定义策略
修改创建 Agent Space 时自动创建的那个 role,默认 role 名是 DevOpsAgentRole-AgentSpace-<后缀>(创建 Agent Space 的时候可以改名)。在 DevOps Agent 控制台里打开这个 Agent Space,Capabilities 标签页的 Cloud 区域能看到它用的是哪个 role。
给这个 role 加一份自定义策略,只给查询这个 workgroup 需要的 Athena 动作,加上日志桶的读权限。不要加 s3:PutObject,加了也不生效。
几点说明:
- Glue 的读权限(
glue:GetDatabase、GetTable、GetTables、GetPartitions)默认策略里已经有了,不用加。用分区投影的表,以及在 Glue 里登记分区的表,实测都不需要额外的 Glue 权限,glue:BatchGetPartition也不需要。 - 这里的
s3:GetObject是读日志数据用的,属于第一层权限限制,默认策略里没有,加到 role 上就能生效,因为跑 Athena 查询那个 session policy 里的ReadOnlyAccess包含它。s3:ListBucket和s3:GetBucketLocation默认已有,写上也没坏处。 - 写查询结果要用的
s3:PutObject属于第二层权限限制,加到 role 上不生效,所以干脆不加,靠第一步的 managed query results 绕开。 - 日志桶如果使用 AWS Key Management Service (AWS KMS) 客户托管密钥做了加密,还要在 role 上增加那个 key 的
kms:Decrypt权限,并确认 key policy 允许这个 role。kms:Decrypt在 session policy 里,所以这条能生效。不加的话会遇到no identity-based policy allows the kms:Decrypt action错误。
5.3 第三步:把 Athena 表事先建好
session policy 里也没有 glue:CreateTable,所以 DevOps Agent 建不了表。需要用 AWS CloudFormation、Glue crawler 等工具,或者用您自己的凭证跑一次 CREATE EXTERNAL TABLE,先把表建好。
5.4 第四步:告诉 agent 用这个 workgroup,而且不要传 ResultConfiguration
agent 调用 StartQueryExecution 时要带上第一步建的那个 workgroup,并且不传 ResultConfiguration 和 OutputLocation。它自己不会主动去找这个 workgroup,要明确告诉它。
写的内容放进 Agent Space 的 agent instructions(AGENTS.md)。下面是一个样例:
表名、Region、workgroup 名换成您自己的。关键是要明确指示 DevOps Agent 用哪个 workgroup,并且不能传结果位置。
写进去有两种方式。一种是在 Operator Web App(DevOps Agent 的网页端)里按用户指南 Agent instructions 的路径操作:进 Agents 页,打开任意一个 managed agent,在 Agent definition 标签页里编辑 Global instructions (AGENTS.md) 并保存。Global instructions 对这个 Agent Space 里所有 agent 都生效。
另一种是用 API:
metadata 里必须带 agent_type,如果不带会报 agent_type is required for AgentsMd knowledge items 错误。根据官方文档 Managing assets,agent_type 可选 GENERIC、CHAT、INCIDENT_TRIAGE、INCIDENT_RCA(investigation 用的)等,每种最多一份,内容是 markdown,不超过 25 KB。实测只需要建一份 agent_type: GENERIC,chat 和 investigation 都能生效,提问时不用再提 workgroup,agent 会自己带上 devops-agent 并且不传 ResultConfiguration。
不写 instructions 也不是完全不能用,但表现不稳定:有时候 agent 被拒之后就放弃了,有时候自己摸到了这个 workgroup 并答对。所以要么写 instructions,要么每次提问都在问题里写明 workgroup 名。
5.5 第五步:验证
在 DevOps Agent 里提一个需要查日志才能回答的问题,比如某个时间段内某个 URI 的请求数。它自己把查询跑完并给出答案,配置就算生效了。如果它答不出来,到 Athena 控制台检查最近的查询记录,错误信息会告诉您缺哪一步。
六、这个方案的限制
- 托管的查询结果只保留 24 小时。过期后
GetQueryResults报The result for this query has expired. Please run the query again to view the results,要再看就得重新跑查询,按扫描量重新计费。调查过程中已经写进结论的内容不受影响。 - managed workgroup 不支持 result reuse,24 小时内重复同一条查询也会重新扫描。
- Athena 的托管结果本身支持用客户托管密钥加密,但 DevOps Agent 用不了,只能用默认的 AWS owned key。改用客户托管密钥会在
StartQueryExecution时就被拒绝,报User is denied access to the KMS key for encrypting query results,因为这时需要的kms:GenerateDataKey不在 session policy 里。 AIDevOpsAgentAccessPolicy和 session policy 都由 AWS 管理,具体内容以后可能会变。
七、如果日志存储在 Amazon CloudWatch Logs
不需要这个规避方案。logs:StartQuery、logs:GetQueryResults、logs:StopQuery 本来就在 AIDevOpsAgentAccessPolicy 里,CloudWatch Logs Insights 查询也不需要往 S3 写东西。只用默认策略,带上任意一种 session policy,实测 Logs Insights 查询都能跑完。
八、总结
DevOps Agent 的有效权限是 role 和 guardrail 的交集,guardrail 里没有 S3 写权限,所以不要让 Athena 往 S3 写东西。规避方案的所有步骤都是基于这个原则展开的,新建一个开 managed query results 的 workgroup,role 上只补读权限,事先建表,再在 agent instructions 里把 workgroup 写清楚。
遇到 Access denied when writing output to url 这个报错时,不必再去怀疑桶策略、KMS 或者缓存,也不用去尝试 elevated role。
配好之后,DevOps Agent 就能直接查 S3 里的 WAF、CloudTrail、CloudFront 等日志,替您完成安全运营的调查工作。
➡️ 下一步行动:
相关产品:
- Amazon Athena — 使用 SQL 在 S3 中查询数据
- Amazon S3 — 适用于 AI、分析和存档的几乎无限的安全对象存储
- Amazon DevOps Agent — 解决和预防事故的代理
- Amazon WAF — Web 应用程序防火墙
- Amazon CloudTrail — 审计跟踪
相关文章:
- Amazon Bedrock AgentCore 数据持久化文件系统:Session Storage 和 Amazon EFS / S3 Files
- 使用 AWS Security Agent 构建应用安全闭环——从代码提交到漏洞修复的自动化之路
- 星合互娱借助 AWS DevOps Agent 构建多游戏智能运维体系
- 将 AWS DevOps Agent 智能运维能力延伸到中国区
- AWS DevOps Agent × MCP Server:打通混合云网络排障的最后一公里
*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。
本篇作者
AWS 架构师中心:云端创新的引领者探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用 |
![]() |

