RBAC Authority Management Practice
This article mainly introduces a case of authorization decision based on Kubernetes RBAC, which allows cluster administrators to dynamically configure policies through Kubernetes API, grants non-cluster administrators all permissions under a certain namespace, and manages the resources under this namespace by Dashboard or kubectl.
For a deeper understanding and mastery of RBAC, you can refer to the official documentation (opens in a new tab).
In K8S, there are two types of users,
- Service Account, an account for non-human users in Kubernetes, provides different identity indications in the Kubernetes cluster. For more details, refer to this official documentation (opens in a new tab)
- Ordinary users(user), K8S itself does not manage users, but is managed by external independent services and cannot create users through the K8SAPI;
Currently, the management of the cluster is through kubectl and Dashboard. The Service account is sufficient to meet the requirements and can be managed directly in Kubernetes. Therefore, this article does not introduce how to manage the cluster using the user object.
1. Create Namespace
kubectl create ns pre
The above example creates a namespace named "pre" for deploying pre-release services.
2. Create Service Account
kubectl create sa mingpianwang -n pre
Create a Service account named "mingpianwang" under the namespace 'pre' for a specific user.
3. Grant Permissions
We said in advance that we need to grant all permissions under the 'pre' namespace to the user 'mingpianwang', that is, admin permissions.
Here comes the crucial part, the RoleBinding (opens in a new tab) object can reference a ClusterRole object. Still, the permissions owned by this ClusterRole will only be valid under this NS. This allows administrators to define a set of universal roles for the entire cluster and then reuse these roles in different namespaces.
Let's first see what default ClusterRoles are in the cluster by executing the get clusterrole command. There are roles like admin, cluster-admin, edit. So, we can directly use the admin clusterrole and grant it to the user "mingpianwang" through rolebinding.
[root@10-9-149-7 ~]# kubectl get clusterrole
NAME AGE
admin 4h53m
cluster-admin 4h53m
edit 4h53m
Here's a yaml example. We just need to execute kubectl apply -f rolebinding.yaml
.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: pre
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: admin
subjects:
- kind: ServiceAccount
name: mingpianwang
namespace: pre
Of course, we can also create a namespace-level role and bind this role to ServiceAccount.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: pre
name: admin
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["*"]
verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: pre
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: admin
subjects:
- kind: ServiceAccount
name: mingpianwang
namespace: pre
This role will not be reusable in other namespaces. Usually, we only create Role objects when doing fine-grained permission management, such as a Role that can only view the pod named test-pod. In other scenarios, cluster administrators are recommended to use ClusterRole.
4. Access Dashboard
In versions prior to Kubernetes 1.22, Kubernetes would provide a long-term valid static token for ServiceAccounts in the form of Secret. In Kubernetes v1.22 and higher versions, users need to set it up themselves; for details, refer to the official document Manually Obtaining ServiceAccount Credentials (opens in a new tab)
Versions prior to Kubernetes 1.22
You should get the token of "mingpianwang", which is the secret. You can get it through the following way, and copy the final token.
bash-4.4# kubectl describe sa/mingpianwang -n pre
Name: mingpianwang
Namespace: pre
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: mingpianwang-token-4l8xj
Tokens: mingpianwang-token-4l8xj
Events: <none>
bash-4.4# kubectl describe secret/mingpianwang-token-4l8xj -n pre
Name: mingpianwang-token-4l8xj
Namespace: pre
Labels: <none>
Annotations: kubernetes.io/service-account.name: mingpianwang
kubernetes.io/service-account.uid: d7bb847d-7621-11e9-9679-5254007e7ba9
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1359 bytes
namespace: 5 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9/....
Versions after Kubernetes 1.22
If you need to get an API token for a ServiceAccount, you can create a new Secret object with a special annotation kubernetes.io/service-account.name. For more details, refer to the official documentation Manually Obtaining a Long-Lived Token (opens in a new tab)
bash-4.4# kubectl -n pre apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: mingpianwang-secret
annotations:
kubernetes.io/service-account.name: mingpianwang
type: kubernetes.io/service-account-token
EOF
You can check Secret with the following command:
bash-4.4# kubectl -n pre describe secrets/mingpianwang-secret
Name: mingpianwang-secret
Namespace: pre
Labels: <none>
Annotations: kubernetes.io/service-account.name: mingpianwang
kubernetes.io/service-account.uid: 0c3e9a16-6962-45ee-9e6e-e7f0107cd9a8
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1359 bytes
namespace: 3 bytes
token: ...
Token content is blurred here. When you delete a ServiceAccount associated with a Secret, Kubernetes control plane automatically cleans up long-term valid tokens in the Secret.
You can view ServiceAccount with the following command:
kubectl -n pre get serviceaccount mingpianwang -o yaml
You will not see the 'mingpianwang-secret' Secret in the ServiceAccount API object. Because this field only fills automatically generated Secrets.
Log in to the Dashboard
Copy to login box, we find that we can log in to the Dashboard homepage. However, please note, since this account only has permissions for the 'pre' namespace, and the Dashboard default is default, a bunch of errors will be reported after entering, don't worry, just change the NS on the left to pre.
5. Manage Cluster Through kubectl
Since we still need to support the kubectl command line management NS, we also need to generate kubeconfig for 'mingpianwang'. It's okay for one user, but it's troublesome for multiple users. So here we use a script to automatically generate kubeconfig. The code is as follows:
#!/bin/bash -e
# Usage ./k8s-service-account-kubeconfig.sh ( namespace ) ( service account name )
TEMPDIR=$( mktemp -d )
trap "{ rm -rf $TEMPDIR ; exit 255; }" EXIT
SA_SECRET=$( kubectl get sa -n $1 $2 -o jsonpath='{.secrets[0].name}' )
# Pull the bearer token and cluster CA from the service account secret.
BEARER_TOKEN=$( kubectl get secrets -n $1 $SA_SECRET -o jsonpath='{.data.token}' | base64 -d )
kubectl get secrets -n $1 $SA_SECRET -o jsonpath='{.data.ca\.crt}' | base64 -d > $TEMPDIR/ca.crt
CLUSTER_URL=$( kubectl config view -o jsonpath='{.clusters[0].cluster.server}' )
KUBECONFIG=kubeconfig
kubectl config --kubeconfig=$KUBECONFIG \
set-cluster \
$CLUSTER_URL \
--server=$CLUSTER_URL \
--certificate-authority=$TEMPDIR/ca.crt \
--embed-certs=true
kubectl config --kubeconfig=$KUBECONFIG \
set-credentials $2 --token=$BEARER_TOKEN
kubectl config --kubeconfig=$KUBECONFIG \
set-context registry \
--cluster=$CLUSTER_URL \
--user=$2 \
--namespace=$1
kubectl config --kubeconfig=$KUBECONFIG \
use-context registry
echo "kubeconfig written to file \"$KUBECONFIG\""
Directly execute sh kubeconfig.sh pre mingpianwang
on the master node, you can automatically generate a kubeconfig file, distribute this kubeconfig file to the user, let him copy to '~/.kube/config', and the default NS is 'pre', operations like get nodes are not allowed.
The source code to generate kubeconfig is here, generator kubeconfig (opens in a new tab). We only added a default NS so that there is no need to append -n pre when executing the kubectl command.