| name | implementing-opa-gatekeeper-for-policy-enforcement |
| description | 使用 OPA Gatekeeper 通过 ConstraintTemplate、Rego 规则和 Gatekeeper 策略库强制执行 Kubernetes 准入策略。 |
| domain | cybersecurity |
| subdomain | container-security |
| tags | ["opa","gatekeeper","kubernetes","admission-control","policy-as-code","rego"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
使用 OPA Gatekeeper 实施策略强制执行
概述
OPA Gatekeeper 是一个 Kubernetes 准入控制器,用于强制执行用 Rego 语言编写的策略。它使用 ConstraintTemplate(包含 Rego 逻辑的策略蓝图)和 Constraint(带参数的实例化策略)在准入时验证、变更或拒绝 Kubernetes 资源请求。
前置条件
- Kubernetes 集群 v1.24+
- Helm 3
- 具有 cluster-admin 权限的 kubectl
- 熟悉 Rego 策略语言
安装 Gatekeeper
helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm repo update
helm install gatekeeper gatekeeper/gatekeeper \
--namespace gatekeeper-system --create-namespace \
--set replicas=3 \
--set audit.replicas=1 \
--set audit.logLevel=INFO
kubectl get pods -n gatekeeper-system
kubectl get crd | grep gatekeeper
验证安装
kubectl get validatingwebhookconfigurations gatekeeper-validating-webhook-configuration
kubectl get crd constrainttemplates.templates.gatekeeper.sh
kubectl get crd configs.config.gatekeeper.sh
ConstraintTemplate 示例
1. 要求资源包含 Label
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg, "details": {"missing_labels": missing}}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing :=
, []
}
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: require-team-label
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Namespace"]
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
labels:
- "team"
- "environment"
2. 阻断特权容器
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sblockprivileged
spec:
crd:
spec:
names:
kind: K8sBlockPrivileged
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sblockprivileged
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged == true
msg := sprintf("不允许特权容器:%v", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[_]
container.securityContext.privileged == true
msg := sprintf("不允许特权初始化容器:%v", [container.name])
}
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
name: block-privileged-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
namespaces:
- "production"
- "staging"
3. 限制容器镜像仓库
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sallowedrepos
spec:
crd:
spec:
names:
kind: K8sAllowedRepos
validation:
openAPIV3Schema:
type: object
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not image_matches(container.image)
msg := sprintf("容器镜像 %v 不来自允许的仓库。允许的仓库:%v", [container.image, input.parameters.repos])
}
violation[{"msg": msg}] {
container := input.review.object.spec.initContainers[]
, [, ]
}
{
[]
,
}
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
name: restrict-image-repos
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
parameters:
repos:
- "gcr.io/my-project/"
- "ghcr.io/my-org/"
- "registry.k8s.io/"
4. 强制资源限制
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequirelimits
spec:
crd:
spec:
names:
kind: K8sRequireLimits
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequirelimits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.cpu
msg := sprintf("容器 %v 未设置 CPU 限制", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits.memory
msg := sprintf("容器 %v 未设置内存限制", [container.name])
}
5. 阻断 latest 镜像标签
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sblocklatesttag
spec:
crd:
spec:
names:
kind: K8sBlockLatestTag
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sblocklatesttag
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
endswith(container.image, ":latest")
msg := sprintf("容器 %v 使用了 ':latest' 标签,请使用具体版本标签。", [container.name])
}
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not contains(container.image, ":")
msg := sprintf("容器 %v 未指定标签(默认为 , []
}
6. 强制只读根文件系统
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8sreadonlyroot
spec:
crd:
spec:
names:
kind: K8sReadOnlyRoot
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sreadonlyroot
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.securityContext.readOnlyRootFilesystem
msg := sprintf("容器 %v 必须将 readOnlyRootFilesystem 设置为 true", [container.name])
}
审计与强制执行模式
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sBlockPrivileged
metadata:
name: block-privileged-dryrun
spec:
enforcementAction: dryrun
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
检查审计违规
kubectl get k8sblockprivileged block-privileged-containers -o yaml | grep -A 20 violations
kubectl get constraints -o json | jq '.items[] | {name: .metadata.name, violations: (.status.violations // [] | length)}'
Gatekeeper 配置(豁免命名空间)
apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
name: config
namespace: gatekeeper-system
spec:
match:
- excludedNamespaces:
- kube-system
- gatekeeper-system
- calico-system
processes:
- "*"
监控
kubectl port-forward -n gatekeeper-system svc/gatekeeper-webhook-service 8443:443
kubectl get --raw /metrics | grep gatekeeper
最佳实践
- 从演练模式开始 - 先以
dryrun 模式部署约束,审查违规后再切换为 deny
- 使用策略库 - 利用 https://github.com/open-policy-agent/gatekeeper-library 中的预置模板
- 豁免系统命名空间 - 始终排除 kube-system 和 gatekeeper-system
- 版本控制策略 - 将 ConstraintTemplate 和 Constraint 存入 Git 仓库
- 监控审计结果 - 定期检查约束的
.status.violations
- 测试 Rego 策略 - 部署前使用
opa test 或 Rego Playground 验证
- 与准入 Webhook 结合 - 将 Gatekeeper 与 Pod Security Admission 分层部署实现纵深防御