Agent SandboxAgent Sandbox

Protecting Agentic Sandboxes with OPA Gatekeeper使用 OPA Gatekeeper 保护 Agentic Sandbox

This guide provides step-by-step instructions for configuring OPA Gatekeeper security policy to prevent granting permissions to ServiceAccounts used by Sandboxes.本指南提供了配置 OPA Gatekeeper 安全策略的分步说明,以防止向 Sandbox 使用的 ServiceAccount 授予权限。

1. Overview 1. 概述

This guide provides step-by-step instructions for configuring a OPA Gatekeeper security policy on a Kubernetes cluster. The goal of this policy is to prevent any user or process from granting new permissions to a ServiceAccount that is actively being used by a custom Sandbox resource.本指南提供了在 Kubernetes 集群上配置 OPA Gatekeeper 安全策略的分步说明。该策略的目标是防止任何用户或进程向正在被自定义 Sandbox 资源使用的 ServiceAccount 授予新权限。

This acts as a critical security boundary, preventing accidental or malicious privilege escalation for sandboxed environments.这构成了关键的安全边界,可防止沙盒环境发生意外或恶意的权限提升。

How it Works:
The policy intercepts all RoleBinding and ClusterRoleBinding creation requests. If the request targets a ServiceAccount that is referenced by a running Sandbox, OPA Gatekeeper will block the request and return an error.
工作原理: 该策略会拦截所有 RoleBinding 和 ClusterRoleBinding 的创建请求。如果请求的目标是正在运行的 Sandbox 所引用的 ServiceAccount,OPA Gatekeeper 将阻止该请求并返回错误。


2. Prerequisites 2. 前置条件

Before you begin, ensure you have the following:在开始之前,请确保您具备以下条件:

  • kubectl access to a Kubernetes Standard cluster with permissions to install Helm charts.拥有 Kubernetes 标准集群的 kubectl 访问权限,并具备安装 Helm chart 的权限。
  • Helm v3+ installed on your local machine.本地机器上已安装 Helm v3+。

3. Configuration Steps 3. 配置步骤

Step 1: Install OPA Gatekeeper 第 1 步:安装 OPA Gatekeeper

Use the following Helm commands to deploy it to your cluster.使用以下 Helm 命令将其部署到您的集群中。

# 1. Add the official OPA Gatekeeper Helm repository
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts

# 2. Update your local Helm repositories
helm repo update

# 3. Install OPA into its own namespace
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace

You can verify the installation by checking the pods and CRDs in the gatekeeper-system namespace:您可以通过检查 gatekeeper-system 命名空间中的 pod 和 CRD 来验证安装情况:

kubectl get pods -n gatekeeper-system

All pods should be in the Running state.所有 pod 都应处于 Running 状态。

Step 2: Verify Custom Resource Definitions (CRDs) 第 2 步:验证自定义资源定义 (CRD)

Ensure that the Gatekeeper CRDs are present in your cluster:确保 Gatekeeper CRD 存在于您的集群中:

kubectl get crds | grep gatekeeper

If either CRD is not found, stop and resolve that issue before proceeding.如果未找到任一 CRD,请停止操作并先解决该问题,然后再继续。

Step 3: Define the ConstraintTemplate 第 3 步:定义 ConstraintTemplate

The ConstraintTemplate provides the Rego logic that Gatekeeper will use to enforce the policy. This template looks for Pods using the targeted ServiceAccount and checks if they are owned by a Sandbox CR.ConstraintTemplate 提供了 Gatekeeper 将用于执行策略的 Rego 逻辑。此模板会查找使用目标 ServiceAccount 的 Pod,并检查它们是否由 Sandbox CR 所拥有。

Apply the template:应用模板:

kubectl apply -f template-sandbox-binding.yaml

This creates a new CRD called K8sPreventActiveServiceAccountBinding that Gatekeeper will recognize. You can verify it by running the following:这将创建一个名为 K8sPreventActiveServiceAccountBinding 的新 CRD,Gatekeeper 将能够识别它。您可以通过运行以下命令进行验证:

kubectl get crd k8spreventactiveserviceaccountbinding

# You should see a crd like the following:
k8spreventactiveserviceaccountbinding.constraints.gatekeeper.sh   

Step 4: Define the Constraint 第 4 步:定义 Constraint

The Constraint instantiates the template and specifies which resources it should apply to.Constraint 会实例化该模板,并指定应将其应用于哪些资源。

kubectl apply -f constraint-sandbox-binding.yaml

Step 5: Define the Config and understanding Rego logic 第 5 步:定义配置并理解 Rego 逻辑

  • The ConstraintTemplate uses Rego code that tries to look up other resources in the cluster. Specifically, it uses data.inventory to find Pod objects, this is from the Rego logic:ConstraintTemplate 使用的 Rego 代码会尝试查找集群中的其他资源。具体来说,它使用 data.inventory 来查找 Pod 对象,这是来自 Rego 的逻辑:
# Find a pod using this ServiceAccount in the same namespace
pod := data.inventory.namespace[sa_namespace]["v1"]["Pod"][_]
  • This line of code means: “Iterate through all Pods in the same namespace as the ServiceAccount in the RoleBinding/ClusterRoleBinding.”这行代码的意思是:“遍历 RoleBinding/ClusterRoleBinding 中与 ServiceAccount 位于同一命名空间下的所有 Pod。”
  • data.inventory Comes from a Cache: Gatekeeper doesn’t query the Kubernetes API server live for every admission request when data.inventory is used. This would be too slow and overload the API server. Instead, it maintains an in-memory cache of certain Kubernetes resources.data.inventory 来自缓存:当使用 data.inventory 时,Gatekeeper 不会为每个准入请求实时查询 Kubernetes API 服务器。那样做速度太慢且会使 API 服务器过载。相反,它会维护某些 Kubernetes 资源的内存缓存。
  • The Config Resource Populates the Cache: The Config object in the gatekeeper-system namespace, specifically the spec.sync.syncOnly section, tells Gatekeeper which resources to watch and put into its cache.Config 资源填充缓存:gatekeeper-system 命名空间中的 Config 对象(特别是 spec.sync.syncOnly 部分)会告诉 Gatekeeper 监视哪些资源并将其放入缓存中。

