k8s RBAC 授权理论实践

 当客户端发起API Server调用时,API Server内部要先进行用户认证,然后执行用户授权流程,即通过授权策略来决定一个API调用是否合法。对合法用户进行授权并且随后在用户访问时进行鉴权,是权限与安全系统的重要一环。简单地说,授权就是授予不同的用户不同的访问权限。API Server目前支持以下几种授权策略(通过API Server的启动参数“--authorization-mode”设置)。

◎ AlwaysDeny:表示拒绝所有请求,一般用于测试。

◎ AlwaysAllow:允许接收所有请求,如果集群不需要授权流程,则可以采用该策略,这也是Kubernetes的默认配置。

◎ ABAC(Attribute-Based Access Control):基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制。

◎ Webhook:通过调用外部REST服务对用户进行授权。

◎ RBAC:Role-Based Access Control,基于角色的访问控制。

◎ Node:是一种专用模式,用于对kubelet发出的请求进行访问控制。

API Server在接收到请求后,会读取该请求中的数据,生成一个访问策略对象,如果在该请求中不带某些属性(如Namespace),则这些属性的值将根据属性类型的不同,设置不同的默认值(例如,为字符串类型的属性设置一个空字符串;为布尔类型的属性设置false;为数值类型的属性设置0)。然后将这个访问策略对象和授权策略文件中的所有访问策略对象逐条匹配,如果至少有一个策略对象被匹配,则该请求被鉴权通过,否则终止API调用流程,并返回客户端的错误调用码。

要使用RBAC授权模式,需要在API Server的启动参数中加上--authorization-mode=RBAC。

 1. 用户授权

使用kubeconfig (https证书认证授权)

1.1 管理员授权

创建证书请求文件

cat > kubectl-admin-csr.json <<EOF
{
  "CN": "admin",  # 用户名
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "ShangHai",
      "ST": "ShangHai",
      "O": "system:masters",   # 所属组
      "OU": "System"
    }
  ]
}
EOF

字段解释:

1. CN (Common Name):通常表示证书的主体或用户标识。在 Kubernetes 中,这里用来标识用户的名称,即 admin

2. hosts:证书可用于的主机名或 IP 地址。为空时,表示证书不会绑定到特定主机名或 IP 地址。

3. key
  • 描述:用于指定证书的密钥算法和密钥大小。

  • algo

    • 值:rsa
    • 描述:密钥算法,选择使用 RSA 算法。
  • size

    • 值:2048
    • 描述:密钥的长度(位数)。2048 位是一个常见且安全的密钥长度。

4. names
  • 描述:定义证书的附加信息,用于标识证书主体的各种属性。

  • 子字段:

    • C (Country)

      • 值:CN
      • 描述:国家代码,用于标识证书主体所属国家。
    • L (Locality)

      • 值:ShangHai
      • 描述:证书主体的所在地城市。
    • ST (State)

      • 值:ShangHai
      • 描述:证书主体所在的州或省份。
    • O (Organization)

      • 值:system:masters
      • 描述:组织名称。在 Kubernetes 中,system:masters 是一个内置组,具有集群管理员权限
    • OU (Organizational Unit)

      • 值:System
      • 描述:组织单位名称。该值通常不影响证书的功能,可自由定义。

总结:当O字段为system:masters时,不需要给用户创建RBAC权限绑定,因为他已经被绑定到集群内置管理组。

如何论证system:master是k8s的管理员用户组呢?

[root@master-1 .kube]# kubectl get clusterrolebinding
system:node-proxier                                    ClusterRole/system:node-proxier                                    16d
cluster-admin                                          ClusterRole/cluster-admin                                          16d

[root@master-1 .kube]# kubectl describe clusterrolebinding cluster-admin
Name:         cluster-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  cluster-admin
Subjects:
  Kind   Name            Namespace
  ----   ----            ---------
  Group  system:masters

同样,kube-proxy是绑定给了用户

{
  "CN": "system:kube-proxy",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "ShangHai",
      "ST": "ShangHai",
      "O": "k8s",
      "OU": "System"
    }
  ]
}

[root@master-1 .kube]# kubectl describe clusterrolebinding system:node-proxier
Name:         system:node-proxier
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
Role:
  Kind:  ClusterRole
  Name:  system:node-proxier
Subjects:
  Kind  Name               Namespace
  ----  ----               ---------
  User  system:kube-proxy

