What we are going to do
There are several ways to create a user in Kubernetes, including a client certificate, Serviceaccount, and OpenID Connect.
We’ll focus on how to create a user in Kubernetes using client certificates and ServiceAccount.
Prerequisites
Before you begin you need to have a Kubernetes cluster and the kubectl command-line tool and also you need to know the concept of ClusterRole and ClusterRoleBinding in Kubernetes.
If you do not already have a cluster setup one in killercoda.
We have also tested all the below commands on Kubernetes version v1.29.0.
Client certificate
We will create a user with admin permissions and most importantly we will be able to revoke access to it.
The default admin kubeconfig file has a system:masters group that allows for unrestricted access to the Kubernetes API server without the need for any roles or rolebindings. so if you create a user with this permission It’s hard to revoke the permissions (actually you need to create a new certificate authority for Kubernetes and sign again most of the Kubernetes components and because most of the Kubernetes installers like Kubeadm don’t support CA rotation we can consider it a hard work)
To grant temporary admin access to someone, we can assign them to a designated ClusterRole, such as cluster-admin, and assign its permission by ClusterRoleBinding(Or we can use our costume ClusterRole).
Steps
- Create a private key for the new user
- Now, we will create a certificate signing request (CSR) with the private key
- Now you need to sign the certificate with the Private CA of your Kubernetes certificate (The CertificateSigningRequest does that for us)
- Create a ClusterRoleBinding to assign the cluster-admin ClusterRole permissions to the user
- Generate a new kubeconfig file for the user
openssl genrsa -out test-user.key 2048 # The private key
openssl req -new -key test-user.key -out test-user.csr -subj "/CN=test-user/O=test-admin"
# Sign the CSR with the CA (Certificate authority of Kubernetes) you can also do (`openssl x509 -req -in myuser.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out test-user.crt -days 365`
if you are logged in the one of master nodes)
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: test-user
spec:
request: $(cat test-user.csr | base64 | tr -d "\n")
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
EOF
kubectl certificate approve test-user
kubectl get csr test-user -o "jsonpath={.status.certificate}" | base64 -d > test-user.crt
# Create ClusterRole
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: example-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: test-admin
EOF
# Create Kubeconfig file
kubectl --kubeconfig ~/.kube/config-test-user config set-cluster preprod --insecure-skip-tls-verify=true --server=https://127.0.0.1:6443
kubectl --kubeconfig ~/.kube/config-test-user config set-credentials test-user --client-certificate=test-user.crt --client-key=test-user.key --embed-certs=true
kubectl --kubeconfig ~/.kube/config-test-user config set-context default --cluster=preprod --user=test-user
kubectl --kubeconfig ~/.kube/config-test-user config use-context default
# Check the Permissions
kubectl get nodes --kubeconfig ~/.kube/config-test-user
Remove the permission of the user
By changing cluster-admin ClusterRole we can change the permission of the user, or by deleting the example-cluster-admin ClusterRoleBinding we can disable all the permissions we have given to the user.
Service Account
Now let’s create a user with a ServiceAccount
- Create ServiceAccount
kubectl create sa test-user
- In Kubernetes 1.24, ServiceAccount token secrets are no longer automatically generated. so we need to create a secret manually
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: test-user
name: test-user
type: kubernetes.io/service-account-token
EOF
- Then give it permission, We will give it the cluster-admin ClusterRole that has been created automatically by Kubernetes
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: example-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: test-user
namespace: default
EOF
- Now generate a kubeconfig file for the user
TOKEN=$(kubectl get secret test-user -o jsonpath='{.data.token}' | base64 -d )
kubectl --kubeconfig ~/.kube/config-test-user config set-cluster kubernetes --insecure-skip-tls-verify=true --server=https://127.0.0.1:6443 # If you want not to use insecure-skip-tls-verify you need to add CA certificate of kubernetes in the config
kubectl --kubeconfig ~/.kube/config-test-user config set-credentials test-user --client-certificate=test-user.crt --client-key=test-user.key --embed-certs=true
kubectl --kubeconfig ~/.kube/config-test-user config set-context default --cluster=kubernetes --user=test-user --username=test-user
kubectl --kubeconfig ~/.kube/config-test-user config use-context default
kubectl --kubeconfig ~/.kube/config-test-user config set-credentials test-user --token $TOKEN
# Check the Permissions
kubectl get nodes --kubeconfig ~/.kube/config-test-user