Author: Wang Changsheng

We know that all operations on resource objects are done through the Apiserver, so how does the cluster know that our request is valid? This requires an understanding of Kubernetes authentication process

API objects

Before we talk about authentication authentication, we need to understand the objects in the Kubernetes cluster. We know that in the Kubernetes cluster, the Kubernetes object is the entity that we persist, which is the data that is eventually stored in the ETCD. We directly write the YAML file, through kubectl to submit the resource manifest file, and then create the corresponding resource object, so how does it convert our YAML file into an API object in the cluster?

The Kubernetes API is an HTTP service that uses JSON as the main serialization method. It also supports Protocol Buffers serialization, which is used for intra-cluster communication between components. Kubernetes API documentation can refer to website https://kubernetes.io/docs/re… Read and learn

For scalability, Kubernetes supports multiple API versions under different API paths (such as/API /v1 or /apis/batch), and different API versions imply different levels of stability and support:

  • Alpha levels such as v1alpha1 are disabled by default and support for features can be removed at any time, so use with caution
  • Beta levels, such as V2Beta1, are enabled by default, indicating that the code has been well tested, but that the semantics of the object may change in incompatible ways in subsequent versions
  • Stable levels, such as v1, indicate that it is already stable and will be present in many subsequent releases.

In Kubernetes cluster, the full Resource path of an API object in the ETCD consists of three parts: Group (API), Version (API) and Resource. With this structure, all the API objects in Kubernetes can actually be represented as the following tree structure:

From the figure above we can also see how Kubernetes’ API objects are organized. At the top level, we can see that there is a core group (for historical reasons, Is everything under/API /v1 instead of under /apis/core/v1) and named groups (path /apis/$NAME/$VERSION) and system-wide entities such as /metrics. We can also use the following command to see the organization of the API in the cluster:

[root@k8s-master ~]# kubectl get --raw /
{
  "paths": [
    "/api",
    "/api/v1",
    "/apis",
    "/apis/",
    ...
    "/version"
  ]
}

For example, if we look at the resource objects under the core group, we can also query the data through kubectl, in which we can see the resource objects under the core group and the corresponding operations

