OPA-Gatekeeper可以在Kubernetes 中,通过策略来实现一些额外的管理、安全方面的限制,例如:限制特定用户在 Namespace 中的行为权限
本次实验将在test命名空间内对开发人员的更新操作提供时间窗口限制。
说明:
在自建的k8s集群实验成功。
在rancher2.4.4中创建失败,原因是rego语法解析错误,已经提交到官方论坛,尚未解决。
为了方便管理,开发人员将使用统一用户deploy,
然后在k8s中添加基于角色的访问控制(RBAC),即使用role和rolebinding,限制deploy在test命名空间内的资源权限。
最后使用gatekeeper做时间窗口限制。
test manager deploy
实现步骤 1 创建用户
创建私钥
openssl genrsa -out deploy.key 2048创建csr(证书签名请求)文件
openssl req -new -key deploy.key -out deploy.csr -subj "/CN=deploy/O=MGM"通过集群的CA证书和deploy的csr文件,来为deploy颁发证书
我的CA证书是在/etc/kubernetes/pki/目录下
openssl x509 -req -in deploy.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out deploy.crt -days 3650为用户配置credentials认证环境和context上下文环境
kubectl config set-credentials deploy --client-certificate=deploy.crt --client-key=deploy.key kubectl config get-users kubectl config set-context deploy --cluster=kubernetes --namespace=test --user=deploy kubectl config get-contexts测试切换用户环境
kubectl config use-context deploy kubectl config use-context kubernetes-admin@kubernetes 2 创建角色在RBAC中,角色有两种——普通角色(Role)和集群角色(ClusterRole),ClusterRole是特殊的Role:
Role属于某个命名空间,而ClusterRole属于整个集群,其中包括所有的命名空间
ClusterRole能够授予集群范围的权限,比如node资源的管理,比如非资源类型的接口请求(如"/health"),比如可以请求全命名空间的资源(通过指定 --all-namespaces)
这里要在test命名空间内创建一个权限小的普通角色
kind: Role metadata: namespace: test name: manager rules: - apiGroups: ["apps"] resources: ["*"] verbs: ["*"] - apiGroups: [""] resources: ["pods"] verbs: ["*"] kubectl apply -f role.yaml kubectl get role -n test以上涉及的api资源查看方式:
kubectl api-resources|grep "apps/v1" kubectl api-resources|grep " v1" 3 将前面的角色和用户绑定 kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: manager-binding namespace: test subjects: - kind: User name: deploy roleRef: kind: Role name: manager apiGroup: "rbac.authorization.k8s.io" kubectl apply -f Rolebinding.yaml kubectl get rolebinding -n test测试deploy用户创建pod
kubectl get pods -n test --context=deploy kubectl run nginx --image=nginx:latest -n default --context=deploy kubectl run nginx --image=nginx:latest -n test --context=deploy 5 安装gatekeeper wget https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml kubectl apply -f gatekeeper.yaml检查
kubectl get ConstraintTemplate #等待出现 No resources found 才表示成功 kubectl get crd #CustomResourceDefinitions #只有当AGE不为<Invalid>而是一个时间时,才表示这个资源对象可用 ConstraintTemplate 约束模板在定义约束之前,必须先定义一个 ConstraintTemplate (相当于创造了自定义的api-resources类型)
它主要内容描述的是 执行约束的Rego语句 和 约束的模式。
约束的模式允许admin对约束行为进行微调,就像对一个函数传参。
spec由两部分组成:
- crd:CustomResourceDefinition 自定义资源
- targets:一组target,是以 rego 代码块为主体
以下模板提供了时间窗口限制(每周一、三,晚23:30至次日06:00)
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: updatelimits spec: crd: spec: names: kind: UpdateLimits targets: - target: admission.k8s.gatekeeper.sh rego: | package updatelimit ###TIME check nanosec := time.now_ns() wday := time.weekday(nanosec) dhour :=time.clock(nanosec)[0] dmin :=time.clock(nanosec)[1] ###userAuth Check #ns := input.review.object.metadata.namespace uname := input.review.userInfo.username # 23:30至次日06:00,要考虑 k8s 的8h时差 timeOK { dhour==15 dmin>=30 } timeOK { dhour>15 dhour<22 } weekdayOK{ wday == "Wednesday" } weekdayOK{ wday == "Monday" } #三种不同情况下的限制提示 violation[{"msg": msgX}] { uname != "deploy" msgX = "\n>>>>>>>>>>>>>>>>>>>>>>>>>> Changes are only allowed for USER [deploy].\n" } violation[{"msg": msgX}] { uname == "deploy" not weekdayOK msgX = "\n%%%%%%%%%%%%%%%%%%%%%%%%%% Changes are only allowed on [Monday] or [Wednesday].\n" } violation[{"msg": msgX}] { uname == "deploy" weekdayOK not timeOK msgX = "\n************************** Changes are only allowed in [23:30-06:00].\n" } # kubectl apply -f constrainttemplateV1Beta1.yaml # kubectl get ConstraintTemplate # kubectl api-resources |grep gatekeeper NAME SHORTNAMES APIVERSION NAMESPACED KIND updatelimits constraints.gatekeeper.sh/v1beta1 false UpdateLimits 注意项spec.crd.spec.names.kind 小写后必须和 metadata.name 一致
violation返回值是一个结构体切片:[{"msg": STRING}]
violation[{"msg": message}] { message := "" } Constraint 约束条件 知识介绍(可以略过)