# 查看权限
[root@master-1 .kube]# kubectl describe clusterrole system:node-proxier
Name:         system:node-proxier
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources                        Non-Resource URLs  Resource Names  Verbs
  ---------                        -----------------  --------------  -----
  events                           []                 []              [create patch update]
  events.events.k8s.io             []                 []              [create patch update]
  nodes                            []                 []              [get list watch]
  endpoints                        []                 []              [list watch]
  services                         []                 []              [list watch]
  endpointslices.discovery.k8s.io  []                 []              [list watch]

2. 普通用户授权

在 Kubernetes 中,为用户创建访问权限涉及以下几个步骤:

  1. 生成用户证书
{
  "CN": "zhangsan",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "ShangHai",
      "ST": "ShangHai",
      "O": "dev-team",
      "OU": "dev"
    }
  ]
}
  1. 2配置 Kubernetes 集群的 RBAC
[root@master-1 kubectl-rbac]# cat zhangsan-kubectl-rbac-clusterrole.yaml
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: zhangsan-view-cluster
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["get", "list", "watch"]
[root@master-1 kubectl-rbac]# cat zhangsan-kubectl-rbac-clusterrolebinding.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: dev-team-zs-rolebinding
subjects:
- kind: User
  name: zhangsan
  #namespace: default
  #apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: zhangsan-view-cluster
  apiGroup: rbac.authorization.k8s.io
  1. 创建用户 kubeconfig 文件
KUBE_CONFIG="/root/.kube/config-zs"
KUBE_APISERVER="https://192.168.43.129:6443"
# 设置集群
kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/tls/k8s/ca.pem \
  --embed-certs=true \  # 将证书导入到配置文件
  --server=${KUBE_APISERVER} \  # 集群地址
  --kubeconfig=${KUBE_CONFIG}
 
# 设置用户证书 kubectl config
set-credentials zhangsan \ --client-certificate=/opt/tls/k8s/kubectl-zhangsan.pem \ --client-key=/opt/tls/k8s/kubectl-zhangsan-key.pem \ --embed-certs=true \ --kubeconfig=${KUBE_CONFIG}
# 设置集群与用户关联的上下文 kubectl config
set-context zhangsan \ --cluster=kubernetes \ --user=zhangsan \ --kubeconfig=${KUBE_CONFIG} # 切换使用上下文 kubectl config use-context zhangsan --kubeconfig=${KUBE_CONFIG}

如果创建的用户属于同一个用户组

cat ../kubectl-zhangsan-csr.json
{
  "CN": "zhangsan",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "ShangHai",
      "ST": "ShangHai",
      "O": "system:rentao",
      "OU": "dev"
    }
  ]
}

直接创建用户的kubeconfig即可,因为之前已经对用户组进行了授权。

2. 普通组授权

2.1 创建普通用户的kubeconfig

[root@master-1 kubectl-rbac]# cat /opt/tls/k8s/kubectl-admin-csr.json
{
  "CN": "lisi",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "ShangHai",
      "ST": "ShangHai",
      "O": "dev",
      "OU": "System"
    }
  ]
}

2.2 创建证书及生成kubeconfig

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes lisi-csr.json | cfssljson -bare lisi

KUBE_CONFIG="/root/.kube/config"
KUBE_APISERVER="https://192.168.43.129:6443"

kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/tls/k8s/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=${KUBE_CONFIG}
 
kubectl config set-credentials lisi \
  --client-certificate=/opt/tls/k8s/kubectl-admin.pem \
  --client-key=/opt/tls/k8s/kubectl-admin-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}

kubectl config set-context default \
  --cluster=kubernetes \
  --user=lisi \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context default --kubeconfig=${KUBE_CONFIG}

2.3 创建rbac,将用户绑定到普通用户组

[root@master-1 kubectl-rbac]# cat kubectl-rbac.yaml
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: dev-team-rolebinding
subjects:
- kind: Group   # 类型为组
  name: dev   # 用户组名称,需要全部对应
  #namespace: default
  #apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole   # 权限类型为集群
  name: view   # 内置权限,只有全局查看权限
  apiGroup: rbac.authorization.k8s.io

执行

[root@master-1 kubectl-rbac]# kubectl apply -f kubectl-rbac.yaml
clusterrolebinding.rbac.authorization.k8s.io/dev-team-rolebinding created

2.4 切换到lisi用户的上下文

kubectl config use lisi

2.5 测试权限

删除pod

[root@master-1 kubectl-rbac]# kubectl delete pod busybox
Error from server (Forbidden): pods "busybox" is forbidden: User "lisi" cannot delete resource "pods" in API group "" in the namespace "defau

创建rbac资源