[root@k8s-master ~]# kubectl get --raw /api/v1 | python -m json.tool
{
    "groupVersion": "v1",
    "kind": "APIResourceList",
    "resources": [
        {
            "kind": "Binding",
            "name": "bindings",
            "namespaced": true,
            "singularName": "",
            "verbs": [
                "create"
            ]
        },
        {
            "kind": "ComponentStatus",
            "name": "componentstatuses",
            "namespaced": false,
            "shortNames": [
                "cs"
            ],
            "singularName": "",
            "verbs": [
                "get",
                "list"
            ]
        },
        {
            "kind": "ConfigMap",
            "name": "configmaps",
            "namespaced": true,
            "shortNames": [
                "cm"
            ],
            "singularName": "",
            "storageVersionHash": "qFsyl6wFWjQ=",
            "verbs": [
                "create",
                "delete",
                "deletecollection",
                "get",
                "list",
                "patch",
                "update",
                "watch"
            ]
        },
        ...
        {
            "kind": "Service",
            "name": "services/status",
            "namespaced": true,
            "singularName": "",
            "verbs": [
                "get",
                "patch",
                "update"
            ]
        }

However, this operation is different from the way we normally operate HTTP services. Here, we can use the kubectl proxy command to start a proxy HTTP service to access Apiserver:

[root@k8s-master ~]# kubectl proxy
Starting to serve on 127.0.0.1:8001

Then open a new terminal, we can access the interface of the Apiserver through the following proxy service, for example, we can access the interface to query a namespace POD resource object

/ root @ k8s - master ~ # curl http://127.0.0.1:8001/api/v1/namespaces/default/pods {" kind ":" PodList ", "apiVersion" : "v1", "metadata": { "selfLink": "/api/v1/namespaces/default/pods", "resourceVersion": "9109616" }, "items": [ { "metadata": { "name": "nginx-deploy-75c7f965d8-hnmvn", "generateName": "nginx-deploy-75c7f965d8-", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/nginx-deploy-75c7f965d8-hnmvn", "uid": "574ac979-41b8-460f-afaf-d29155911ba3", "resourceVersion": "6786396", "creationTimestamp": "2021-05-10T03:30:07Z", "labels": { "app": "nginx", "pod-template-hash": "75c7f965d8" }, "ownerReferences": [ { "apiVersion": "apps/v1", "kind": "ReplicaSet", "name": "nginx-deploy-75c7f965d8", "uid": "25bdae05-87e9-41e0-bcde-6bfeda87047c", "controller": true, "blockOwnerDeletion": true } ], ...

In general, the Kubernetes API supports creating, updating, deleting, and retrieving operations on a specified PATH PATH via standard HTTP POST, PUT, DELETE, and GET, using JSON as the default data interaction format.

Kubernetes certification

We used the method of Kubectl or Kubectl Proxy above to obtain the data of resource objects of Apiserver smoothly, because they have passed the authentication authentication component of Kubernetes smoothly

The flow of requests from the Kubernetes API to the operation storage layer is shown in the figure

Next, we will analyze the authentication methods of Kubectl, Kubectl Proxy and POD to access Apiserver

Kubectl access apiserver

The authentication method used by Kubectl is ClientCA authentication. X509 authentication is the default authentication method used between Kubernetes components. It is also the frequently used access credential in the corresponding kube-config of Kubectl client. It is a secure way for visitors to access the Apiserver using a client certificate issued by the cluster CA or by the Granting CA that was added to the Apiserver configuration. After receiving the request, the APIServer will conduct the TLS handshake process. In addition to verifying the validity of the certificate, Apiserver also verifies information such as the requested source address of the client certificate, enabling two-way authentication. For example, let’s check the certificate information of our kubectl

[root@k8s-master ~]# cat ~/.kube/config apiVersion: v1 contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes users: - name: kubernetes-admin user: client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lJVmxIbDlTalNvdFF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0Ex VUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TVRBME1EY3hNVFF6TXpsYUZ3MHlNakEwTURjeE1UUXpOREZhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJU cHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFF QXFzVnlQc2RQRGlEYW9FNWcKZWxOQjV4ZHJoZCs1eEd5RUJFbGpUY2tMb3JPQlN6SjE3Z2JpY0VSaXRQLzh1YVpmVk9ISnZ0Y2tyZUpGa3NHNgp2Ujc5YUk4 d3k0elUreEk0ZzdzK2ZrTFRsK1QrR2xaSWlQaXN3a2RQZE9ad0REUDBKdDQ5NjljVzFndVJ6UTVQCmhpSjRTcE96Z0dmeFJGQWpFTUFCNktJcXBWYjlrbmV4 d0xHVDRRNTZNS1JvV294UytEaFBQZFk4bUlVR3pHZ0oKbkw1bEl1Mjl2a0FmWG1vZEdZMVFUNkszSXU3NmFhWXl0TTVRUTZZVnFwekxXU0lYOFN2L0E0dlFq VDlTSDY5eQptQ1RmQ0lXWjVTRGZ4VTlvQ0p5RGpKTmpBdUErNWJONUpxMDFEYjhjK0hjTHVHUENBRVJUVnBZU3docWx1T0lFCk40SU9Md0lEQVFBQm8wZ3dS akFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0h3WURWUjBqQkJnd0ZvQVV6RmZHVHJhMjRVa3hzM2NReWJzSnpr T2R2UXN3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFDRHUwQ3g5Qk1NdjdUMnh6T3gzTDNNczk5NTdKMDY3WDVhbTZnZW4yaXltekViMkNldG51REdoCnFM WW5MZnBOZ1FOQ1pTbkg5dzZIYjdWenRMTzlheXZjejcvRVlRVkpyOVN0MzdtZDc0d3dKY1AvZWY1b2ZEbkgKVTVJaXZKK1RuM3REeGhlVVU5VlBFSkdCbFZm d3N0UmxJZ3NWclR0TkVnNGYzaW04azZzNlRTTGV5Sis4Y21zdgpwTmYyRDNpWWw3aEhBTGJwS2tFWVEya2xSY0IyRDFSL1Fhd2o4WWoyUGJ4cEZOU0t4QmQ4 S09mcGVaMWQ5ZmpiCmZMbUxGU29rZjk1b0lrTk9TSGpUanVDNmNaNGVHczU0bjhaMmhnMWZia1R0Y2pJK1ROZi9nY29FNExvM3JhaDgKbW1sa1Qxdit4T3hK UWpkbkdwT2FSNytINFkwblY5dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBcXNWeVBzZFBEaURhb0U1Z2VsTkI1eGRyaGQrNXhHeUVCRWxqVGNrTG9y T0JTekoxCjdnYmljRVJpdFAvOHVhWmZWT0hKdnRja3JlSkZrc0c2dlI3OWFJOHd5NHpVK3hJNGc3cytma0xUbCtUK0dsWkkKaVBpc3drZFBkT1p3RERQMEp0 NDk2OWNXMWd1UnpRNVBoaUo0U3BPemdHZnhSRkFqRU1BQjZLSXFwVmI5a25leAp3TEdUNFE1Nk1LUm9Xb3hTK0RoUFBkWThtSVVHekdnSm5MNWxJdTI5dmtB Zlhtb2RHWTFRVDZLM0l1NzZhYVl5CnRNNVFRNllWcXB6TFdTSVg4U3YvQTR2UWpUOVNINjl5bUNUZkNJV1o1U0RmeFU5b0NKeURqSk5qQXVBKzViTjUKSnEw MURiOGMrSGNMdUdQQ0FFUlRWcFlTd2hxbHVPSUVONElPTHdJREFRQUJBb0lCQUdLQnVzRVQzenBiSVVIUApkRCtidnl3NmlqK1RLbWx2MzBkSnZncWtxaDJV UmtUR090aXZCL2VTdXcyRmpKYmFyYXNkQTI4ZVUzNHFROC9BCkNLUUhPRTRVS3lWL2Uydkl1dWppSGM1ZlpnYjhoTWRVZGtyc2gxc2FIMjlqYmNiY1FUNGFm TVdLTVJZUFhtOVcKamZEbCtWV3JsYVBBVWFBQ1NmZmppalpUTlI1aCtuSUxxazdLQ3dUelRTRk1FNmNpS3g3NkhJZ08wODlhSzJGTgpqNWpLTjRhdWtSSTQy MnNiYmFvRGNsMXVpNVFtaHFVU0xCVVQvemVhTHM0MXJrN2w4MWNtQXhYQll0YXRwb1A0Ci84dDQzSkMyRVdYQU5BZDQ1cW1jbzVBUmZoMUZJMWo4ejB3dFZp akhDSmFIMmo4TjhGTHh3YzhZL0ttNGphMncKcVVyK0dhRUNnWUVBei95dVJMUDBBbWwvRXhLN0oxVUpERnJGbG5GTHVsRmVDM2dwWFRCL0NxUXFOL1BkbDVD dgpKbVpCV3VhTXArWEJna0NMZE5UV1BNMGFIUEd3aExKUWZXa1ZYc1lCM2VENllwM0pXVGR1dmJvbVVuRzY1TC9yCnF2WTVSUy83WWNmRnZtbVNNYVAxeCsx UDFEQWVUWHBvdllBczlIS2U3RFh4UUUxL3BEOHEwTzBDZ1lFQTBqRngKSlpQU1J4RE5tNVNaTzNsYUZwVDJKdGJQdDUvdUtXRjAraDZvWlNKaDlPVjhhaVM5 NlRPRStYREYwaHk5ZVBMbAp6a1NFQ0hEOEE3ZVF0OWc1VGc2c3lCWkpWMXJzYUN0YjRCWGRpcU1jSGE4SWhLQW9ySnpxYldGTXZmdG1WMjc5CjMrVldGaW13 dnBuTzNWaHhnQ3lLWjRhRjdaNkV2T1ZDb3IzNDVBc0NnWUVBeUlkME1qTmFtUlREKzB5OCsxQW0KZUMzd2dYdGNxeGdXVjNLVVZ4QVIvTjJKQXdkeDU5Y011 RFl3M3dhWUtLMEJwS2E4am5sQzBiNWlaZk8wNEV2WQpCUUpUSTF3L29vQnVpTFJlMUZENHlaNTNvbGVhL1QvNVpZMGViSkcxaW5JRk92QW9qd25wUjhpTGhp YWFvTkxiCnQ1R2tSazlZNEorbHFmek9penFIK29VQ2dZQUp0aWNZS1dCSjBFanZxMG41S1g0MEZPWGFuWW96WGJ4UFJTVjIKZVB3bTBCUGVrTXZTeTZmS29v cStTNnVZTGFQRGR0V1BWak1UZ01Ua0Z4TWtxMlRhYW1zcFEzNVgvdWQxV0t1QwpDd0NWYXp2ZFV6ejlnN2pkWU5La0F4N2NtRVQrUFM2VnJhN3dqelNQV2VQ bzdqRXdUdDZHTWZ6MklhRFlhVzlPCnZhQkdTUUtCZ0dEaGdvK3BucWFrZmhVRE15bWxwQ3ZiNWZXS000RzJWbDFHZEdaSlFSWEpPR0hqbjlyNWZuQzEKdGx4 d3BBN2NucjNPalRLYVRYeVM1SzA0QlVzQ0l2UFZmZVZlMW9ydm9rR3ZkNGJxUlFab3AvVlFzWnI2RGpnTApqUjV4UzBOdXJnR2QzVVEwRHFhL0xOQW9mMEFO dG9nTHM1Vm1VL1pueDA2L3dndHN6empnCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==

By default, we use the kubectl command line. The default context used is kubernetes-admin@kubernetes, and the kubernetes user is kubernetes-admin, whose certificate contains the authentication information

echo -n "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFekNDQWZ1Z0F3SUJBZ0lJVmxIbDlTalNvdFF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0E xVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TVRBME1EY3hNVFF6TXpsYUZ3MHlNakEwTURjeE1UUXpOREZhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJ UcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVF FQXFzVnlQc2RQRGlEYW9FNWcKZWxOQjV4ZHJoZCs1eEd5RUJFbGpUY2tMb3JPQlN6SjE3Z2JpY0VSaXRQLzh1YVpmVk9ISnZ0Y2tyZUpGa3NHNgp2Ujc5YUk 4d3k0elUreEk0ZzdzK2ZrTFRsK1QrR2xaSWlQaXN3a2RQZE9ad0REUDBKdDQ5NjljVzFndVJ6UTVQCmhpSjRTcE96Z0dmeFJGQWpFTUFCNktJcXBWYjlrbmV 4d0xHVDRRNTZNS1JvV294UytEaFBQZFk4bUlVR3pHZ0oKbkw1bEl1Mjl2a0FmWG1vZEdZMVFUNkszSXU3NmFhWXl0TTVRUTZZVnFwekxXU0lYOFN2L0E0dlF qVDlTSDY5eQptQ1RmQ0lXWjVTRGZ4VTlvQ0p5RGpKTmpBdUErNWJONUpxMDFEYjhjK0hjTHVHUENBRVJUVnBZU3docWx1T0lFCk40SU9Md0lEQVFBQm8wZ3d SakFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0h3WURWUjBqQkJnd0ZvQVV6RmZHVHJhMjRVa3hzM2NReWJzSnp rT2R2UXN3RFFZSktvWklodmNOQVFFTApCUUFEZ2dFQkFDRHUwQ3g5Qk1NdjdUMnh6T3gzTDNNczk5NTdKMDY3WDVhbTZnZW4yaXltekViMkNldG51REdoCnF MWW5MZnBOZ1FOQ1pTbkg5dzZIYjdWenRMTzlheXZjejcvRVlRVkpyOVN0MzdtZDc0d3dKY1AvZWY1b2ZEbkgKVTVJaXZKK1RuM3REeGhlVVU5VlBFSkdCbFZ md3N0UmxJZ3NWclR0TkVnNGYzaW04azZzNlRTTGV5Sis4Y21zdgpwTmYyRDNpWWw3aEhBTGJwS2tFWVEya2xSY0IyRDFSL1Fhd2o4WWoyUGJ4cEZOU0t4QmQ 4S09mcGVaMWQ5ZmpiCmZMbUxGU29rZjk1b0lrTk9TSGpUanVDNmNaNGVHczU0bjhaMmhnMWZia1R0Y2pJK1ROZi9nY29FNExvM3JhaDgKbW1sa1Qxdit4T3h KUWpkbkdwT2FSNytINFkwblY5dz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo="|base64 -d|openssl x509 -text certificate: Data: Version: 3 (0x2) Serial Number: 6220005401490006740 (0x5651e5f528d2a2d4) Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Apr 7 11:43:39 2021 GMT Not After : Apr 7 11:43:41 2022 GMT Subject: O=system:masters, CN=kubernetes-admin ...

Where Subject: O= System: Masters and CN=kubernetes-admin represent the O user group and the CN user group respectively, and kubernetes has configured the corresponding permissions for these users and groups based on RBAC

Kubectl Proxy accesses Apiserver

Kubectl Proxy uses RequestHeader authentication, In this mode, we make a request to the proxy service via HTTP. At this time, the proxy service will send the request to Kube-Apiserver. Before this, the proxy service will send the request to the proxy service. The proxy will add the certificate information to the request header sent to the kube-apiserver.

  • –requestheader-username-headers=X-Remote-User
  • –requestheader-group-headers=X-Remote-Group
  • –requestheader-extra-headers-prefix=X-Remote-Extra-
  • — questheader-client-ca-file: Prevent header spoofs
  • — requestTheader-allowable -names: Sets the list of CN’s allowed
  • –proxy-client-cert-file: Client certificate
  • –proxy-client-key-file: The client’s private key
   [root@k8s-master ~]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
   ...
     - --proxy-client-cert-file=/etc/kubernetes/pki/front-proxy-client.crt
    - --proxy-client-key-file=/etc/kubernetes/pki/front-proxy-client.key
    - --requestheader-allowed-names=front-proxy-client
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --requestheader-extra-headers-prefix=X-Remote-Extra-
    - --requestheader-group-headers=X-Remote-Group
    - --requestheader-username-headers=X-Remote-User
   ...

We checked the corresponding proxy-client-cert-file certificate to obtain user information

[root@k8s-master ~]# cat /etc/kubernetes/pki/front-proxy-client.crt|openssl x509 -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 1421614817980964257 (0x13ba9725192fdda1)
    Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=front-proxy-ca
        Validity
            Not Before: Apr  7 11:43:40 2021 GMT
            Not After : Apr  7 11:43:40 2022 GMT
        Subject: CN=front-proxy-client

— requestTheader-allowable -names=front-proxy-client; — requestTheader-allowable -names=front-proxy-client; — requestTheader-allowable -names=front-proxy-client

Pod access apiserver

POD uses ServiceAccountauth authentication to access APIServer. ServiceAccount is the only APIServer access credential that can be managed by API in K8S. It is usually used for the interaction between business processes in POD and APIServer. ServiceAccount solves the identity authentication problem of POD in the cluster. Authorization information used for authentication is stored in secret (created by SecretAccount Controller). A ServiceAccount named default and the corresponding Secret are also generated under that namespace:

[root@k8s-master ~]# kubectl get sa default -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2021-04-07T11:44:12Z"
  name: default
  namespace: default
  resourceVersion: "379"
  selfLink: /api/v1/namespaces/default/serviceaccounts/default
  uid: 3493e0f4-a87c-4c0e-a373-3c117d205d8d
secrets:
- name: default-token-s46zd
[root@k8s-master ~]# kubectl get secret default-token-s46zd -o yaml apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRX SmwKY201bGRHVnpNQjRYRFRJeE1EUXdOekV4TkRNek9Wb1hEVE14TURRd05URXhORE16T1Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FT SXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSlFWCjNmRmVraUdmL3ZDK1JPNFR4SC9QbkRhMmJINi9lRFAzNUc1SXppUnladmpUWWtN eGVyOHIrTWdndCtCN05oc28Ka0ZCVVNCVUhrbVhHZFFBUHRjNTJocVdGRlhtZk10TzBhNzZBTWNCdFZUa2hPZDRxc3NPcy9jUndVcGxYKytteApLcW9FdDc0 eFBhRnJxRzIyeDVEN011Y3lYQmtxQk4vWGRKcThKNU5xTWhHd2EvbjVtbWUxYmRrdGh3UWd1SnZzCkc2THRBZGZhRWdXbWxnUVFUMWZHNkhVV3g0L085aTJS NEhIU1VXMDFmTnUwaGFVekNJcE04VERLMk9DbDJYN04KcWE3QitGZDlZR1krUVdhNWVMZk9nMFJUcTJOb210M1E5WWVGWHJKZDJMOHlpc3VsbjM0ZDNxZjFQ akxtMkdJQwpQS01XenBVaWJxbkpNb0RvdjYwQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURW UjBPQkJZRUZNeFh4azYydHVGSk1iTjNFTW03Q2M1RG5iMExNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFBdW5WUXYvTnhnN2JCYXBiVWRVT2s4UWhkclZk bXFGVUlCWnlQN0FUMlh5eVNlMG8xVwp4dEU3c1NyWlQvZDJUTzJseFRLM0NQRVU2dW9uMDQ1amhyd1N1dGNVa3llMUZVcnF6aWNTa1luZjhnVFdOMmtlCnpU dWJ5OUowcVZFRVErc2cvU2Q1bERVUm9LSHAyVXRLZzdrbVRzT3d3U2ppVnlVZEdmMGcrZ2djUU9iMjFvNVgKYUtoOUtIQUdBVDRvQnlOdTY0STJEaWV0QkRk WWdsL3B5cTgwcCtwVTlLSDJObEZrMERhc01uU2I0eEE1M2U3RApJQVJua0JGOFNuSXR2a3pacFFTVWhXNVpJT2IvdjdOcWZxalhuTE8rdUx4czRPSllXL3V5 TzBpMEkrYUF5RWRYClUyUkMzZjIyUHV1VmNnWmZ6ck5vUzU5dnQwVVlVM1FRcURqMgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== namespace: ZGVmYXVsdA== token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklraDZZMnB4VlhCbk5ubFBVa3AxVVZwblYwbGthMmhOZG14TVpHeHdOa1pGVFdvMVFXUkhjbUpPWldNaWZR LmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZ VzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbVJsWm1G MWJIUXRkRzlyWlc0dGN6UTJlbVFpTENKcmRXSmxjbTVsZEdWekxtbHZMM05sY25acFkyVmhZMk52ZFc1MEwzTmxjblpwWTJVdFlXTmpiM1Z1ZEM1dVlXMWxJ am9pWkdWbVlYVnNkQ0lzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVnlkbWxqWlMxaFkyTnZkVzUwTG5WcFpDSTZJak0wT1RO bE1HWTBMV0U0TjJNdE5HTXdaUzFoTXpjekxUTmpNVEUzWkRJd05XUTRaQ0lzSW5OMVlpSTZJbk41YzNSbGJUcHpaWEoyYVdObFlXTmpiM1Z1ZERwa1pXWmhk V3gwT21SbFptRjFiSFFpZlEuWHc3Rm4zWURoTlViYWNMOVdMVW1ISFQzbzkyZ2d2c0t0dzdPY21PTUhyd2ZDTnlPUFRIWTFKTUtCRkpCZkIzcmhjdURncHI2 dHBpQm1BN0pnUzkwRTVhNG4zU1VoU0pscEE4eElZWU90aklJSFhaV25rYVg3T1c0WkRwU2RIVzNienNyOHBBc09SS2diTENzZ18yRlBmRGhybHRQMjFKNnZo OHZMUGlfVVJlTmtiSVM4WlgzcERFNTV2eHZlRkE1Zkk1S2NqLVJKdnRpOFQ3TUc5WjQxZU56OXlyWVd5SkRpenh5RUlLR0tEVnVIUjNyLXpvWm9icHhvQU1B cUc2aFN6NkhXUUkzVG45anVXcmVWTGJWYk9qUktzTmF4ZVNqOU5BSTBsZXRzQTJPVFVGcUF3M1drU3E0MnRZOE5fcm5NbkZuN1R3U3VqQk5hVmlPSl9xQi13  kind: Secret metadata: annotations: kubernetes.io/service-account.name: default ...

The corresponding Secret: data field contains two pieces of data: Ca.crt is used to verify the server side and token is used to authenticate the POD. Both of them are Base64-encoded POD when it is created. Admission Controller according to the corresponding specified ServiceAccount secret ca. CRT and token file mount to fixed the directory/var/run/secrets/kubernetes. IO/ServiceAccount

    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: default-token-s46zd
      readOnly: true

When POD wants to access APIServer, it uses the token file in Secret by default to authenticate the identity of POD, and uses CA.CRT to verify the server. After POD identity is authenticated and legitimate, its permissions need to be configured through RBAC

Kubernetes Authentication (RBAC)

All resource objects in Kubernetes are modeled API objects that allow CRUD(Create, Read, Update, Delete) operations, such as the following resources:

  • Pods
  • ConfigMaps
  • Deployments
  • Nodes
  • Secrets
  • Namespaces
  • . Possible operations for these resource objects are:
  • create
  • get
  • delete
  • list
  • update
  • edit
  • watch
  • exec
  • patch

At a higher level, these resources are associated with API groups, such as PODS belong to the Core API Group and Deployements belong to the Apps API Group. Now we need to use RBAC to manage resources in Kubernetes. In addition to the above resources and operations, we need to understand a few other concepts:

  • Rule: A Rule is a set of operations that belong to a set of different API Group resources
  • The Role and ClusterRole: Both roles and cluster roles contain the Rules element above. The difference between the two objects is that in Role, the Rules defined apply only to a single namespace, that is, associated with a namespace, while ClusterRole is cluster-scoped, so the Rules defined are not subject to namespace constraints. In addition, Role and ClusterRole are defined as the API resources inside the cluster in Kubernetes. Similar to POD, Deployment and other objects we have learned before, both of them are resource objects of our cluster, so the same can be described by YAML file. Use the kubectl tool to manage
  • Subject: Subject, which corresponds to the object in the cluster where the operation is attempted. There are three types of Subject resources defined in the cluster:

    • User Account: This is managed by a separate external service, where the administrator assigns private keys, uses a KeyStone or Google Account, or even a file list of User names and passwords. There is no resource object associated with the management cluster for users, so users cannot manage through the API within the cluster
    • Group: This is used to associate multiple accounts. There are some default groups created in the cluster, such as cluster-admin
    • The Service Account: Service accounts, some user accounts managed through Kubernetes API, are associated with namespace and are applicable to applications running inside the cluster. Permission authentication needs to be completed through API, so permission operation is carried out inside the cluster. We all need to use ServiceAccount
  • Role bindings RoleBinding and ClusterRoleBinding: Role bindings and cluster, is simply a statement of the Subject and our Role in the binding process (permissions to a user on the binding operation), the difference between the two is also a difference between scope: RoleBinding affects only resource operation permissions under the current namespace, while ClusterRoleBinding affects all namespaces.

Let’s use a few simple examples to demonstrate how RBAC can be used in a Kubernetes cluster.

You can only access normal users of a namespace

If we want to create a User Account, we can only access the default namespace, and the corresponding User information is as follows:

username: wangcs
group: imonkey

Create user credentials

As mentioned earlier, Kubernetes does not have an API object for User Account, but it is quite simple to create a User Account using a private key assigned to you by the administrator. For this, we can refer to the official documentation. Here we have to use the OpenSSL certificate to create a User wangcs to users to create a private key, is named wangcs. The key:

[root@k8s-master k8s-rbac]# openssl genrsa -out wangcs.key 2048 Generating RSA private key, 2048 bit long modulus .... + + +... +++ e is 65537 (0x10001)

Create a certificate signing request file with the private key we just created: wangcs.csr, note that you need to be sure to specify the user name and group in the -subj parameter (CN for user name and O for group) :

[root@k8s-master k8s-rbac]# openssl req -new -key wangcs.key -out wangcs.csr -subj "/CN=wangcs/O=imonkey"

Then find the CA certificate of our Kubernetes cluster, we are using the Kubeadm installed cluster, the CA certificate is located in /etc/kubernetes/pki/ directory, We will use the two files below the directory, ca. CRT and ca.key, to approve the above certificate request. Generate the final certificate file. Here we set the validity of the certificate to be 100 days:

[root@k8s-master k8s-rbac]# openssl x509 -req -in wangcs.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out wangcs.crt -days 100
Signature ok
subject=/CN=wangcs/O=imonkey
Getting CA Private Key

Now check to see if a certificate file is generated under our current folder:

[root@k8s-master k8s-rbac]# ls
wangcs.crt  wangcs.csr  wangcs.key

Now we can use the newly created certificate file and private key file to create new credentials and contexts in the cluster:

[root@k8s-master]# kubectl config set-credentials wangcs --client-certificate=/root/k8s-rbac/wangcs.crt --client-key=/root/k8s-rbac/wangcs.key
User "wangcs" set.

We can see that a user wangcs is created, and then we can set a new Context for this user. We can specify a namespace for this user:

[root@k8s-master ~]# kubectl config set-context wangcs-context --cluster=kubernetes --namespace=default --user=wangcs
Context "wangcs-context" created.

We have created our user wangcs successfully, and now we should get an error when we use the current configuration file to operate on the kubectl command, because we have not defined any permissions for the user to do anything:

[root@k8s-master ~]# kubectl get pods --context=wangcs-context
Error from server (Forbidden): pods is forbidden: User "wangcs" cannot list resource "pods" in API group "" in the namespace "default"

Create the role

Once the user has been created, it is now necessary to add operational permissions to the user. Let’s define a YAML file to create a role that allows the user to operate Deployment, Pod, and ReplicaSets, as defined below :(wangcs-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: wangcs-role namespace: default rules: - apiGroups: ["", "apps"] resources: ["deployments", "replicasets", "pods"] verbs: [" get ", "a list", "watch", "create", "update", the "patch", "delete"] # can also use [' * ']

Where POD belongs to Core API Group, and NULL characters can be used in YAML, Deployment and Replicaset are now part of the Apps API Group (see the kubectl explain command if you don’t know), Therefore, the API groups under Rules combine the API groups of these resources: [“”, “apps”], where verbs are the operations we mentioned above. We need all the verbs, so we can use [‘*’] instead and create this Role directly:

[root@k8s-master k8s-rbac]# kubectl apply -f wangcs-role.yaml 
role.rbac.authorization.k8s.io/wangcs-role created

Create a role permission binding

Now that the Role is created, it’s clear that our Role has nothing to do with our user wangcs, right? Here we need to create a RoleBinding object that binds the above wangcs-role role to user wangcs under the default namespace: wangcs-RoleBinding. Yaml

apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: wangcs-rolebinding namespace: default subjects: - kind: User name: wangcs apiGroup: "" roleRef: kind: Role name: wangcs-role apiGroup: . Rbac authorization. K8s. IO # blank string can, using the current apiGroup

In the YAML file above we see the subjects field, which is the object we mentioned above to try to manipulate the cluster. For the User account wangcs above, we create the resource object above using kubectl:

[root@k8s-master k8s-rbac]# kubectl apply -f wangcs-rolebinding.yaml 
rolebinding.rbac.authorization.k8s.io/wangcs-rolebinding created

test

We should now be able to manipulate the cluster with the above wangcs-context context:

[root@k8s-master ~]# kubectl get pods --context=wangcs-context
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-75c7f965d8-hnmvn   1/1     Running   0          11d
nginx-deploy-75c7f965d8-xtdv9   1/1     Running   0          11d

We can successfully access the pod object in the default namespace, but what if we add -n kube-system to the end?

[root@k8s-master ~]# kubectl get pods --context=wangcs-context -n kube-system
Error from server (Forbidden): pods is forbidden: User "wangcs" cannot list resource "pods" in API group "" in the namespace "kube-system"

How about getting another resource object:

[root@k8s-master ~]# kubectl get configmaps  --context=wangcs-context
Error from server (Forbidden): configmaps is forbidden: User "wangcs" cannot list resource "configmaps" in API group "" in the namespace "default"

We can see that no permission is obtained because we did not specify access rights to configMap for the current operation user, which is what we expected. This creates a normal User with access to a single namespace.

Only the ServiceAccount of a namespace can be accessed

Above we have created a normal user who can only access a certain namespace. We have also mentioned that there is another type of subject resource under subjects: ServiceAccount. Now let’s create a cluster where users can only operate on pods and deployments under the default namespace. First we’ll create a ServiceAccount object:

[root@k8s-master ~]# kubectl create sa wangcs-sa
serviceaccount/wangcs-sa created

Of course, we can also define the form of YAML file to create:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: wangcs-sa
  namespace: default

Then create a new Role object :(wangcs-sa-role.yaml)

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: wangcs-sa-role
  namespace: default
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch"]

As you can see, the Role we defined here only has query POD and Deployment permissions, so we can focus on testing it later by creating this Role object:

[root@k8s-master k8s-rbac]# kubectl apply -f wangcs-sa-role.yaml
role.rbac.authorization.k8s.io/wangcs-sa-role created

Then create a RoleBinding object that binds the above serviceAccount wangcs-sa to the role wangcs-sa-role :(wangcs-sa-RoleBinding. Yaml)

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: wangcs-sa-rolebinding
  namespace: default
subjects:
- kind: ServiceAccount
  name: wangcs-sa
  namespace: default
roleRef:
  kind: Role
  name: wangcs-sa-role
  apiGroup: rbac.authorization.k8s.io

Add this resource object:

[root@k8s-master k8s-rbac]# kubectl apply -f wangcs-sa-rolebinding.yaml 
rolebinding.rbac.authorization.k8s.io/wangcs-sa-rolebinding created

test

ServiceAccount wangcs-sa is the corresponding token of secret

[root@k8s-master ~]# kubectl get secret wangcs-sa-token-b6blc -o yaml apiVersion: v1 data: ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRX SmwKY201bGRHVnpNQjRYRFRJeE1EUXdOekV4TkRNek9Wb1hEVE14TURRd05URXhORE16T1Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FT SXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBSlFWCjNmRmVraUdmL3ZDK1JPNFR4SC9QbkRhMmJINi9lRFAzNUc1SXppUnladmpUWWtN eGVyOHIrTWdndCtCN05oc28Ka0ZCVVNCVUhrbVhHZFFBUHRjNTJocVdGRlhtZk10TzBhNzZBTWNCdFZUa2hPZDRxc3NPcy9jUndVcGxYKytteApLcW9FdDc0 eFBhRnJxRzIyeDVEN011Y3lYQmtxQk4vWGRKcThKNU5xTWhHd2EvbjVtbWUxYmRrdGh3UWd1SnZzCkc2THRBZGZhRWdXbWxnUVFUMWZHNkhVV3g0L085aTJS NEhIU1VXMDFmTnUwaGFVekNJcE04VERLMk9DbDJYN04KcWE3QitGZDlZR1krUVdhNWVMZk9nMFJUcTJOb210M1E5WWVGWHJKZDJMOHlpc3VsbjM0ZDNxZjFQ akxtMkdJQwpQS01XenBVaWJxbkpNb0RvdjYwQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURW UjBPQkJZRUZNeFh4azYydHVGSk1iTjNFTW03Q2M1RG5iMExNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFBdW5WUXYvTnhnN2JCYXBiVWRVT2s4UWhkclZk bXFGVUlCWnlQN0FUMlh5eVNlMG8xVwp4dEU3c1NyWlQvZDJUTzJseFRLM0NQRVU2dW9uMDQ1amhyd1N1dGNVa3llMUZVcnF6aWNTa1luZjhnVFdOMmtlCnpU dWJ5OUowcVZFRVErc2cvU2Q1bERVUm9LSHAyVXRLZzdrbVRzT3d3U2ppVnlVZEdmMGcrZ2djUU9iMjFvNVgKYUtoOUtIQUdBVDRvQnlOdTY0STJEaWV0QkRk WWdsL3B5cTgwcCtwVTlLSDJObEZrMERhc01uU2I0eEE1M2U3RApJQVJua0JGOFNuSXR2a3pacFFTVWhXNVpJT2IvdjdOcWZxalhuTE8rdUx4czRPSllXL3V5 TzBpMEkrYUF5RWRYClUyUkMzZjIyUHV1VmNnWmZ6ck5vUzU5dnQwVVlVM1FRcURqMgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== namespace: ZGVmYXVsdA== token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklraDZZMnB4VlhCbk5ubFBVa3AxVVZwblYwbGthMmhOZG14TVpHeHdOa1pGVFdvMVFXUkhjbUpPWldNaWZR LmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXVZ VzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbmRoYm1k amN5MXpZUzEwYjJ0bGJpMWlObUpzWXlJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExtNWhi V1VpT2lKM1lXNW5ZM010YzJFaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNTFhV1FpT2lJ NU9EZ3pPV1kxT0MweE5EZG1MVFEzWm1NdE9HVXlaQzFoTjJRMk1HRmtOakUyWVRNaUxDSnpkV0lpT2lKemVYTjBaVzA2YzJWeWRtbGpaV0ZqWTI5MWJuUTZa R1ZtWVhWc2REcDNZVzVuWTNNdGMyRWlmUS5BRl85T1hWd1pkeGVnckRSYWtXYjFrYWM3YmVlclBNTE03T2IwU3JiN2pPcFl4VzdMQllxNkpqNUE5NWxRQm9Y d3haQ09WLUtsYUZxSDc2RnZBRnFYX2taWE5XdWFkeElIZzhkWmVwWl9HbnJwYXBSeFFZZVlsbGRFR3BRdHZZSXdqLUsxRE9xMEprYnM3TW55dGUtcDE0WWxD WGZrdGp2NnVlaDEtcHZnRWRhbjdlS2xjNldwaFFvNnNRUm8xNmppc1VINkRvYU5FdXIxcGpXWVRHSlpuZ2tmQVU2QkNnV1lkRDd1MmwwZnV5dXh0Z2RyM0V1 cHBmSVc1Wk5DQVBBbVU3SWRFd3JBVWJtWW5jZ3JyeTNaQWsxR1ctbnlpa0tWTmNNa29NTFAxejIwdHlQWUFaUkVHOTdSWkRhd1JQM1NvSXlIZTRxM245V1hh N0QxdjhSM1E= kind: Secret ...

Base64 decryption is performed on the token

echo -n "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklraDZZMnB4VlhCbk5ubFBVa3AxVVZwblYwbGthMmhOZG14TVpHeHdOa1pGVFdvMVFXUkhjbUpPWldNaWZ RLmV5SnBjM01pT2lKcmRXSmxjbTVsZEdWekwzTmxjblpwWTJWaFkyTnZkVzUwSWl3aWEzVmlaWEp1WlhSbGN5NXBieTl6WlhKMmFXTmxZV05qYjNWdWRDOXV ZVzFsYzNCaFkyVWlPaUprWldaaGRXeDBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5elpXTnlaWFF1Ym1GdFpTSTZJbmRoYm1 kamN5MXpZUzEwYjJ0bGJpMWlObUpzWXlJc0ltdDFZbVZ5Ym1WMFpYTXVhVzh2YzJWeWRtbGpaV0ZqWTI5MWJuUXZjMlZ5ZG1salpTMWhZMk52ZFc1MExtNWh iV1VpT2lKM1lXNW5ZM010YzJFaUxDSnJkV0psY201bGRHVnpMbWx2TDNObGNuWnBZMlZoWTJOdmRXNTBMM05sY25acFkyVXRZV05qYjNWdWRDNTFhV1FpT2l JNU9EZ3pPV1kxT0MweE5EZG1MVFEzWm1NdE9HVXlaQzFoTjJRMk1HRmtOakUyWVRNaUxDSnpkV0lpT2lKemVYTjBaVzA2YzJWeWRtbGpaV0ZqWTI5MWJuUTZ aR1ZtWVhWc2REcDNZVzVuWTNNdGMyRWlmUS5BRl85T1hWd1pkeGVnckRSYWtXYjFrYWM3YmVlclBNTE03T2IwU3JiN2pPcFl4VzdMQllxNkpqNUE5NWxRQm9 Yd3haQ09WLUtsYUZxSDc2RnZBRnFYX2taWE5XdWFkeElIZzhkWmVwWl9HbnJwYXBSeFFZZVlsbGRFR3BRdHZZSXdqLUsxRE9xMEprYnM3TW55dGUtcDE0WWx DWGZrdGp2NnVlaDEtcHZnRWRhbjdlS2xjNldwaFFvNnNRUm8xNmppc1VINkRvYU5FdXIxcGpXWVRHSlpuZ2tmQVU2QkNnV1lkRDd1MmwwZnV5dXh0Z2RyM0V 1cHBmSVc1Wk5DQVBBbVU3SWRFd3JBVWJtWW5jZ3JyeTNaQWsxR1ctbnlpa0tWTmNNa29NTFAxejIwdHlQWUFaUkVHOTdSWkRhd1JQM1NvSXlIZTRxM245V1h hN0QxdjhSM1E="|base64 -d eyJhbGciOiJSUzI1NiIsImtpZCI6Ikh6Y2pxVXBnNnlPUkp1UVpnV0lka2hNdmxMZGxwNkZFTWo1QWRHcmJOZWMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3Nlc nZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb 3VudC9zZWNyZXQubmFtZSI6Indhbmdjcy1zYS10b2tlbi1iNmJsYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hb WUiOiJ3YW5nY3Mtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5ODgzOWY1OC0xNDdmLTQ3ZmMtOGUyZ C1hN2Q2MGFkNjE2YTMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDp3YW5nY3Mtc2EifQ.AF_9OXVwZdxegrDRakWb1kac7beerPMLM7 Ob0Srb7jOpYxW7LBYq6Jj5A95lQBoXwxZCOV-KlaFqH76FvAFqX_kZXNWuadxIHg8dZepZ_GnrpapRxQYeYlldEGpQtvYIwj-K1DOq0Jkbs7Mnyte-p14YlC Xfktjv6ueh1-pvgEdan7eKlc6WphQo6sQRo16jisUH6DoaNEur1pjWYTGJZngkfAU6BCgWYdD7u2l0fuyuxtgdr3EuppfIW5ZNCAPAmU7IdEwrAUbmYncgrr y3ZAk1GW-nyikKVNcMkoMLP1z20tyPYAZREG97RZDawRP3SoIyHe4q3n9WXa7D1v8R3Q

Next, use this token to request https://} {apiserver IP apiserver: 6443 / API/v1 / namespaces/default/pods

curl -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikh6Y2pxVXBnNnlPUkp1UVpnV0lka2hNdmxMZGxwNkZFTWo1QWRHcmJOZWMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3Nlc nZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb 3VudC9zZWNyZXQubmFtZSI6Indhbmdjcy1zYS10b2tlbi1iNmJsYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hb WUiOiJ3YW5nY3Mtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5ODgzOWY1OC0xNDdmLTQ3ZmMtOGUyZ C1hN2Q2MGFkNjE2YTMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDp3YW5nY3Mtc2EifQ.AF_9OXVwZdxegrDRakWb1kac7beerPMLM7 Ob0Srb7jOpYxW7LBYq6Jj5A95lQBoXwxZCOV-KlaFqH76FvAFqX_kZXNWuadxIHg8dZepZ_GnrpapRxQYeYlldEGpQtvYIwj-K1DOq0Jkbs7Mnyte-p14YlC Xfktjv6ueh1-pvgEdan7eKlc6WphQo6sQRo16jisUH6DoaNEur1pjWYTGJZngkfAU6BCgWYdD7u2l0fuyuxtgdr3EuppfIW5ZNCAPAmU7IdEwrAUbmYncgrr y3ZAk1GW-nyikKVNcMkoMLP1z20tyPYAZREG97RZDawRP3SoIyHe4q3n9WXa7D1v8R3Q" "Https://172.17.114.33:6443/api/v1/namespaces/default/pods" {" kind ":" PodList ", "apiVersion" : "v1", "metadata" : { "selfLink": "/api/v1/namespaces/default/pods", "resourceVersion": "9141416" }, "items": [ { "metadata": { "name": "nginx-deploy-75c7f965d8-hnmvn", "generateName": "nginx-deploy-75c7f965d8-", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/nginx-deploy-75c7f965d8-hnmvn", "uid": "574ac979-41b8-460f-afaf-d29155911ba3", "resourceVersion": "6786396", "creationTimestamp": "2021-05-10T03:30:07Z", "labels": { "app": "nginx", "pod-template-hash": "75c7f965d8" }, ...

So let’s look at the pod list that has access to the default namespace, as expected Use this token to request https://} {apiserver IP apiserver: 6443 / API/v1 / namespaces/kube – system/pods, access kube – the pod list under the system namespace

[root@k8s-master ~]# curl -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikh6Y2pxVXBnNnlPUkp1UVpnV0lka2hNdmxMZGxwNkZFTWo1QWRHcmJOZWMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3Nlc nZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb 3VudC9zZWNyZXQubmFtZSI6Indhbmdjcy1zYS10b2tlbi1iNmJsYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hb WUiOiJ3YW5nY3Mtc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5ODgzOWY1OC0xNDdmLTQ3ZmMtOGUyZ C1hN2Q2MGFkNjE2YTMiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDp3YW5nY3Mtc2EifQ.AF_9OXVwZdxegrDRakWb1kac7beerPMLM7 Ob0Srb7jOpYxW7LBYq6Jj5A95lQBoXwxZCOV-KlaFqH76FvAFqX_kZXNWuadxIHg8dZepZ_GnrpapRxQYeYlldEGpQtvYIwj-K1DOq0Jkbs7Mnyte-p14YlC Xfktjv6ueh1-pvgEdan7eKlc6WphQo6sQRo16jisUH6DoaNEur1pjWYTGJZngkfAU6BCgWYdD7u2l0fuyuxtgdr3EuppfIW5ZNCAPAmU7IdEwrAUbmYncgrr y3ZAk1GW-nyikKVNcMkoMLP1z20tyPYAZREG97RZDawRP3SoIyHe4q3n9WXa7D1v8R3Q" "Https://172.17.114.33:6443/api/v1/namespaces/kube-system/pods" {" kind ":" Status ", "apiVersion" : "v1", "metadata" : { }, "status": "Failure", "message": "pods is forbidden: User \"system:serviceaccount:default:wangcs-sa\" cannot list resource \"pods\" in API group \"\" in the namespace \"kube-system\"", "reason": "Forbidden", "details": { "kind": "pods" }, "code": 403 }

Return 403 with no permissions, as expected

A serviceAccount that is globally accessible

The wangcs-sa serviceAccount that we just created is bound to a Role. If we create a new serviceAccount, we need its permissions to apply to all namespaces. At this point we need to use the two resource objects ClusterRole and ClusterRolleBinding. Again, first create a new ServiceACount object :(wangcs-sa2.yaml)

apiVersion: v1
kind: ServiceAccount
metadata:
  name: wangcs-sa2
  namespace: default

Create:

[root@k8s-master k8s-rbac]# kubectl apply -f wangcs-sa2.yaml 
serviceaccount/wangcs-sa2 created

Then create a ClusterRolleBinding object (WANGCS-ClusteroleBinding. YAML) :

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: wangcs-sa2-clusterrolebinding
subjects:
- kind: ServiceAccount
  name: wangcs-sa2
  namespace: default
roleRef:
  kind: ClusterRole
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io

As can be seen from above, we did not declare a namespace for this resource object because it is a ClusterRolleBinding resource object that applies to the entire cluster, nor did we create a separate ClusterRole object. Instead, we use the cluster-admin object, which is the ClusterRole object built into the Kubernetes cluster. We can use the Kubectl Get ClusterRole and the Kubectl Get ClusterroleBinding to view some of the built-in cluster roles and clusterrole bindings. The cluster role cluster-admin that we are using here is the cluster role with the highest permissions, so it is generally prudent to use this cluster role.

Create:

kubectl apply -f wangcs-clusterolebinding.yaml Warning: . Rbac authorization. K8s. IO/v1beta1 ClusterRoleBinding is deprecated in v1.17 +, unavailable in v1.22 +; use rbac.authorization.k8s.io/v1 ClusterRoleBinding clusterrolebinding.rbac.authorization.k8s.io/wangcs-sa2-clusterrolebinding created

Testing:

Next, make a request to apiserver using the token of secret corresponding to wangcs-sa2 https://{apiserver IP}:6443/ API /v1/pods

!

[root@k8s-master k8s-rbac]# curl -k -H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ikh6Y2pxVXBnNnlPUkp1UVpnV0lka2hNdmxMZGxwNkZFTWo1QWRHcmJOZWMifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3Nlc nZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb 3VudC9zZWNyZXQubmFtZSI6Indhbmdjcy1zYTItdG9rZW4tdHQ1d2oiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uY W1lIjoid2FuZ2NzLXNhMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjU3ZDU4M2JiLWMwNWUtNDU2NC04Z DQwLTIxOWJlMGM2NzBmMiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0Ondhbmdjcy1zYTIifQ.YIYq33Ww8X8NNwjk_P-4IcV95e7j__ aIv-2EX8AicsB_o2kwbfUvoe1Rgx8mN7MErRul46PgKshGL62C4D9pvZFi7H0BeFnY2CsUbYMIIHlEF_IhhKZLkXIbhgcQa8EzAa4KRkgcfO4ULPezO2EnLp -NPt4RABxaAa0aMbkYKgwL-ILCGKbNBQmrWASNcfgfjCavOZXW_hhyLIy_uO3PsCMP4k_T_Tv3lKOYzd8JnKLp1b1ytLrYBtinGYHgJHQB48XnNi8a-gL8rt P5GuDzOf_cQj43Fdub2yRtcNYgkLt6nAxlqNHV1ENjPxUYpJzqzsE5BWhcZQT6bZuyBlWobA "" https://172.17.114.33:6443/api/v1/pods" | more % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0{ "kind": "PodList", "apiVersion": "v1", "metadata": { "selfLink": "/api/v1/pods", "resourceVersion": "9143830" }, "items": [ { "metadata": { "name": "nginx-deploy-75c7f965d8-hnmvn", "generateName": "nginx-deploy-75c7f965d8-", "namespace": "default", "selfLink": "/api/v1/namespaces/default/pods/nginx-deploy-75c7f965d8-hnmvn", "uid": "574ac979-41b8-460f-afaf-d29155911ba3", "resourceVersion": "6786396", "creationTimestamp": "2021-05-10T03:30:07Z", "labels": { "app": "nginx", "pod-template-hash": "75c7f965d8" }, ...

All the pod lists in the namespace can be queried, as expected