本文介绍 ACS Agent Sandbox 在网络隔离、存储安全、凭据管理和运行时安全四个维度的安全能力,并提供多种最佳实践帮助你构建纵深防御体系。
安全能力总览
ACS Agent Sandbox 提供的安全能力涵盖网络隔离、存储安全、凭据与身份管理等多个安全域。
|
安全域 |
阿里云提供的能力 |
|
计算隔离 |
Agent Sandbox 沙箱隔离 |
|
网络隔离 |
专属 VSwitch + 企业安全组 + L4 TrafficPolicy + L7 SecurityProfile |
|
存储安全 |
CSI 动态挂载 + 临时 Token 鉴权 + ReadOnly + subPath 隔离 |
|
凭据管理 |
AgentIdentity + ServiceAccount 禁用 + KMS 凭据管家 |
|
访问控制 |
AgentRole/AgentRoleBinding + RBAC |
|
可观测 |
出站流量审计 Webhook + Prometheus 监控集成 |
|
运行时安全 |
Agent 安全中心 + Agentic SOC(SIEM+SOAR) |
网络安全能力与最佳实践
阿里云提供的网络安全能力
网络分区信任模型
按信任等级将集群工作负载划分为三个网络分区,沙箱应使用独立 vSwitch + 独立企业安全组隔离,具体的网络分区架构请参考Agent Sandbox网络规划与扩容
|
网络分区 |
信任等级 |
典型组件 |
vSwitch |
安全组 |
|
托管侧系统组件 |
高 |
Kube API Server、CCM、ack-agent-sandbox-controller、ack-agent-identity |
控制面交换机 |
控制面安全组 |
|
非托管侧系统组件 |
中 |
ack-sandbox-manager |
控制面交换机 |
控制面安全组 |
|
沙箱算力 |
不可信 |
Sandbox Pod |
独立 vSwitch |
独立企业级安全组 |
ACS Agent Sandbox 支持三种网络策略模式,安全能力递增:
|
模式 |
annotation 值 |
能力 |
依赖组件 |
|
基础网络策略 |
|
仅支持原生 K8s NetworkPolicy |
— |
|
流量策略 |
|
L4 出入站流量管理(TrafficPolicy CRD) |
Poseidon |
|
增强型流量策略 |
|
L4(TrafficPolicy) + L7 出站管理(SecurityProfile CRD),自动注入 traffic-proxy Sidecar |
ack-sandbox-manager (≥0.6.1)+ Poseidon |
专属 VSwitch(子网隔离)
ACS Agent Sandbox 支持为沙箱 Pod 指定独立的 VSwitch,将沙箱流量与集群控制面和业务 Pod 在网段层面物理隔离。
annotations:
network.alibabacloud.com/vswitch-ids: "vsw-****"
企业安全组(VPC 边界防护)
支持为沙箱 Pod 配置专属企业安全组,提供 VPC 级别的粗粒度边界防护。
annotations:
network.alibabacloud.com/security-group-ids: "sg-****"
TrafficPolicy 和 GlobalTrafficPolicy(L4 Pod 级微隔离)
基于 Poseidon 组件提供 Pod 粒度的 L4 出入站流量控制,支持 IP 段、Service Label 和 FQDN 匹配。ACS 提供两种资源,共享相同 Spec,区别在作用范围:
|
属性 |
TrafficPolicy |
GlobalTrafficPolicy |
|
作用范围 |
命名空间级 |
集群级 |
|
|
本命名空间所有 Pod |
全集群所有 Pod |
|
典型场景 |
应用级精细规则 |
全集群安全基线 |
|
API Group |
|
同左 |
策略执行规则:优先级 1-1000(数值越小越高)→ 同优先级内按定义顺序 → 命中即止 → Pod 被任一策略选中后,未显式允许的流量默认拒绝。具体规则在前、兜底规则在后。
FQDN 匹配限制:不支持泛域名、依赖动态 DNS 解析有延迟、多域名解析到同 IP 时无法区分 allow/deny。建议仅用于内部服务;公网/泛域名场景改用 SecurityProfile 的 L7 域名匹配。
SecurityProfile(L7 增强型出站控制)
SecurityProfile 是 ACS Agent Sandbox 独有的 L7 层出站流量管控能力,通过自动注入的 traffic-proxy Sidecar 透明拦截所有出站请求,在 egress-gateway 层进行安全策略评估。
架构流程:
核心组件(部署在 sandbox-traffic-system 命名空间):
|
组件 |
职责 |
|
gateway-controller |
控制面,负责 traffic-proxy 和 egress-gateway 的配置管理与下发 |
|
egress-gateway |
出站网关,统一接收和转发集群内所有沙箱出站流量 |
|
traffic-extension |
策略执行引擎,执行出站流量管控策略(流量拦截、令牌注入等) |
|
traffic-proxy(Sidecar) |
注入到沙箱 Pod,透明拦截出站流量转发至 egress-gateway |
SecurityProfile 支持的匹配维度:
|
维度 |
字段 |
说明 |
|
域名 |
|
支持 |
|
URL 路径 |
|
支持 Prefix / Exact / Regex(RE2) |
|
HTTP 方法 |
|
GET / POST / PUT / DELETE / PATCH 等 |
|
端口 |
|
数组,如 |
|
请求头 |
|
支持 Exact / Prefix / Regex |
|
查询参数 |
|
支持 Exact / Prefix / Regex |
规则匹配逻辑:
-
同一
match条目内多个字段为 AND 关系 -
多个
match条目之间为 OR 关系 -
规则链按顺序执行,Block/Bypass 为终结动作,匹配后停止后续评估
支持 HTTPS 流量管控:启用 TLS termination 后,egress-gateway 对指定域名的 HTTPS 请求进行 TLS 终止,解密后应用 SecurityProfile 规则,对沙箱应用完全透明。
TrafficPolicy和SecurityProfile的典型能力如下:
|
匹配维度 |
TrafficPolicy |
SecurityProfile |
|
IP CIDR |
支持 |
— |
|
Service (namespace + name) |
支持 |
— |
|
FQDN 域名 |
支持(仅精确) |
支持(精确 + 通配) |
|
入站控制 |
支持 |
— |
|
端口 |
支持 |
支持 |
|
URL 路径 |
— |
支持(Prefix / Exact / Regex) |
|
HTTP 方法 |
— |
支持(GET/POST/PUT/DELETE...) |
|
请求头 |
— |
支持(Exact / Prefix / Regex) |
|
查询参数 |
— |
支持(Exact / Prefix / Regex) |
网络安全最佳实践
实践1:使用 enhanced-traffic-policy 模式
|
TrafficPolicy |
SecurityProfile |
|
|
定位 |
L4——按 IP、端口、协议决定「能不能连」 |
L7——按域名、路径、方法、请求头决定「能不能访问这个 API」 |
|
工作层级 |
L4(TCP 层) |
L7(HTTP/HTTPS 层) |
|
管控方向 |
出站 + 入站 |
仅出站 |
注意:enhanced-traffic-policy 模式同时包含 L4(TrafficPolicy)和 L7(SecurityProfile)能力。选择该模式即可同时使用两种策略,无需单独启用 traffic-policy 模式。
Agent Sandbox 通过 network.alibabacloud.com/network-policy-mode 注解(Annotation)指定网络策略模式:
network.alibabacloud.com/network-policy-mode: enhanced-traffic-policy
一个完整的配置示例如下:
apiVersion: agents.kruise.io/v1alpha1
kind: Sandbox
metadata:
name: sample
namespace: default
spec:
runtimes:
- name: agent-runtime
template:
metadata:
labels:
agent: sample
alibabacloud.com/compute-class: agent-sandbox
annotations:
network.alibabacloud.com/network-policy-mode: enhanced-traffic-policy
spec:
containers:
- name: sandbox
image: registry-cn-zhangjiakou.ack.aliyuncs.com/acs/code-interpreter:v1.6 # 替换成实际集群所在的地域
command: ["/bin/sleep", "infinity"]
实践2:默认拒绝所有内网访问
沙箱中运行的是不可信的 AI 生成代码,必须假设沙箱内代码可能被提示注入攻击。配置 TrafficPolicy 默认拒绝所有内网段:
apiVersion: network.alibabacloud.com/v1alpha1
kind: TrafficPolicy
metadata:
name: agent-internet-only-policy
namespace: default
spec:
priority: 100
selector:
matchLabels:
app: agent
egress:
rules:
# 允许 DNS
- action: allow
to:
- service:
namespace: kube-system
name: kube-dns
# 禁止访问私有网络
- action: deny
to:
- cidr: 10.0.0.0/8
- action: deny
to:
- cidr: 172.16.0.0/12
- action: deny
to:
- cidr: 192.168.0.0/16
实践3:限制ECS元数据服务
阿里云 ECS metadata endpoint(100.100.100.200)可被沙箱内代码访问以获取实例角色临时凭证,导致凭据泄露。这是最关键的安全配置之一。
- action: deny
to:
- cidr: 100.100.100.200/32
建议用高优先级 GlobalTrafficPolicy(优先级 1)全集群禁止访问元数据服务,确保任何应用策略都无法绕过(见实践6)。
实践4:仅白名单开放必要外部访问
如果沙箱需要访问外部资源(如 OSS endpoint),使用 FQDN/CIDR 白名单精确放行:
egress:
rules:
# 允许 DNS
- action: allow
to:
- service:
namespace: kube-system
name: kube-dns
# 允许特定 OSS endpoint
- action: allow
to:
- fqdn: your-bucket.oss-cn-hangzhou-internal.aliyuncs.com
# 禁止沙箱访问沙箱网关从而跳转访问其他沙箱
- action: deny
to:
- service:
name: sandbox-gateway
namespace: sandbox-system
- service:
name: sandbox-manager
namespace: sandbox-system
# 按需允许公网(仅当 Agent 需要互联网访问时)
- action: allow
to:
- cidr: 0.0.0.0/0
FQDN 有解析延迟和多域名同 IP 的限制,公网/泛域名场景优先用 SecurityProfile L7 域名匹配(实践11)。
实践5:限制 Ingress 仅允许管控面访问
沙箱 Pod 不应接受任意来源的入站连接。优先按管控组件交换机网段放行(无 Pod IP 解析延迟),Service 匹配为辅,并补全 webhook 组件:
# Ingress 规则
- action: allow
from:
- service:
namespace: sandbox-system
name: sandbox-gateway
- service:
namespace: sandbox-system
name: sandbox-manager
- service:
namespace: sandbox-system
name: sandbox-controller-manager-webhook-service
- action: deny
from:
- cidr: 0.0.0.0/0
控制面/非托管组件交换机网段在集群信息>基本信息>网络>控制面交换机查看。
实践6:使用 GlobalTrafficPolicy 建立全集群安全基线
用 GlobalTrafficPolicy 对全集群 Pod 施加"任何沙箱都不能突破"的兜底规则,避免逐 namespace 重复配置、防漏配。
-
高优先级 gtp(优先级 1):元数据服务硬禁,不可被任何应用策略覆盖。
-
低优先级 gtp(优先级 1000):内网网段、跨沙箱访问兜底。
-
应用级 tp(优先级 50-200):特定 Agent 的精细放行。
apiVersion: network.alibabacloud.com/v1alpha1
kind: GlobalTrafficPolicy
metadata:
name: global-metadata-hard-deny
spec:
priority: 1 # 最高优先级,不可被覆盖
selector: {} # 全集群所有 Pod
egress:
rules:
- action: deny
to:
- cidr: 100.100.100.200/32
---
apiVersion: network.alibabacloud.com/v1alpha1
kind: GlobalTrafficPolicy
metadata:
name: global-sandbox-baseline
spec:
priority: 1000 # 低优先级兜底
selector: {}
egress:
rules:
- action: deny
to:
- cidr: 10.0.0.0/8
- cidr: 172.16.0.0/12
- cidr: 192.168.0.0/16
- cidr: 100.64.0.0/10
- action: allow
to:
- cidr: 0.0.0.0/0
ingress:
rules:
# 禁止 Sandbox 网段互相访问(防横向移动)
- action: deny
from:
- cidr: 10.8.0.0/16 # 替换为实际 Sandbox vSwitch 网段
- action: allow
from:
- cidr: 0.0.0.0/0
实践7:配置网络策略时需要兼顾系统组件功能需求
配置任何 deny-all 策略前,必须先为下列系统组件放行,否则沙箱功能异常(DNS 不通、凭据注入失败、策略下发异常、无法连接沙箱)。
|
系统组件 |
方向 |
端口/协议 |
漏配后果 |
|
CoreDNS / kube-dns |
出 |
TCP/53、UDP/53 |
所有域名访问失败(含 SDK、OSS endpoint) |
|
Poseidon |
出 |
TCP/9082 |
TrafficPolicy 规则不生效/延迟 |
|
ack-sandbox-manager / sandbox-gateway |
入 |
TCP/49983、49999 |
无法连接沙箱、exec/命令执行失败 |
|
ack-agent-sandbox-controller |
入 |
TCP/49983 |
沙箱创建/管理异常 |
|
ack-agent-identity |
出 |
TCP/8443 |
凭据注入失败(failStrategy=Block 时请求被拒) |
|
enhanced-traffic-policy 网关 |
出 |
TCP/15008、15012 |
SecurityProfile 出站管控失效/请求不通 |
|
监控(Prometheus/node-exporter/Ingress) |
入 |
TCP/9090、9100、10254 |
监控数据缺失 |
|
健康探测 |
入 |
ICMP |
健康检查失败、Pod 被误判 |
实践8:企业安全组配置(组内隔离 + 端口矩阵)
安全组是 VPC/ENI 层的粗粒度边界防护,与 TrafficPolicy(Pod 级精细)是 AND 关系(互补,缺一不可)。
-
为沙箱配置独立企业级安全组,默认即为组内隔离(组内实例默认不互通,防横向移动),无需额外配置。
-
单安全组可关联 ENI 上限 65,536,建议 IP 占用率 ≤ 80%(约 52,000),临近上限扩容(见 实践10)。
安全组规则说明请参考复用或新建沙箱安全组。
实践9:VSwitch 隔离控制面
为沙箱创建独立 VSwitch(如 10.10.0.0/16),不要与集群控制面交换机混用。切勿将沙箱 VSwitch 添加到集群控制面交换机列表中,否则可能因网络隔离策略导致控制面服务异常。
实践10:网络扩容时同步更新安全组与 TrafficPolicy 网段
企业安全组 ENI 上限 65,536;接近上限或交换机 IP 耗尽时需新建一组 vSwitch + 安全组。扩容时必须同步:
-
新 vSwitch 加 NAT SNAT 条目(否则新网段无公网)。
-
目标侧安全组新增放行新 vSwitch 网段的入方向(例如CoreDNS TCP/UDP 53、Poseidon TCP/9082等规则)。
-
检查现有 TrafficPolicy/GlobalTrafficPolicy 是否覆盖新网段。
-
将新 vSwitch + 安全组配置到 Pod(已分配 Sandbox 需重建后生效)。
扩容后验证:hostname -i(IP 落在新 CIDR)、curl https://httpbin.org/ip(SNAT 正常)、getent hosts kubernetes.default.svc.cluster.local(DNS 正常)。
实践11:使用 SecurityProfile 实现 L7 出站精细控制
SecurityProfile 提供了比 L4 TrafficPolicy 更细粒度的出站控制,建议按以下场景配置:
场景 A:白名单模式(推荐生产环境)
只允许沙箱访问已知安全的域名,拒绝其他所有请求:
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: allowlist-only
spec:
selector:
matchLabels:
alibabacloud.com/compute-class: agent-sandbox
rules:
# 放行已知安全域名
- name: allow-aliyuncs
match:
- domains: ["*.aliyuncs.com"]
actions:
bypass: true
- name: allow-llm-provider
match:
- domains: ["dashscope.aliyuncs.com", "api.openai.com"]
actions:
bypass: true
# 兜底拒绝所有
- name: deny-all
match:
- domains: ["*"]
actions:
block:
statusCode: 403
body: '{"error":"access denied: domain not in allowlist"}'
场景 B:使用 SecurityProfile 封锁管理路径防止 SSRF
阻止 Agent 访问管理接口,即使域名被允许:
rules:
- name: deny-management-paths
match:
- domains: ["*"]
paths:
- type: Prefix
value: /admin
- type: Prefix
value: /console
- type: Prefix
value: /dashboard
- type: Prefix
value: /manage
- type: Regex
value: "^/internal/v[0-9]+/.*"
actions:
block:
statusCode: 403
body: '{"error":"management paths are blocked"}'
场景 C:只读模式(限制 HTTP 写操作)
对于仅需读取数据的 Agent,封锁所有写方法:
rules:
- name: read-only-mode
match:
- domains: ["*"]
paths:
- type: Prefix
value: /
methods: ["POST", "PUT", "DELETE", "PATCH"]
actions:
block:
statusCode: 405
body: '{"error":"write operations are not allowed in read-only mode"}'
场景 D:封锁非标准端口防止安全审计绕过
rules:
- name: deny-non-standard-ports
match:
- domains: ["*"]
ports: [8080, 8443, 9090, 3000, 6379, 27017]
actions:
block:
statusCode: 403
body: '{"error":"access to non-standard ports is blocked"}'
实践12:启用 HTTPS 流量管控
对于需要管控 HTTPS 出站的场景(如阿里云 API 调用、第三方 LLM 服务),启用 TLS termination:
# ack-sandbox-manager 组件配置
enhancedTrafficManagement:
egressGateway:
tlsTermination:
includeHosts:
- "*.aliyuncs.com" # 阿里云 API
- "*.openai.com" # OpenAI
- "api.anthropic.com" # Anthropic
excludeHosts:
- "*.cluster.local" # 排除集群内部通信
启用后,系统自动向沙箱 Pod 注入 Gateway CA 证书并配置 SSL_CERT_FILE、NODE_EXTRA_CA_CERTS、REQUESTS_CA_BUNDLE、CURL_CA_BUNDLE 等环境变量,对应用完全透明。
注意:如果对某域名启用了 TLS termination,但沙箱 Pod 未配置 enhanced-traffic-policy annotation(因而未注入 CA 证书),则该沙箱的 HTTPS 请求会因 TLS 握手失败而报错。
实践13:启用审计 Webhook 实现安全事件追踪
SecurityProfile 支持审计 Webhook——当规则匹配时向外部服务发送 HTTP 通知,用于安全审计、异常监控和事件告警。审计为非终结动作,不影响请求处理。
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: audited-policy
spec:
selector:
matchLabels:
security.agents.kruise.io/agent-name: my-agent
audit:
- name: central-audit
when: 'result == "blocked"' # 仅在请求被拦截时审计
webhook:
url: "https://audit.internal.company.com/events"
timeout: 5s
request:
method: POST
headers:
- name: Authorization
value: "Bearer <audit-service-token>"
body:
json:
event: "request_blocked"
result: "{{ .Result }}"
pod: "{{ .Pod.Namespace }}/{{ .Pod.Name }}"
rule: "{{ .Rule.Name }}"
host: "{{ .Request.Host }}"
path: "{{ .Request.Path }}"
method: "{{ .Request.Method }}"
rules:
- name: deny-admin
match:
- domains: ["*"]
paths:
- type: Prefix
value: /admin
actions:
block:
statusCode: 403
body: '{"error":"admin path is blocked"}'
CEL 条件表达式变量(用于 when 字段):
|
变量 |
说明 |
|
|
处理结果: |
|
|
请求目标域名 |
|
|
HTTP 方法 |
|
|
请求路径 |
|
|
发起请求的沙箱 Pod 信息 |
|
|
匹配的 SecurityProfile 名称 |
|
|
匹配的规则名称 |
实践14:启用控制面/数据面流量分离(SandboxGateway)
默认配置下控制面(api.{domain})与数据面(*.{domain})流量都汇聚到 sandbox-manager,控制面故障会波及业务数据通信。切换后数据面改由 sandbox-gateway 转发,实现故障隔离。
-
前置:ack-sandbox-manager ≥ v0.5.2,sandbox-gateway 副本 ≥ 1;控制面安全组放行 TCP/7788;TrafficPolicy 放行来自 sandbox-gateway 的入方向。
-
切换:组件管理 → ack-sandbox-manager → 配置,将
dataplaneService切换为sandbox-gateway(业务低峰期执行,可回滚)。
实践15:启用 SandboxGateway 入站流量认证(推荐 JWT 动态令牌)
仅靠 TrafficPolicy 限制来源 IP 不够,应在 sandbox-gateway 层叠加令牌认证。sandbox-gateway 提供两种认证方式,优先选用基于 JWT 的动态令牌认证:
|
维度 |
静态 Access Token(v0.6.6 起) |
基于 JWT 的动态令牌(v0.6.8 起,推荐) |
|
请求头 |
|
|
|
Token 格式 |
随机 UUID |
非对称签名 Compact JWT |
|
签发方 |
sandbox-manager |
|
|
校验方式 |
常量时间字符串比对 |
本地验证 JWT 签名、标准 Claims 及 Sandbox ID/UID 绑定 |
|
有效期 |
与 Sandbox 生命周期一致,静态不变 |
签发参数控制,失效可重新签发 |
|
泄露重放窗口 |
持续到 Sandbox 销毁 |
限制在 JWT 有效期内 |
|
持久化 |
写入 Sandbox CR 注解 |
不写入 CR,仅在创建响应中返回 |
|
Token 获取字段 |
创建响应的 |
创建响应的 |
|
校验失败响应 |
HTTP |
HTTP |
为什么推荐 JWT 动态令牌:静态 Token 是数据面/envd 凭据,一旦泄露可重放至 Sandbox 销毁,且明文持久化在 CR 注解中;JWT 是数据面代理专用凭据、非对称签名、绑定 Sandbox ID/UID、失效可重签,泄露窗口受有效期约束,且不落盘到 CR,适合限时失效、防重放、多租户隔离场景。
开启方式请参考 基于 JWT 的动态令牌认证。
存储安全能力与最佳实践
阿里云提供的存储能力
|
能力 |
说明 |
|
CSI 动态挂载 |
Sidecar 注入 CSI 插件,支持沙箱运行时动态挂载 OSS 存储卷(需 |
|
Agent Identity 认证 |
|
|
多卷挂载与 subPath 隔离 |
通过 |
|
readOnly 挂载 |
只读挂载防止沙箱篡改共享数据 |
两层权限模型:
-
第一层 RAM 角色(最大权限边界):RAM 控制台创建,覆盖所有 Sandbox 可能访问的 Bucket 范围,绑定 RRSA OIDC。
-
第二层 CredentialProvider 策略(实际生效权限):集群内
CredentialProviderCR 定义,必须是第一层子集,支持模板函数按每个 Sandbox 声明的 Bucket 和子路径动态收缩。 -
最终权限 = RAM 角色和CredentialProvider 策略的交集,仅对该 Sandbox 声明的 Bucket/subPath 生效。
存储安全最佳实践
实践16:默认 readOnly 挂载共享存储
除非明确需要写入,共享存储卷一律只读挂载。
# SandboxClaim 方式
dynamicVolumesMount:
- pvName: oss-pv-sandbox-system
mountPath: "/data/readonly"
subPath: "tenant-a/datasets"
readOnly: true
attributes:
credentialProviderName: "oss-ro"
实践17:使用 subPath 实现租户级数据隔离
不同租户挂载同一 PV 时,通过 subPath + 独立 CredentialProvider 确保每个租户只能访问自己的数据子目录,互不可见。
# 租户 A(只读)
metadata = {
"e2b.agents.kruise.io/csi-volume-config": json.dumps([
{"pvName": "oss-pv-sandbox-system", "mountPath": "/data",
"subPath": "tenants/tenant-a", "attributes": {"credentialProviderName": "oss-ro"}}
]),
"security.agents.kruise.io/agent-name": "my-storage-agent"
}
实践18:OSS 凭据使用 Agent Identity + 模板函数(替换静态 AccessKey)
CredentialProvider的policy字段支持使用专用模板函数,由sandbox-controller根据每个Sandbox实例的挂载配置自动填充,无需为每个子路径单独创建CredentialProvider。
|
模板函数 |
作用 |
|
|
限制到 子路径维度 的 Resource(对象级操作 GetObject/PutObject) |
|
|
限制到 Bucket 维度 的 Resource(ListObjects) |
|
|
|
只读 CredentialProvider:
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
name: oss-ro
namespace: <YOUR-NAMESPACE>
spec:
type: RAM
ram:
source:
provider: RRSA
rrsa:
roleName: <YOUR-RAM-ROLE-NAME>
tokenValidity: 1h
policy: |
{
"Statement": [
{
"Action": ["oss:GetObject"],
"Effect": "Allow",
"Resource": {{ build_policy_oss_resource() }}
},
{
"Action": ["oss:ListObjects"],
"Effect": "Allow",
"Resource": {{ build_policy_oss_resource(limit_sub_path=false) }},
"Condition": {
"StringLike": { "oss:Prefix": {{ build_policy_oss_prefix_condition() }} }
}
}
],
"Version": "1"
}
ListObjects 是 Bucket 级操作,必须用 oss:Prefix Condition 限制子路径,否则 Sandbox 可列举整个 Bucket。读写场景改用 oss-rw(含 PutObject/DeleteObject 等)。
授权(AgentRole + AgentRoleBinding):
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRole
metadata:
name: oss-storage-role
namespace: <YOUR-NAMESPACE>
spec:
rules:
- effect: Allow
action: "GetResourceCredential"
resource: "CredentialProvider/oss-ro"
- effect: Allow
action: "GetResourceCredential"
resource: "CredentialProvider/oss-rw"
---
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRoleBinding
metadata:
name: my-agent-oss-binding
namespace: <YOUR-NAMESPACE>
spec:
agentRoleRef:
apiGroup: agentidentity.alibabacloud.com
kind: AgentRole
name: oss-storage-role
subjects:
- authorizationType: "Agent"
agentAuthorizationConfiguration:
agentName: my-storage-agent
更多的模板配置方式请参考为Agent Sandbox挂载OSS存储
实践19:PV 使用 Agent Identity(无需 Secret + 必须 sigv4)
Agent Identity 方式下 PV 无需 nodePublishSecretRef、无需创建 Secret。
apiVersion: v1
kind: PersistentVolume
metadata:
name: oss-pv-sandbox-system
labels:
alicloud-pvname: oss-pv-sandbox-system
spec:
accessModes: [ReadWriteMany]
capacity:
storage: 50Gi
csi:
driver: ossplugin.csi.alibabacloud.com
volumeAttributes:
authType: agent-identity # 固定值
bucket: <YOUR-BUCKET-NAME>
url: https://oss-cn-hangzhou-internal.aliyuncs.com # HTTPS 内网 Endpoint
path: /
otherOpts: "-o sigv4 -o region=cn-hangzhou -o umask=022 -o allow_other" # 必须带 sigv4 + region
volumeHandle: oss-pv-sandbox-system # 必须与 PV 名称一致
persistentVolumeReclaimPolicy: Retain
storageClassName: test
volumeMode: Filesystem
-
otherOpts必须包含-o sigv4和-o region=<实际region>。 -
PV 的
volumeAttributes创建后不可修改,变更鉴权方式需删除重建。
实践20:SandboxSet 与挂载配置
-
SandboxSet 启用
csi+agent-runtime两个 runtime;dnsPolicy必须为ClusterFirst;建议加注解network.alibabacloud.com/wait-clusterip-ready: "*"。 -
挂载时通过
attributes.credentialProviderName指定 CredentialProvider,security.agents.kruise.io/agent-name关联 AgentIdentity(名称必须完全一致,区分大小写)。 -
同一 Sandbox 可挂多个 subPath,分别引用
oss-ro/oss-rw实现混合权限。
实践21:使用 HTTPS endpoint 访问 OSS
PV 的 url 使用 HTTPS internal endpoint,防止存储流量被窃听:
url: "https://oss-cn-hangzhou-internal.aliyuncs.com"
实践22:理解 CSI Sidecar 的安全权衡
CSI 动态挂载需要特权容器和 hostPath(/var/run/csi),打破标准容器安全边界。
-
仅在确需动态存储挂载时启用 CSI runtime;
-
仅需静态数据时,考虑镜像内置或 init container 预加载;
-
启用 CSI 时确保 TrafficPolicy 和安全组配置到位作为补偿控制;
-
基于安全共担责任模型——阿里云提供平台安全,用户需承担特权容器带来的额外风险。
OSS 挂载网络放行:使用 Agent Identity 挂载 OSS 时,网络策略必须放行 CredentialProvider(ack-agent-identity/credential-provider,安全组出方向 TCP/8443)、CoreDNS(53)、OSS Endpoint(HTTPS)。验证:telnet credential-provider.ack-agent-identity.svc 8443。
凭据与身份管理安全能力与最佳实践
阿里云提供的凭据安全能力
API Key 多租户认证
sandbox-manager 内置 API Key 认证体系,支持 Team 级别隔离:
-
每个 Team 映射到一个 Kubernetes Namespace
-
API Key 仅能操作所属 Team 的沙箱
-
admin Key 不可删除
ServiceAccount Token 禁用
SandboxSet 模板默认设置 automountServiceAccountToken: false,阻止沙箱获取 Kubernetes API 凭证。
环境变量清洗
支持显式清空 Kubernetes 注入的 Service 环境变量(如 KUBERNETES_SERVICE_HOST),防止泄露集群信息。
出站凭据注入(Agent Identity 体系)
ACS Agent Sandbox 提供了一套完整的出站凭据注入体系,核心设计原则是:沙箱内仅持有假凭证(占位符),真实凭证在 egress-gateway 层动态替换,沙箱永远不接触真实密钥。
五个 CRD 协作实现凭据注入:
两种注入模式:
|
CRD |
API Group |
职责 |
|
|
|
定义 Agent 身份,沙箱通过 Label 关联 |
|
|
|
定义真实凭据来源(K8s Secret 或 RRSA RAM 角色) |
|
|
|
定义权限规则,声明可获取哪些 CredentialProvider 的凭据 |
|
|
|
将 AgentRole 绑定到指定 AgentIdentity,完成授权 |
|
|
|
定义 |
|
模式 |
适用场景 |
工作方式 |
|
API Key 注入 |
第三方 LLM 服务(OpenAI、通义千问等) |
替换请求头中的占位 Token 为真实 API Key |
|
阿里云 STS 凭据注入 |
调用阿里云 OpenAPI |
替换 AK/SK/STS 三元组并重新计算请求签名 |
凭据与身份最佳实践
实践23:禁用 ServiceAccount Token 自动挂载
这是最关键的凭据安全配置。必须确保每个 SandboxSet 的 Pod 模板中都设置:
spec:
automountServiceAccountToken: false
enableServiceLinks: false
-
automountServiceAccountToken: false:阻止挂载 ServiceAccount Token -
enableServiceLinks: false:阻止注入 Service 相关环境变量
如果不设置这两项,沙箱内代码可以:
-
读取
/var/run/secrets/kubernetes.io/serviceaccount/token获取 K8s API Token -
通过环境变量获取 Kubernetes API Server 地址
-
直接调用 Kubernetes API 操控集群资源
实践24:清洗 Kubernetes 环境变量
显式覆盖 Kubernetes 自动注入的环境变量,防止泄露集群拓扑信息:
spec:
containers:
- name: sandbox
env:
- name: KUBERNETES_SERVICE_HOST
value: ""
- name: KUBERNETES_SERVICE_PORT
value: ""
- name: KUBERNETES_SERVICE_PORT_HTTPS
value: ""
实践25:使用凭据注入替代明文凭证
永远不要在沙箱内放置真实凭证。 使用 Agent Identity 凭据注入体系,让沙箱仅持有占位符,真实凭据在网关层替换。
API Key 注入示例(如 LLM API Key):
# 1. 创建 Agent 身份
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentIdentity
metadata:
name: my-agent
namespace: tenant-a
spec:
description: "生产环境 AI Agent 身份"
---
# 2. 将真实 API Key 存入 K8s Secret(集群侧管理,沙箱不可见)
apiVersion: v1
kind: Secret
metadata:
name: llm-api-key
namespace: tenant-a
type: Opaque
stringData:
apiKey: "sk-xxxxxxxxxxxxxxxx" # 真实 API Key
---
# 3. 创建 CredentialProvider 引用 Secret
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
name: llm-api-key
namespace: tenant-a
spec:
type: APIKey
apiKey:
source:
provider: Kubernetes
kubernetes:
secretRef:
name: llm-api-key
keyName: apiKey
---
# 4. 授权:AgentRole + AgentRoleBinding
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRole
metadata:
name: get-llm-key
namespace: tenant-a
spec:
rules:
- effect: Allow
action: "GetResourceCredential"
resource: "CredentialProvider/llm-api-key"
---
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: AgentRoleBinding
metadata:
name: my-agent-get-llm-key
namespace: tenant-a
spec:
agentRoleRef:
apiGroup: agentidentity.alibabacloud.com
kind: AgentRole
name: get-llm-key
subjects:
- authorizationType: "Agent"
agentAuthorizationConfiguration:
agentName: my-agent
---
# 5. SecurityProfile 定义替换规则
apiVersion: agents.kruise.io/v1alpha1
kind: SecurityProfile
metadata:
name: inject-llm-key
namespace: tenant-a
spec:
selector:
matchLabels:
security.agents.kruise.io/agent-name: my-agent
rules:
- name: inject-openai-key
match:
- domains: ["api.openai.com", "dashscope.aliyuncs.com"]
actions:
tokenTransformation:
type: ApiKey
credentialRef:
kind: CredentialProvider
name: llm-api-key
apiKey:
when:
header: Authorization
pattern: "^Bearer .+" # 仅当请求头包含 Bearer token 时替换
targetHeader: Authorization
valueTemplate: "Bearer {{ .Token }}"
沙箱内代码使用任意假 Token 即可:
import openai
client = openai.OpenAI(api_key="fake-token") # 假凭证,网关会替换为真实 Key
阿里云 STS 凭据注入示例(调用阿里云 API):
# CredentialProvider 使用 RRSA 获取 STS 临时凭证
apiVersion: agentidentity.alibabacloud.com/v1alpha1
kind: CredentialProvider
metadata:
name: aliyun-cs-readonly
namespace: tenant-a
spec:
type: RAM
ram:
source:
provider: RRSA
rrsa:
roleName: ack-agent-identity-sample-role
# policy 限制最终颁发的 STS Token 权限范围(必须是角色权限的子集)
policy: |
{
"Statement": [{
"Action": ["cs:Describe*", "cs:Get*", "cs:List*"],
"Effect": "Allow",
"Resource": ["*"]
}],
"Version": "1"
}
沙箱内使用假 AK/SK,SDK 正常调用,网关透明替换并重算签名:
env:
- name: ALIBABA_CLOUD_ACCESS_KEY_ID
value: "FAKE_AK" # 占位符
- name: ALIBABA_CLOUD_ACCESS_KEY_SECRET
value: "FAKE_SK" # 占位符
实践26:使用模板变量实现每沙箱动态权限收窄
CredentialProvider 的 policy 和 secretRef.name 字段支持模板变量,可根据沙箱实例身份动态调整权限范围:
# SandboxClaim 通过 Label 传递业务参数
apiVersion: agents.kruise.io/v1alpha1
kind: SandboxClaim
metadata:
name: user-sandbox
spec:
templateName: my-sandbox-set
replicas: 1
labels:
security.agents.kruise.io/agent-name: my-agent
security.agents.kruise.io/oss-bucket-name: user-bucket-123
security.agents.kruise.io/oss-subpath: user-data/alice// CredentialProvider 的 policy 中引用模板变量
{
"Action": ["oss:Get*", "oss:List*"],
"Effect": "Allow",
"Resource": [
"acs:oss:*:*:${ack:agent-identity/metadata/oss-bucket-name}/${ack:agent-identity/metadata/oss-subpath}/*"
]
}
这实现了每个沙箱实例获得的 STS Token 权限不同,真正的最小权限原则。
可用模板变量:
|
模板变量 |
说明 |
|
|
关联的 AgentIdentity CR 名称 |
|
|
SandboxClaim Label 中的自定义值 |
实践27:设置 failStrategy 为 Block
凭据注入失败时(如 Secret 不存在、STS 配额耗尽),failStrategy 决定请求的处理方式:
actions:
tokenTransformation:
failStrategy: Block # 默认值,凭据获取失败则阻止请求
# failStrategy: Allow # 危险!失败时放行原始请求(含假凭证),仅用于调试
生产环境必须使用 Block(默认值)。如果设置为 Allow,凭据注入失败时请求会带着假凭证 FAKE_AK 发送到目标服务,虽然不会泄露真实凭证,但可能暴露沙箱身份信息。
实践28:注意 STS API 配额
STS 模式依赖 AssumeRoleWithOIDC API 获取临时凭证。需根据实际沙箱实例规模,在配额中心提前申请足够的 API 调用配额,避免因配额不足导致注入失败。
实践29:API Key 生命周期管理
-
立即保存:API Key 明文仅在创建时返回一次,之后无法再次查询
-
定期轮换:建立 Key 轮换机制,删除旧 Key 并创建新 Key
-
最小范围:为每个集成方(每个 Agent 应用)创建独立 Key,而非共享单个 Key
-
监控使用:通过
lastUsed字段审计 Key 使用情况,及时清理未使用的 Key
# 检查 Key 最后使用时间
curl -H "X-API-KEY: $ADMIN_KEY" https://your.domain.com/kruise/api/api-keys
实践30:Namespace 级租户隔离
利用 Team → Namespace 的映射关系实现租户隔离:
-
每个租户对应独立的 Kubernetes Namespace
-
租户的 API Key 仅能操作本 Namespace 内的沙箱
-
配合 Kubernetes RBAC 和 NetworkPolicy 加强 Namespace 间隔离
# 创建租户 Namespace
kubectl create ns tenant-security-team
# 通过 Admin Key 为租户创建 API Key
curl -X POST -H "X-API-KEY: $ADMIN_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "security-team-key", "teamName": "tenant-security-team"}' \
https://your.domain.com/kruise/api/api-keys
实践31:禁用 hostNetwork
确保 SandboxSet 模板中 hostNetwork: false(默认值),防止沙箱直接访问宿主机网络栈:
spec:
hostNetwork: false # 必须确保为 false
实践32:使用非 root 身份启动业务容器
业务容器应以非 root 用户启动,遵循最小权限原则。即使发生容器逃逸或应用漏洞被利用,非 root 身份也能显著缩小攻击者可造成的影响面(无法直接读写沙箱特权路径、无法加载内核模块、无法滥用 root capability)。
在 SandboxSet Pod 模板的 securityContext 中显式声明:
spec:
securityContext:
runAsNonRoot: true # 拒绝以 root(uid 0)启动,启动即校验
runAsUser: 1000 # 指定非 root uid
runAsGroup: 1000
fsGroup: 1000 # 卷属组归属该 gid,保证非 root 可读写挂载卷
containers:
- name: app
securityContext:
allowPrivilegeEscalation: false # 禁止通过 setuid 提权
readOnlyRootFilesystem: true # 根文件系统只读(按需放开可写目录)
capabilities:
drop: ["ALL"] # 丢弃所有 Linux capability
要点:
-
runAsNonRoot: true是硬性门控——若镜像默认以 root 运行且未指定runAsUser,Pod 将启动失败(fail-closed),从而强制暴露"镜像以 root 运行"的问题。 -
不改业务镜像的前提下,可仅通过上述 spec 的
securityContext+fsGroup实现;如业务代码强依赖某路径的写权限,用 initContainer(root)预建目录/软链接并chown到业务 uid。
运行时安全能力与最佳实践
ACS Agent Sandbox 的网络/存储/凭据管控属于预防性基线安全控制(Preventive Controls),但完整的安全体系还需要检测性控制(Detective Controls)和响应性控制(Responsive Controls)。阿里云安全中心提供两个核心产品与 ACS Agent Sandbox 形成互补闭环:
|
产品 |
定位 |
与 Agent Sandbox 的关系 |
|
云原生 SIEM + SOAR,多云日志统一检测与自动化响应 |
接入集群审计日志 + VPC 流日志,检测沙箱层面的异常行为并自动编排响应 |
|
|
AI Agent 专属安全基线检查、漏洞扫描、运行时恶意行为拦截 |
检测 Agent 应用本身的提示注入、越权、凭证泄露等 AI 特有风险 |
实践33:接入 Agentic SOC 实现沙箱威胁闭环
建议:将集群审计日志和 VPC 流日志接入 Agentic SOC,实现沙箱层面的统一威胁检测。
配置步骤:
-
在 Agentic SOC 控制台开通日志接入,选择集群审计日志和 VPC 流日志
-
配置告警关联规则,将同一沙箱 Pod 的多源告警聚合为统一安全事件
-
创建针对 Agent Sandbox 场景的 Playbook(如自动封禁矿池 IP、自动吊销 STS 凭据)
实践34:启用 Agent 安全基线定期扫描
建议:将 ACS Agent Sandbox 中部署的 Agent 应用纳入 Agent Security Center 管理,启用定期安全基线扫描。
关键动作:
-
将 AI 资产接入 Agent安全中心
-
确认 OpenClaw 安全基线中的所有检查项全部通过
-
配置变更后立即执行手动检测,验证无新增风险
-
重点关注:Gateway 绑定地址、明文密码、Skill 白名单、未授权访问
实践35:部署 OpenClaw 实时防护拦截 Agent 运行时威胁
建议:为生产环境的 Agent 安装 OpenClaw 安全防护插件,实时拦截提示注入、恶意命令执行等运行时威胁。
前置条件:
-
服务器已安装 OpenClaw 且 Node.js ≥ 22
-
已开通 AI 安全护栏服务
与 ACS Agent Sandbox 安全能力的协同:
|
安全层 |
ACS Agent Sandbox 能力 |
Agent Security Center 能力 |
协同效果 |
|
网络层 |
SecurityProfile 域名/路径白名单 |
OpenClaw 恶意 URL 拦截 |
双重过滤:先 L7 策略白名单,再恶意 URL 黑名单 |
|
凭据层 |
tokenTransformation 动态注入 |
基线检查:明文密码禁止 |
消除硬编码 + 基线审计双保险 |
|
执行层 |
Pod 级计算隔离 |
恶意命令执行实时阻断 |
即使沙箱内代码被注入,恶意命令也被实时拦截 |
|
检测层 |
审计 Webhook 记录 L7 请求 |
Agentic SOC 多源关联分析 |
L7 审计 + K8s 审计 + VPC 流日志三维关联 |
实践36:建立 Agent Sandbox 安全事件响应 Playbook
建议:在 Agentic SOC 中预配置针对 Agent Sandbox 常见攻击场景的自动化 Playbook。
推荐 Playbook 模板:
|
Playbook 名称 |
触发条件 |
自动化动作 |
|
沙箱挖矿应急 |
检测到挖矿进程 + 矿池连接 |
终止进程 → 隔离文件 → 云防火墙封禁矿池 IP → 通知 |
|
STS 凭据滥用应急 |
STS 调用异常(频率/范围超阈值) |
吊销 STS 凭据 → AgentRole 降权 → 审计溯源 → 通知 |
|
反弹 Shell 应急 |
检测到反弹 Shell 命令 |
阻断连接 → 终止进程 → 取证快照 → 通知 |
|
数据外泄应急 |
OSS 异常大规模下载 |
临时冻结 CSI 挂载权限 → 审计访问日志 → 通知 |
实践37:多产品协同构建 Agent 安全纵深防御
建议:结合ACS Agent Sandbox、Agentic SOC、Agent安全中心、AI 安全护栏等阿里云安全产品能力,构建完整的纵深防御体系。
纵深防御层次:
|
层级 |
典型安全能力 |
|
ACS Agent Sandbox |
|
|
Agent安全中心 |
|
|
Agentic SOC |
|
最小权限原则实施清单
计算层最小权限
|
配置项 |
推荐值 |
说明 |
|
automountServiceAccountToken |
false |
阻止 K8s API 访问 |
|
enableServiceLinks |
false |
阻止 Service 信息泄露 |
|
hostNetwork |
false |
禁止宿主网络 |
|
hostPID |
false |
禁止查看宿主进程 |
|
hostIPC |
false |
禁止宿主 IPC |
|
securityContext.runAsNonRoot |
true |
以非 root 身份启动,缩小逃逸影响面 |
|
securityContext.runAsUser / runAsGroup |
非 0(如 1000) |
指定非 root uid/gid |
|
securityContext.fsGroup |
与 uid 对应 |
卷属组归属,保证非 root 可读写挂载卷 |
|
allowPrivilegeEscalation |
false |
禁止 setuid 提权 |
|
readOnlyRootFilesystem |
true |
根文件系统只读(按需放开可写目录) |
|
capabilities.drop |
["ALL"] |
丢弃所有 Linux capability |
网络层最小权限
|
配置项 |
推荐值 |
说明 |
|
网络策略模式 |
|
获得 L4 + L7 完整安全能力 |
|
元数据服务 |
禁止访问 100.100.100.200/32 |
阻止凭证窃取 |
|
内网访问 |
禁止内网访问 |
阻止横向移动 |
|
DNS |
仅 Allow kube-dns |
仅允许域名解析 |
|
外部访问 |
按需 Allow 特定 FQDN/CIDR |
最小化外部暴露面 |
|
L7 出站 |
SecurityProfile 白名单模式 |
仅允许已知安全域名 |
|
管理路径 |
SecurityProfile 封锁 /admin /console 等 |
防 SSRF 攻击 |
|
HTTP 写操作 |
按需封锁 POST/PUT/DELETE |
只读 Agent 限制写方法 |
|
非标准端口 |
SecurityProfile 封锁 8080/9090/6379 等 |
防止审计绕过 |
|
入站 |
阻止外部探测 |
|
|
安全组 |
独立企业安全组 + 组内隔离 + 端口矩阵(实践8) |
防止沙箱间横向通信 |
|
HTTPS 管控 |
启用 TLS termination |
加密流量也受 SecurityProfile 管控 |
|
审计 |
启用审计 Webhook |
安全事件可追踪 |
|
控制面/数据面 |
分离(SandboxGateway) |
控制面故障不影响数据通信 |
|
Drop RAW_NET |
增加securityContext配置 |
防止用户进行劫持(ping、tcpdump 不可用) |
存储层最小权限
|
配置项 |
推荐值 |
说明 |
|
认证方式 |
Agent Identity(RRSA + STS) |
沙箱不留长期密钥 |
|
共享存储挂载 |
readOnly: true |
默认只读 |
|
subPath |
配置租户专属子目录 |
数据隔离 |
|
CredentialProvider |
模板函数动态收窄到 Bucket/subPath |
每沙箱最小权限 |
|
PV |
authType: agent-identity,无需 Secret,otherOpts 带 sigv4 |
— |
|
存储 endpoint |
HTTPS internal endpoint |
加密传输 |
|
CSI Sidecar |
仅在需要时启用 |
减少特权容器暴露面 |
|
dnsPolicy |
ClusterFirst |
解析 CredentialProvider 域名 |
凭据层最小权限
|
配置项 |
推荐值 |
说明 |
|
外部 API 凭证 |
Agent Identity 凭据注入 |
沙箱仅持有假凭证,网关层替换 |
|
阿里云 API 凭证 |
STS 模式 + RRSA |
临时凭证 + 每实例权限收窄 |
|
CredentialProvider policy |
模板变量动态收窄 |
沙箱维度最小权限 |
|
failStrategy |
|
凭据获取失败时阻止请求 |
|
STS 配额 |
提前申请 |
避免因配额不足导致注入失败 |
|
API Key |
每集成方独立 Key |
故障隔离 + 审计粒度 |
|
镜像内容 |
不含任何凭证 |
避免镜像泄露即凭证泄露 |
|
K8s 环境变量 |
清空覆盖 |
防止集群信息泄露 |