使用k8s RBAC和ValidatingAdmissionPolicy 配合来校验用户权限

时间:2024-11-07 12:40:12

我先讲一下业务场景:

  1. k8s集群内部有几个重要的命名空间(比如: kube-system, kube-public 等),这些命名空间除了管理员有权限,其他用户不可以操作(编辑,删除)这几个命名空间。
  2. 在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 权限。
  3. saas-admin 用户可以在集群下创建用户 sass-user 和 用户独有的命名空间 users-ns, 并且把用户 saas-user 绑定到 ClusterRole。
  4. 用户 saas-user 具有命名空间 users-ns 下的所有权限(每个用户都有自己的命名空间)。
  5. 这里重复一下,用户 saas-admin 不可以查看 kube-system 和 kube-public 命名空间下的任务资源, 也不能操作(编辑,删除) kube-system 和 kube-public 命名空间。

这里先抛出一个问题:如果只用 RBAC 如何才能做到上面这种场景?


我想了很久, 发现只有RBAC根本做不到(也可能是我才书浅薄, 如果大家有想法,可以在评论区留言) , 我给出理由就是 saas-admin 有 namespace 操作权限,那么没有办法避免操作 kube-system 等重要命名空间。

那么如何让saas-admin 没有权限操作这些重要命名空间呢?这个时候就要配合 ValidatingAdmissionPolicy 来使用了,如果不熟悉 ValidatingAdmissionPolicy ,可以去官方文档了接一下,我说一下个人想法:

  1. 使用 ValidatingAdmissionPolicy 来判断用户是否saas-admin, 如果是则拒绝。
  2. 使用 ValidatingAdmissionPolicyBinding 来把验证准入策略绑定带有特定标签的命名空间。
  3. 使用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"]