[root@master-1 prometheus-k8s]# kubectl apply -f rbac.yaml
serviceaccount/prometheus unchanged
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "rbac.authorization.k8s.io/v1, Resource=clusterroles", GroupVersionKind: "rbac.authorization.k8s.io/v1, Kind=ClusterRole"
Name: "prometheus", Namespace: ""
from server for: "rbac.yaml": clusterroles.rbac.authorization.k8s.io "prometheus" is forbidden: User "lisi" cannot get resource "clusterroles" in API grou.authorization.k8s.io" at the cluster scope
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "rbac.authorization.k8s.io/v1, Resource=clusterrolebindings", GroupVersionKind: "rbac.authorization.k8s.io/v1, Kind=ClusterRoleBinding"
Name: "prometheus", Namespace: ""
from server for: "rbac.yaml": clusterrolebindings.rbac.authorization.k8s.io "prometheus" is forbidden: User "lisi" cannot get resource "clusterrolebindingPI group "rbac.authorization.k8s.io" at the cluster scope

[root@master-1 prometheus-k8s]# kubectl apply -f prometheus-deployment.yaml Error from server (Forbidden): error when creating "prometheus-deployment.yaml": deployments.apps is forbidden: User "lisi" cannot create resource "deployin API group "apps" in the namespace "monitor" Error from server (Forbidden): error when creating "prometheus-deployment.yaml": services is forbidden: User "lisi" cannot create resource "services" in Ap "" in the namespace "monitor"

查看pod

[root@master-1 kubectl-rbac]# kubectl get pod -A
NAMESPACE     NAME                                          READY   STATUS    RESTARTS   AGE
default       busybox                                       1/1     Running   0          89s
default       ingressclass-ingress-nginx-controller-p22gm   1/1     Running   17         14d
default       ingressclass-ingress-nginx-controller-t5wz9   1/1     Running   17         14d
default       ingressclass-ingress-nginx-controller-tt7wg   1/1     Running   18         14d
default       nfs-client-provisioner-7d4f48bb8f-zbhfd       1/1     Running   18         14d
kube-system   calico-kube-controllers-7775799c8c-6x766      1/1     Running   18         14d
kube-system   calico-kube-controllers-7775799c8c-75bsz      1/1     Running   18         14d
kube-system   calico-kube-controllers-7775799c8c-gss8z      1/1     Running   19         14d
kube-system   calico-node-cczr6                             1/1     Running   18         14d
kube-system   calico-node-k89f9                             1/1     Running   19         14d
kube-system   calico-node-w4xgb                             1/1     Running   18         14d
kube-system   calico-typha-5dc577d877-ht7rq                 1/1     Running   19         14d
kube-system   coredns-6bd54f798b-4khqv                      1/1     Running   9          7d3h
kube-system   coredns-6bd54f798b-574qp                      1/1     Running   9          7d3h
kube-system   metrics-server-5bbd7cb4c6-hv8kj               1/1     Running   18         14d
staticpod     static-web-master-1                           1/1     Running   15         10d

修改权限

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: dev-team-rolebinding
subjects:
- kind: Group
  name: dev
  #namespace: default
  #apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

执行,报错

The ClusterRoleBinding "dev-team-rolebinding" is invalid: roleRef: Invalid value: rbac.RoleRef{APIGroup:"rbac.authorization.k8s.io", Kind:"ClusterRole", Name:"cluster-admin"}: cannot change roleRef

原因:出现错误 cannot change roleRef 是因为 Kubernetes 中的 RoleRef 字段是不可变的。一旦创建了 ClusterRoleBindingRoleBinding,其 roleRef 字段就无法被修改。如果需要更改角色绑定到的角色,必须删除原有的绑定并重新创建一个新的绑定。

2. ServiceAccount (Token认证授权)

2.1 默认secret

每个命名空间下都会有一个default的secret,当权限不满足当前需求时,可以创建一个SA,然后创建一系列的role与clusterrole,然后使用rolebinding与clusterrolebinding与S绑定,然后在创建pod时指定该SA,该SA就会挂载到容器内部的/var/run/secrets/kubernetes.io/serviceaccount/目录下。

[root@master-1 yml]# kubectl get secret -A | grep admin-user
kubernetes-dashboard   admin-user-token-p57w4                kubernetes.io/service-account-token   3      57s
[root@master-1 yml]# kubectl  describe secret -n kubernetes-dashboard   admin-user-token-p57w4
Name:         admin-user-token-p57w4
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: admin-user
              kubernetes.io/service-account.uid: b20ee7cb-cc60-4750-be86-916c99b292ef

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1326 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsIcTc4dUEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3N...

