ServiceAccount 和 rbac

一、简单感受一下:

可以通过将不同的sa赋值给pod来控制每个pod可以访问的资源。当api服务器收到一个带有认证token的请求时,服务器会用这个token来验证发送请求的客户端所关联的sa是否运行执行请求的操作。

几个注意点:

1、向sa中添加镜像拉取秘钥可以不必对每个pod都单独进行镜像拉取秘钥的添加操作。

2、pod的sa必须在pod创建时进行设置,后续不能被修改。

3、让pod只允许挂载sa中列出的可挂载秘钥,sa在创建的时候就必须指定注解,kubernetes.io/enforce-mountable-secrets="true"

 

二、token

1、创建个pod

apiVersion: v1
kind: Pod
metadata:
  name: curl-custom-sa
spec:
  serviceAccountName: foo
  containers:
  - name: main
    image: tutum/curl
    command: ["sleep", "9999999"]
  - name: ambassador
    image: luksa/kubectl-proxy:1.6.2

2、查看挂载进pod容器内的token

kubectl exec -it curl-custom-sa -c main cat /var/run/secrets/kubernetes.io/serviceaccount/token
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
eyJhbGciOiJSUzI1NiIsImtpZCI6ImduV1VxbVFYdkh6eWVjSER3SHdsUXE3b3Jpd1NfazB0OGNxaUIzaVdnUVUifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjkyNjAwNTMxLCJpYXQiOjE2NjEwNjQ1MzEsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJjdXJsLWN1c3RvbS1zYSIsInVpZCI6IjE0ZDhjNjg3LWE0YzQtNDU0ZS1hODY3LThkNmEzYzU3YWE1OCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZm9vIiwidWlkIjoiZGEzYmEyODYtMjZkYi00MjIzLWFmNmQtNzVmYTdhYmNiMWNhIn0sIndhcm5hZnRlciI6MTY2MTA2ODEzOH0sIm5iZiI6MTY2MTA2NDUzMSwic3ViIjoic3lzdGVtOnNlcnZpY2VhY2NvdW50OmRlZmF1bHQ6Zm9vIn0.H5Xw6qHWeML9Sfxh7PKjUx2yiSx2LHun84t4twZcpcDkc0aCfDSu1m8AAQWKh68QF6JM-HpczSa_ZHnxzqIUOpnGPkh7hH8xftRX6fdkKFfzXfO9ojkGF9ptrhA8JKuf3bGP5lRfQ3dFEIqMMqgvDOmN1iq0knaFjHXnvh6WJBiNN4eezAyILo-zUKsUOnJrO8mJq2PG3V3NCPiYaWG2pyvBrZqJXdlcWKmYJsIm-UyTVsHGbnwEYgUKKXc7HkL3MebxfYpqUKz38LZde61mKxNkzZVyRn1cwoqqE_vz99wgN8mc-FthMV14k_F93bCFqCUt4xO5oY73r4LRsUE5x

3、我自己尝试的创建的sa是没有操作权限的。 

 

三、rbac,除了rbac还有其他的授权插件,授权插件检查是否允许用户请求的动作执行。

1、认证动词和http方法之间的映射关系

http方法 单一资源的动词 集合的动词
GET,HEAD get(以及watch用户监听) list(以及watch)
POST create n/a
PUT update n/a
PATCH patch n/a
DELETE delete deletecollection

2、role和rolebinding

角色定义了可以做什么操作,绑定定义了谁可以做这些操作。

角色和集群角色,区别在于角色和角色绑定是命名空间资源,而集群角色和集群角色绑定是集群级别的资源。

角色和角色绑定:

2.1)创建sa

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2022-08-14T08:26:34Z"
  name: foo
  namespace: default
  resourceVersion: "4311847"
  uid: da3ba286-26db-4223-af6d-75fa7abcb1ca
secrets:
- name: foo-token-rjkxw

2.2)创建role,在指定资源时,必须使用复数的形式。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: service-reader
rules:
- apiGroups: [""]
  verbs: ["get", "list"]
  resources: ["services"]

2.3)rolebinding,如果要绑定一个user(用户)而不是sa上,使用--user作为参数来指定用户名。如果要绑定角色到组,可以使用--group参数。

kubectl create rolebinding test --role=service-reader --serviceaccount=default:foo -n default 

2.4)测试

kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/namespaces/default/services
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "4619791"
  },
  "items": [
  .
  .
  .
  .

查看pod时就返回403

kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/namespaces/default/pod     
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
    
  },
  "status": "Failure",
  "message": "pod is forbidden: User \"system:serviceaccount:default:foo\" cannot list resource \"pod\" in API group \"\" in the namespace \"default\"",
  "reason": "Forbidden",
  "details": {
    "kind": "pod"
  },
  "code": 403
}            

 

2.5)rolebinding将来自不同命名空间的sa绑定到同一个role, rolebinding可以引用来自其他命名空间中的sa。这样就实现了访问其他ns中的资源

以下发生在ttt这个ns。

kubectl get sa bar -n ttt -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2022-08-14T09:48:41Z"
  name: bar
  namespace: ttt
  resourceVersion: "4317975"
  uid: 801153c4-3d5a-4d31-9395-f18fd693cd52
secrets:
- name: bar-token-tclnh
---
apiVersion: v1
kind: Pod
metadata:
  name: curl-custom-sa-ttt
  namespace: ttt
