使用k8s RBAC和ValidatingAdmissionPolicy 配合来校验用户权限
我先讲一下业务场景:
- k8s集群内部有几个重要的命名空间(比如: kube-system, kube-public 等),这些命名空间除了管理员有权限,其他用户不可以操作(编辑,删除)这几个命名空间。
- 在k8s集群需要创建一个用户 saas-admin, 有以下权限:
(1). namespace 的 create, update, delete, get, list, watch 权限。
(2). rolebindings 的 create, update, delete, get, list 权限。
(3). serviceaccounts 的 create, update, delete, get, list, watch 权限。 - saas-admin 用户可以在集群下创建用户 sass-user 和 用户独有的命名空间 users-ns, 并且把用户 saas-user 绑定到 ClusterRole。
- 用户 saas-user 具有命名空间 users-ns 下的所有权限(每个用户都有自己的命名空间)。
- 这里重复一下,用户 saas-admin 不可以查看 kube-system 和 kube-public 命名空间下的任务资源, 也不能操作(编辑,删除) kube-system 和 kube-public 命名空间。
这里先抛出一个问题:如果只用 RBAC 如何才能做到上面这种场景?
…
我想了很久, 发现只有RBAC根本做不到(也可能是我才书浅薄, 如果大家有想法,可以在评论区留言) , 我给出理由就是 saas-admin 有 namespace 操作权限,那么没有办法避免操作 kube-system 等重要命名空间。
那么如何让saas-admin 没有权限操作这些重要命名空间呢?这个时候就要配合 ValidatingAdmissionPolicy 来使用了,如果不熟悉 ValidatingAdmissionPolicy ,可以去官方文档了接一下,我说一下个人想法:
- 使用 ValidatingAdmissionPolicy 来判断用户是否saas-admin, 如果是则拒绝。
- 使用 ValidatingAdmissionPolicyBinding 来把验证准入策略绑定带有特定标签的命名空间。
- 使用RBAC来分配saas-admin的权限。
第1和第2步的目的是防止saas-admin 误操作 kube-system 等命名空间, 这样目的就达到。
下面展示一下配置,噢,对了,如果不知道k8s怎么开启ValidatingAdmissionPolicy,可以参考这篇文章:k8s 启用 ValidatingAdmissionPolicy 特性
配置 ValidatingAdmissionPolicy
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicy
metadata:
name: deny-inter
spec:
matchConstraints:
resourceRules:
- apiGroups: ["*"]
apiVersions: ["*"]
operations: ["*"]
resources: ["*"]
validations:
- expression: "request.userInfo.username != 'system:serviceaccount:saas:saas-admin'" # 拒绝所有请求
message: "ServiceAccount 'saas-admin' cannot operate in namespace"
failurePolicy: Fail
---
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingAdmissionPolicyBinding
metadata:
name: deny-inter-binding
spec:
policyName: deny-inter # 引用策略名称
matchResources:
namespaceSelector:
matchLabels:
test-label: inter # 匹配命名空间的标签, 可以为kube-system和kube-public打上标签
validationActions: ["Deny"] # 添加验证动作
配置RBAC
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: saas-admin-role
rules:
- apiGroups: ["*"]
resources: ["namespace"]
verbs: ["create", "update", "delete", "get", "list", "watch"]
- apiGroups: ["rbac.authorization.k8s.io"]
resources: ["rolebindings"]
verbs: ["create", "update", "delete", "get", "list"]
- apiGroups: [""]
resources: ["serviceaccounts"]
verbs: ["create", "get", "list", "watch", "update", "delete"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: saas-admin # 替换为实际用户名
namespace: saas # 替换为所需的命名空间
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: saas-admin-role-binding
subjects:
- kind: ServiceAccount
name: sass-admin
namespace: saas
roleRef:
kind: ClusterRole
name: saas-admin-role # 替换为实际权限角色
apiGroup: rbac.authorization.k8s.io
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: saas-user-role
rules:
- apiGroups: [""]
resources: ["pods", "services", "configmaps", "secrets", "persistentvolumeclaims", "persistentvolumes"]
verbs: ["get", "list", "create", "update", "delete", "watch"]
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "create", "update", "delete", "watch"]