2.2 制作kubeconfig的两种方式

DASHBOARD_TOKEN=eyJhbGciOiJSUzI1NdF83Z3oNscTc4dUEifQ.eyJpc3MiOiJrdW...
# echo $DASHBOARD_TOKEN

# Token认证方式
kubectl config set-cluster kubernetes --certificate-authority=/opt/kubernetes/ssl/ca.pem --server="https://192.168.0.190:8443" --embed-certs=true --kubeconfig=/opt/kubernetes/dashboard/dashboard.config

kubectl config set-credentials dashboard-admin --token=$DASHBOARD_TOKEN --kubeconfig=./dashboard.config
 
kubectl config set-context dashboard-admin@kubernetes --cluster=kubernetes --user=dashboard-admin --kubeconfig=./dashboard.config
 
kubectl config use-context dashboard-admin@kubernetes --kubeconfig=./dashboard.config
 ----------------------------------------------------------
证书认证方式
kubectl config set-cluster kubernetes \
  --certificate-authority=/opt/kubernetes/ssl/ca.pem \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=${KUBE_CONFIG}
 
kubectl config set-credentials cluster-admin \  # 用户名
  --client-certificate=/opt/kubernetes/ssl/kubectl-admin.pem \
  --client-key=/opt/kubernetes/ssl/kubectl-admin-key.pem \
  --embed-certs=true \
  --kubeconfig=${KUBE_CONFIG}

kubectl config set-context default \
  --cluster=kubernetes \
  # --namespace=xxx   # 限制某个命名空间的权限
  --user=cluster-admin \
  --kubeconfig=${KUBE_CONFIG}

kubectl config use-context default --kubeconfig=${KUBE_CONFIG}

2.3 查看容器内部挂载的SA

    spec:
      serviceAccountName: kubernetes-dashboard
      containers:
        - name: kubernetes-dashboard
          image: xxx/k8s/dashboard:v2.1.0
          imagePullPolicy: IfNotPresent

2.4 查看创建的SA

[root@master-1 dashboard]# kubectl get secret -n kubernetes-dashboard
NAME                               TYPE                                  DATA   AGE
default-token-mrr2s                kubernetes.io/service-account-token   3      73s
kubernetes-dashboard-certs         Opaque                                0      73s
kubernetes-dashboard-csrf          Opaque                                1      72s
kubernetes-dashboard-key-holder    Opaque                                2      72s
kubernetes-dashboard-token-6r4nl   kubernetes.io/service-account-token   3      73s

2.5 查看SA关联的secret

[root@master-1 dashboard]# kubectl  describe secret  -n kubernetes-dashboard kubernetes-dashboard-token-6r4nl
Name:         kubernetes-dashboard-token-6r4nl
Namespace:    kubernetes-dashboard
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: kubernetes-dashboard
              kubernetes.io/service-account.uid: 4bd529b2-c313-4dc5-9d4d-9ab723c2e8af

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1326 bytes
namespace:  20 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6InBKV3FGbERnYVltWHA3XzRRQy1OSWRia1NIZW5FSE5QLXZoX0hCUjQ0NVkifQ...

这个SA挂载到pod容器内部,容器就赋予了相应的权限。

2.6 示例

2.6.1 以dashboard为例,我们查看下权限创建清单

apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
rules:
- apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs", "kubernetes-dashboard-csrf"]
    verbs: ["get", "update", "delete"]
- apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["kubernetes-dashboard-settings"]
    verbs: ["get", "update"]