spec:
  serviceAccountName: bar

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  creationTimestamp: "2022-08-14T09:17:30Z"
  name: test
  namespace: default
  resourceVersion: "4318642"
  uid: 4c3945aa-044e-40c7-8c5f-91c924388ee9
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: service-reader
subjects:
- kind: ServiceAccount
  name: bar
  namespace: ttt
- kind: ServiceAccount
  name: foo
  namespace: default
  containers:
  - name: main
    image: tutum/curl
    command: ["sleep", "9999999"]
  - name: ambassador
    image: luksa/kubectl-proxy:1.6.2

在ttt 命名空间中测试是否可以访问default中的service,别的资源是不行的。

kubectl -n ttt exec -it curl-custom-sa-ttt -c main curl localhost:8001/api/v1/namespaces/default/services 
{
  "kind": "ServiceList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "4620600"
  },
  "items": [
    {
      "metadata": {
        "name": "kubernetes",
        "namespace": "default",
        "uid": "bf42983a-5db3-42d7-803d-2d10886c762a",
        "resourceVersion": "205",
        "creationTimestamp": "2022-03-29T10:01:42Z",
        "labels": {
          "component": "apiserver",
          "provider": "kubernetes"
            .
            .   
            .

 

3、culster-role和cluster-rolebinding

一个常规的角色只允许访问和角色在同一命名空间中的资源。如果你希望允许跨不同命名空间访问资源,就必须要在每个ns中创建一个role和rolebinding。如果你想将这种行为扩展到所有的ns,需要在每个ns中创建相同的role和rolebinding。

3.1) 试试普通的功能

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: pv-reader
rules:
- apiGroups: [""]
  verbs: ["get", "list"]
  resources: ["persistentvolumes"]

---

kubectl create clusterrolebinding pv-test --clusterrole=pv-reader --serviceaccount=default:foo

---
kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/persistentvolumes       
{
  "kind": "PersistentVolumeList",
  "apiVersion": "v1",
  "metadata": {
    "resourceVersion": "4624017"
  },
  "items": [
    {
      "metadata": {
        "name": "pv-a",
        "uid": "8a5ddc4a-b232-4958-a187-cfdfc122aa08",
        "resourceVersion": "3747274",
        "creationTimestamp": "2022-07-31T10:15:56Z",
        "annotations": {
          "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolume\",\"metadata\":{\"annotations\":{},\"name\":\"pv-a\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"capacity\":{\"storage\":\"1Mi\"},\"h
      ...

测试的接口路径里面没有包含命名空间,因为pv不在命名空间里面,rolebinding虽然可以在你想开启命名空间资源的访问时引用一个clusterrole,但是不能对集群级别(没有命名空间)资源使用相同的方法。必须使用cluster-rolebinding来对集群级别的资源进行授权访问。

一个rolebinding不能授予集群级别的资源访问权限,即使它引用率一个cluster-rolebinding。

 

4、允许访问非资源型的url

api服务器也会对外暴露非资源型的url。访问这些url也必须要显示地授予权限,否则api服务器会拒绝客户端的请求。

例如:

xxx@localhost serviceaccount % kubectl get clusterrole system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-03-29T10:01:41Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:discovery
  resourceVersion: "84"
  uid: f7ee554f-8c0a-421f-b88a-be30542989c9
rules:
- nonResourceURLs:
  - /api
  - /api/*
  - /apis
  - /apis/*
  - /healthz
  - /livez
  - /openapi
  - /openapi/*
  - /readyz
  - /version
  - /version/
  verbs:
  - get


  
xxx@localhost serviceaccount % kubectl get clusterrolebinding system:discovery -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-03-29T10:01:41Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  name: system:discovery
  resourceVersion: "148"
  uid: cce8a7de-668f-4b7d-bdb0-3075ec71c49d
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: system:discovery
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: Group
  name: system:authenticated

 

5、使用clusterRole来授权访问指定命名空间中的资源

cluster不是必须一直和集群级别的clusterRoleBinding捆绑使用。他们也可以和常规的有命名空间的rolebinding进行捆绑。

kubectl get clusterrole view -o yaml
aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.authorization.k8s.io/aggregate-to-view: "true"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2022-03-29T10:01:41Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
    rbac.authorization.k8s.io/aggregate-to-edit: "true"
  name: view
  resourceVersion: "390"
  uid: ddd1999c-a8c5-426c-9359-93b5495a99ae
rules:
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - discovery.k8s.io
  resources:
  - endpointslices
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
View Code

clusterRole 和 clusterRolebinding捆绑,那在绑定中列出的主体可以在所有命名空间中查看指定资源。

culsterRole 和 rolebinding捆绑,那在绑定中列出的主体只能查看在rolebinding命名空间中的资源。

 

5.1)绑定试试

kubectl create clusterrolebinding view-test --clusterrole=view --serviceaccount=default:foo

kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/pods
kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1/namespaces/ttt/pods

5.2)缓存rolebinding 就变成只能查询对应ns中的资源

 

6、何时使用具体的role和 binding组合。

访问的资源 使用的角色类型 使用的绑定类型
集群级别的资源(nodes,pv,...) clusterRole clusterRoleBinding
非资源型url(/api,/healthz,...) clusterRole clusterRoleBinding
在任何ns中的资源 clusterRole clusterRoleBinding
在具体ns中的资源(在多个ns中重用这个相同的clusterrole) clusterRole rolebinding
在具体的ns中的资源 role rolebinding
posted @ 2022-08-21 17:40  JvvYou  阅读(219)  评论(0编辑  收藏  举报