Apply the config:应用配置:

kubectl apply -f config-sandbox-binding.yaml

Gatekeeper will now start enforcing this policy on any new or updated RoleBinding or ClusterRoleBinding resources.Gatekeeper 现在将开始对任何新的或更新的 RoleBinding 或 ClusterRoleBinding 资源执行此策略。

4. Testing and Verification 4. 测试与验证

To confirm the policy is working, simulate an attempt to grant new permissions to a protected ServiceAccount.要确认策略是否生效,请模拟一次向受保护的 ServiceAccount 授予新权限的尝试。

A. Set Up the Test Scenario A. 设置测试场景

Apply the Namespace, ServiceAccount and Sandbox resources to the cluster.将 Namespace、ServiceAccount 和 Sandbox 资源应用到集群中。

kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: sandbox-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: sandbox-sa
  namespace: sandbox-ns
---
apiVersion: agents.x-k8s.io/v1beta1
kind: Sandbox
metadata:
  name: sandbox-example
  namespace: sandbox-ns
spec:
  podTemplate:
    metadata:
      labels:
        sandbox: my-sandbox
      annotations:
        test: "yes"
    spec:
      serviceAccountName: sandbox-sa
      containers:
      - name: my-container
        image: busybox
        command: ["/bin/sh", "-c", "sleep 3600"]
EOF

B. Trigger the Policy (Expected Failure) B. 触发策略(预期失败)

Apply a RoleBinding that should fail应用一个应该会失败的 RoleBinding

kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-forbidden-binding
  namespace: sandbox-ns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: view
subjects:
- kind: ServiceAccount
  name: sandbox-sa
  namespace: sandbox-ns
EOF

C. Check the Expected Outcome C. 检查预期结果

You should see an error like:您应该会看到类似以下的错误:

Error from server (Forbidden): error when creating "STDIN": admission webhook "validation.gatekeeper.sh" denied the request: [prevent-active-sa-binding] RoleBinding cannot be created/updated: ServiceAccount 'sandbox-ns/sandbox-sa' is in use by Pod 'sandbox-ns/sandbox-example', which is controlled by Sandbox CR 'sandbox-example'

If you see this error, your security policy is successfully configured and enforced. ✅如果您看到此错误,说明您的安全策略已成功配置并生效。✅

Scenario 2: Binding to an unused ServiceAccount (Should be ALLOWED) 场景 2:绑定到未使用的 ServiceAccount(应被允许)

Try to bind to another-sa in test-ns, assuming no Sandbox Pod uses it.尝试绑定到 test-ns 中的 another-sa,假设没有 Sandbox Pod 使用它。

kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: test-ns
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: another-sa
  namespace: test-ns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test-allow
  namespace: test-ns
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: view
subjects:
- kind: ServiceAccount
  name: another-sa
  namespace: test-ns
EOF

You should see:您应该会看到:

rolebinding.rbac.authorization.k8s.io/test-allow created

Scenario 3: Binding to a ServiceAccount used by a NON-Sandbox Pod (Should be ALLOWED) 场景 3:绑定到非 Sandbox Pod 使用的 ServiceAccount(应被允许)

If sandbox in sandbox-ns is used by a Pod not managed by an Sandbox CR (e.g., a standalone Pod or one managed by a Deployment), the binding should also be allowed, because the policy specifically checks for ownerReferences of kind Sandbox.如果 sandbox-ns 中的 sandbox 被一个非 Sandbox CR 管理的 Pod 使用(例如,独立 Pod 或由 Deployment 管理的 Pod),该绑定也应该被允许,因为该策略专门检查 kind 为 Sandbox 的 ownerReferences。

Summary of How it Works 工作原理总结

The Rego code in the ConstraintTemplate intercepts the creation/update of RoleBindings and ClusterRoleBindings. For each ServiceAccount subject, it queries Gatekeeper’s in-memory cache (data.inventory) for any Pods in the specified namespace that use this ServiceAccount. It then filters this list to include only Pods whose metadata.ownerReferences indicate they are owned by an Sandbox resource from the agents.x-k8s.io API group. If any such active Pods are found, the binding is rejected. This setup effectively prevents assigning potentially elevated permissions to ServiceAccounts that are actively in use by your sandboxed workloads.ConstraintTemplate 中的 Rego 代码会拦截 RoleBindings 和 ClusterRoleBindings 的创建/更新。对于每个 ServiceAccount 主体,它会查询 Gatekeeper 的内存缓存 (data.inventory),查找指定命名空间中所有使用该 ServiceAccount 的 Pod。然后,它会过滤此列表,仅包含 metadata.ownerReferences 指明其由 agents.x-k8s.io API 组下的 Sandbox 资源所拥有的 Pod。如果找到任何此类活动的 Pod,绑定将被拒绝。 此设置有效地防止了将潜在的提升权限分配给沙盒工作负载正在使用的 ServiceAccount。

5. Uninstall 5. 卸载

helm delete gatekeeper --namespace gatekeeper-system

# helm won't remove the crds so you have to run the following 
kubectl delete crd -l gatekeeper.sh/system=yes
Last modified April 23, 2026: Docs feature use cases (#652) (0840ee5)