- apiGroups: [""]
    resources: ["services"]
    resourceNames: ["heapster", "dashboard-metrics-scraper"]
    verbs: ["proxy"]
  - apiGroups: [""]
    resources: ["services/proxy"]
    resourceNames: ["heapster", "http:heapster:", "https:heapster:", "dashboard-metrics-scraper", "http:dashboard-metrics-scraper"]
    verbs: ["get"]
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
rules:
  # Allow Metrics Scraper to get metrics from the Metrics server
  - apiGroups: ["metrics.k8s.io"]
    resources: ["pods", "nodes"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  labels:
    k8s-app: kubernetes-dashboard
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kubernetes-dashboard
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard

2.6.2 关于resourceNames: [] 解释:

resourceNames 指定了资源的具体名称,用于限制权限仅适用于某些特定资源。

resourceNames 的含义
  • 资源名称限制resourceNames 表示权限仅适用于 resources 中列出的特定资源的名称。
  • 目标资源:在这个配置中,权限仅适用于以下三个 Secret
    • kubernetes-dashboard-key-holder
    • kubernetes-dashboard-certs
    • kubernetes-dashboard-csrf
    这些资源的名字必须完全匹配,权限不会扩展到其他名称的 Secret
[root@master-1 dashboard]# kubectl get secret -n kubernetes-dashboard
NAME                                    TYPE                                  DATA   AGE
default-token-mrr2s                     kubernetes.io/service-account-token   3      23h
kubernetes-dashboard-certs              Opaque                                0      23h
kubernetes-dashboard-csrf               Opaque                                1      23h
kubernetes-dashboard-key-holder         Opaque                                2      23h
kubernetes-dashboard-read-token-9w5r9   kubernetes.io/service-account-token   3      20h
kubernetes-dashboard-token-6r4nl        kubernetes.io/service-account-token   3      23h
[root@master-1 dashboard]# kubectl get configmap -n kubernetes-dashboard
NAME                            DATA   AGE
kube-root-ca.crt                1      23h
kubernetes-dashboard-settings   0      23h
[root@master-1 dashboard]# kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.0.103.140   <none>        8000/TCP        23h
kubernetes-dashboard        NodePort    10.0.14.33     <none>        443:38778/TCP   23h
注意事项
  • resourceNames 的局限性resourceNames 只能用于非列表(list)和非观察(watch)操作,因为这些操作本身需要访问多个资源,无法限制到单个资源名称。例如,listwatch 动作无法与 resourceNames 同时使用。

    不支持的配置示例:

rules:
  - apiGroups: [""]
    resources: ["pods"]
    resourceNames: ["specific-pod"]
    verbs: ["list", "watch"]  # 不支持

2.6.3 ClusterRole 配置 resourceNames示例:

下面的集群角色和角色绑定能让user-1为其他用户在user-1-namespace命名空间中授予admin、editview角色:

apiVersion:rbac.authorization.k8s.io/v1
kind:ClusterRole
metadata:
  name:role-grantor
rules :
- apiGroups:["rbac.authorization.k8s.io"]
  resources:["rolebindings"]
  verbs:["create" ]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources:["clusterroles"]
  verbs:["bind"]
  resourceNames:["admin","edit","view"]

---

kind: RoleBinding
metadata:
  name: role-grantor-binding
  namespace: user-1-namecpace
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: role-grantor
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user-1

创建完成后切换到用户查看授权资源与权限

[root@master-1 .kube]# kubectl auth can-i --list -n kube-system
Resources                                       Non-Resource URLs   Resource Names   Verbs
clusterroles.rbac.authorization.k8s.io          []                  [admin]          [bind]
clusterroles.rbac.authorization.k8s.io          []                  [edit]           [bind]
clusterroles.rbac.authorization.k8s.io          []                  [view]           [bind]
selfsubjectaccessreviews.authorization.k8s.io   []                  []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                  []               [create]
rolebindings.rbac.authorization.k8s.io          []                  []               [create]
                                                [/api/*]            []               [get]
                                                [/api]              []               [get]
                                                [/apis/*]           []               [get]
                                                [/apis]             []               [get]
                                                [/healthz]          []               [get]
                                                [/healthz]          []               [get]
                                                [/livez]            []               [get]
                                                [/livez]            []               [get]
                                                [/openapi/*]        []               [get]
                                                [/openapi]          []               [get]
                                                [/readyz]           []               [get]
                                                [/readyz]           []               [get]
                                                [/version/]         []               [get]
                                                [/version/]         []               [get]
                                                [/version]          []               [get]
                                                [/version]          []               [get]

 

可以看到,clusterrole 配置了resourceNames,clusterrole是集群范围的权限,不受限于namespace。

优点:

1. 通过rolebinding绑定到某一个namespace,实现权限降级

2. 只需要创建一次,而不需要在每一个namespace创建一个role与rolebinding与user/group/sa绑定。

3. 如果要使用clusterrole 创建权限,多个namespace的用户引用,一般来说需要设置一些集群类型的资源,而不是资源类型的资源,可以理解设置一下非namespace类型的资源对象

查看集群API资源

属于namecpace的资源

[root@master-1 clash]# kubectl api-resources --namespaced=true
NAME                        SHORTNAMES   APIVERSION                     NAMESPACED   KIND
bindings                                 v1                             true         Binding
configmaps                  cm           v1                             true         ConfigMap
endpoints                   ep           v1                             true         Endpoints
events                      ev           v1                             true         Event
limitranges                 limits       v1                             true         LimitRange
persistentvolumeclaims      pvc          v1                             true         PersistentVolumeClaim
pods                        po           v1                             true         Pod
podtemplates                             v1                             true         PodTemplate
replicationcontrollers      rc           v1                             true         ReplicationController
resourcequotas              quota        v1                             true         ResourceQuota
secrets                                  v1                             true         Secret
serviceaccounts             sa           v1                             true         ServiceAccount
services                    svc          v1                             true         Service
controllerrevisions                      apps/v1                        true         ControllerRevision
daemonsets                  ds           apps/v1                        true         DaemonSet
deployments                 deploy       apps/v1                        true         Deployment
replicasets                 rs           apps/v1                        true         ReplicaSet
statefulsets                sts          apps/v1                        true         StatefulSet
localsubjectaccessreviews                authorization.k8s.io/v1        true         LocalSubjectAccessReview
horizontalpodautoscalers    hpa          autoscaling/v1                 true         HorizontalPodAutoscaler
cronjobs                    cj           batch/v1beta1                  true         CronJob
jobs                                     batch/v1                       true         Job
leases                                   coordination.k8s.io/v1         true         Lease
networkpolicies                          crd.projectcalico.org/v1       true         NetworkPolicy
networksets                              crd.projectcalico.org/v1       true         NetworkSet
endpointslices                           discovery.k8s.io/v1beta1       true         EndpointSlice
events                      ev           events.k8s.io/v1               true         Event
ingresses                   ing          extensions/v1beta1             true         Ingress
pods                                     metrics.k8s.io/v1beta1         true         PodMetrics
ingresses                   ing          networking.k8s.io/v1           true         Ingress
networkpolicies             netpol       networking.k8s.io/v1           true         NetworkPolicy
poddisruptionbudgets        pdb          policy/v1beta1                 true         PodDisruptionBudget
rolebindings                             rbac.authorization.k8s.io/v1   true         RoleBinding
roles                                    rbac.authorization.k8s.io/v1   true         Role

集群范围的资源

[root@master-1 clash]# kubectl api-resources --namespaced=false
NAME                              SHORTNAMES   APIVERSION                             NAMESPACED   KIND
componentstatuses                 cs           v1                                     false        ComponentStatus
namespaces                        ns           v1                                     false        Namespace
nodes                             no           v1                                     false        Node
persistentvolumes                 pv           v1                                     false        PersistentVolume
mutatingwebhookconfigurations                  admissionregistration.k8s.io/v1        false        MutatingWebhookConfiguration
validatingwebhookconfigurations                admissionregistration.k8s.io/v1        false        ValidatingWebhookConfiguration
customresourcedefinitions         crd,crds     apiextensions.k8s.io/v1                false        CustomResourceDefinition
apiservices                                    apiregistration.k8s.io/v1              false        APIService
tokenreviews                                   authentication.k8s.io/v1               false        TokenReview
selfsubjectaccessreviews                       authorization.k8s.io/v1                false        SelfSubjectAccessReview
selfsubjectrulesreviews                        authorization.k8s.io/v1                false        SelfSubjectRulesReview
subjectaccessreviews                           authorization.k8s.io/v1                false        SubjectAccessReview
certificatesigningrequests        csr          certificates.k8s.io/v1                 false        CertificateSigningRequest
bgpconfigurations                              crd.projectcalico.org/v1               false        BGPConfiguration
bgppeers                                       crd.projectcalico.org/v1               false        BGPPeer
blockaffinities                                crd.projectcalico.org/v1               false        BlockAffinity
clusterinformations                            crd.projectcalico.org/v1               false        ClusterInformation
felixconfigurations                            crd.projectcalico.org/v1               false        FelixConfiguration
globalnetworkpolicies                          crd.projectcalico.org/v1               false        GlobalNetworkPolicy
globalnetworksets                              crd.projectcalico.org/v1               false        GlobalNetworkSet
hostendpoints                                  crd.projectcalico.org/v1               false        HostEndpoint
ipamblocks                                     crd.projectcalico.org/v1               false        IPAMBlock
ipamconfigs                                    crd.projectcalico.org/v1               false        IPAMConfig
ipamhandles                                    crd.projectcalico.org/v1               false        IPAMHandle
ippools                                        crd.projectcalico.org/v1               false        IPPool
kubecontrollersconfigurations                  crd.projectcalico.org/v1               false        KubeControllersConfiguration
flowschemas                                    flowcontrol.apiserver.k8s.io/v1beta1   false        FlowSchema
prioritylevelconfigurations                    flowcontrol.apiserver.k8s.io/v1beta1   false        PriorityLevelConfiguration
nodes                                          metrics.k8s.io/v1beta1                 false        NodeMetrics
ingressclasses                                 networking.k8s.io/v1                   false        IngressClass
runtimeclasses                                 node.k8s.io/v1                         false        RuntimeClass
podsecuritypolicies               psp          policy/v1beta1                         false        PodSecurityPolicy
clusterrolebindings                            rbac.authorization.k8s.io/v1           false        ClusterRoleBinding
clusterroles                                   rbac.authorization.k8s.io/v1           false        ClusterRole
priorityclasses                   pc           scheduling.k8s.io/v1                   false        PriorityClass
csidrivers                                     storage.k8s.io/v1                      false        CSIDriver
csinodes                                       storage.k8s.io/v1                      false        CSINode
storageclasses                    sc           storage.k8s.io/v1                      false        StorageClass
volumeattachments                              storage.k8s.io/v1                      false        VolumeAttachment

2.7 权限降级

RoleBinding也可以引用ClusterRole,对属于同一命名空间内ClusterRole定义的资源主体进行授权。一种常见的做法是集群管理员为集群范围预先定义好一组ClusterRole,然后在多个命名空间中重复使用这些ClusterRole。

2.7.1 绑定用户

例如,在下面的例子中,虽然read-only-cluster-role是一个集群角色,但是因为使用了RoleBinding,所以zhangsan只能读取kubernetes-dashboard命名空间中的资源:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: read-only-cluster-role
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: ["apps", "batch", "extensions", "networking.k8s.io", "policy", "rbac.authorization.k8s.io", "storage.k8s.io", "autoscaling"]
    resources: ["*"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: dashboard-test-rolebinding
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: read-only-cluster-role
subjects:
- kind: User
  name: zhangsan
  apiGroup: rbac.authorization.k8s.io

注意如果rolebinding的metadata.namecpace未指定,则默认授权的是default命名空间。

测试权限

切换到张三的kubeconfig

mv config config-a
mv config-zs config

获取资源

[root@master-1 .kube]# kubectl get svc,secret
Error from server (Forbidden): services is forbidden: User "zhangsan" cannot list resource "services" in API group "" in the namespace "default"
Error from server (Forbidden): secrets is forbidden: User "zhangsan" cannot list resource "secrets" in API group "" in the namespace "default"

获取授权的命名空间资源

[root@master-1 .kube]# kubectl get svc -n kubernetes-dashboard
NAME                        TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
dashboard-metrics-scraper   ClusterIP   10.0.103.140   <none>        8000/TCP        28h
kubernetes-dashboard        NodePort    10.0.14.33     <none>        443:38778/TCP   28h
[root@master-1 .kube]#
[root@master-1 .kube]# kubectl get svc,pod,cm,deploy,secret -n kubernetes-dashboard
NAME                                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)         AGE
service/dashboard-metrics-scraper   ClusterIP   10.0.103.140   <none>        8000/TCP        28h
service/kubernetes-dashboard        NodePort    10.0.14.33     <none>        443:38778/TCP   28h

NAME                                             READY   STATUS    RESTARTS   AGE
pod/dashboard-metrics-scraper-6c68887d4f-zgljm   1/1     Running   3          28h
pod/kubernetes-dashboard-6fb98955f6-swdf4        1/1     Running   3          28h

NAME                                      DATA   AGE
configmap/kube-root-ca.crt                1      28h
configmap/kubernetes-dashboard-settings   0      28h

NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dashboard-metrics-scraper   1/1     1            1           28h
deployment.apps/kubernetes-dashboard        1/1     1            1           28h

NAME                                           TYPE                                  DATA   AGE
secret/dashboard-test-sa-token-x4bzx           kubernetes.io/service-account-token   3      6m14s
secret/default-token-mrr2s                     kubernetes.io/service-account-token   3      28h
secret/kubernetes-dashboard-certs              Opaque                                0      28h
secret/kubernetes-dashboard-csrf               Opaque                                1      28h
secret/kubernetes-dashboard-key-holder         Opaque                                2      28h
secret/kubernetes-dashboard-read-token-9w5r9   kubernetes.io/service-account-token   3      25h
secret/kubernetes-dashboard-token-6r4nl        kubernetes.io/service-account-token   3      28h

2.7.2 绑定SA

apiVersion: v1
kind: ServiceAccount
metadata:
  name: test-read
  namespace: kube-system

---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: read-only-cluster-role
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: ["apps", "batch", "extensions", "networking.k8s.io", "policy", "rbac.authorization.k8s.io", "storage.k8s.io", "autoscaling"]
    resources: ["*"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]

---

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-only-rolebinding
  namespace: kube-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: read-only-cluster-role
subjects:
- kind: ServiceAccount
  name: test-read
  namespace: kube-system

创建sa的上下文

[root@master-1 dashboard]# kubectl describe secret test-read-token-fcmbb -n kube-system
Name:         test-read-token-fcmbb
Namespace:    kube-system
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: test-read
              kubernetes.io/service-account.uid: 16787adf-6811-4df8-8c62-85d5a19d6958

Type:  kubernetes.io/service-account-token

Data
====
namespace:  11 bytes
token:      eyJhbGciOiJSUzI1NiIs7JZg_O3nI68o55OfYvK_urzFEPzIeQzCKzHjXn9Ssfw5gQ1R9CuQXNGH0PCPKkCsLCRJBVb7bHIsdxkzL9A
ca.crt:     1326 bytes

[root@master-1 dashboard]# READ_TOKEN=eyJhbGciOiJSUzI1NiIsImtpZCIRia1NIZW56HWRKe3Mw5gQ1R9CuQXNGH0PCPKkCsLCRXz7dskL9A
[root@master-1 dashboard]# echo $READ_TOKEN
eyJhbGciOiJSUzI1NiIsImtpZCI6InBKV3FGbERnYVltWHA3XzRRQy1OSWRia1NIZW5FSE5lcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRl
kubectl config set-cluster kubernetes --certificate-authority=/opt/tls/k8s/ca.pem --server="https://192.168.43.129:6443" 

kubectl config set-credentials system-read --token=$READ_TOKEN
 
kubectl config set-context system-read-context --cluster=kubernetes --user=system-read
 
kubectl config use-context system-read-context

查看权限

]# kubectl  get pod
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:kube-system:test-read" cannot list resource "pods" in API group "" in the namespace "default"

]# kubectl  get pod -n kube-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-7775799c8c-2xjvh   1/1     Running   16         9d
calico-kube-controllers-7775799c8c-48w8h   1/1     Running   15         9d
calico-kube-controllers-7775799c8c-gss8z   1/1     Running   70         39d
calico-node-cczr6                          1/1     Running   60         39d
calico-node-k89f9                          1/1     Running   60         39d
calico-node-nk8qv                          1/1     Running   2          3d19h
calico-node-w4xgb                          1/1     Running   62         39d
calico-typha-5dc577d877-ht7rq              1/1     Running   60         39d
coredns-6bd54f798b-7fl28                   1/1     Running   15         9d
coredns-6bd54f798b-r5gkr                   1/1     Running   16         9d
metrics-server-5bbd7cb4c6-kkdct            1/1     Running   15         9d

]# kubectl auth can-i --list -n kube-system
Resources                                       Non-Resource URLs                     Resource Names   Verbs
selfsubjectaccessreviews.authorization.k8s.io   []                                    []               [create]
selfsubjectrulesreviews.authorization.k8s.io    []                                    []               [create]
*                                               []                                    []               [get list watch create update patch]
*.apps                                          []                                    []               [get list watch create update patch]
*.autoscaling                                   []                                    []               [get list watch create update patch]
*.batch                                         []                                    []               [get list watch create update patch]
*.extensions                                    []                                    []               [get list watch create update patch]
*.networking.k8s.io                             []                                    []               [get list watch create update patch]
*.policy                                        []                                    []               [get list watch create update patch]
*.rbac.authorization.k8s.io                     []                                    []               [get list watch create update patch]
*.storage.k8s.io                                []                                    []               [get list watch create update patch]
                                                [/.well-known/openid-configuration]   []               [get]
                                                [/api/*]                              []               [get]
                                                [/api]                                []               [get]
                                                [/apis/*]                             []               [get]
                                                [/apis]                               []               [get]
                                                [/healthz]                            []               [get]
                                                [/healthz]                            []               [get]
                                                [/livez]                              []               [get]
                                                [/livez]                              []               [get]
                                                [/openapi/*]                          []               [get]
                                                [/openapi]                            []               [get]
                                                [/openid/v1/jwks]                     []               [get]
                                                [/readyz]                             []               [get]
                                                [/readyz]                             []               [get]
                                                [/version/]                           []               [get]
                                                [/version/]                           []               [get]
                                                [/version]                            []               [get]
                                                [/version]                            []               [get]

对某个命名空间下所有的sa授权

 所有Service Account

 

posted @ 2024-12-09 14:50  不会跳舞的胖子  阅读(36)  评论(0编辑  收藏  举报