Adding a full admin user in Kubernetes
I built my cluster, now I wanted to make a new user with full privileges.
I built my cluster, now I wanted to make a new user with full privileges.
I'm building a brand new, bare bones, raw, Kubernetes cluster. I used kubeadm
and built up a cluster with 3 control planes and 2 worker nodes. Now I want to add a new user with full privileges. This is primarily for the "can I do it" and how thought. But, it's more secure to have separate certs for each user anyways so it all applies in the real world.
A little background and few key facts.
- My cluster is Kubernetes 1.20
- I'm using basic certificate authentication with RBAC which is the default cluster configuration.
- There is a
system:masters
group that has full permissions to the cluster. - The
system:masters
group is tied to aClusterRoleBinding
namedcluster-admins
. - A default
kubeadm
cluster won't let you add a user that has thesystem:masters
group. - Groups are assigned in the organization part of the subject name of the certificate.
- Our users name is going to be named
test
so replacetest
with the appropriate user. I'll have scripts and other stuff at the end. - My new group name is
example:masters
Solution:
- Create a new role binding.
- Create a new user.
- Set the values in a new config.
Create the ClusterRoleBinding
- Create the
ClusterRoleBinding
yaml fileexample-cluster-admin.yaml
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: example:masters
- Apply the
ClusterRoleBinding
kubectl apply -f example-cluster-admin.yaml
Create a new user
- Create a certificate key using openssl.
openssl genrsa -out test.key 4096
- Create a signing request.
openssl req -new -key ${USERNAME}.key -out ${USERNAME}.csr -subj "/CN=${USERNAME}/O=example:masters"
- Get the base 64 encoded signing request.
cat test.csr | base64 | tr -d '\n'
- Create the CertificateSigningRequest yaml file test.yaml to add to the cluster
apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: test-csr spec: groups: - system:authenticated request: BASE64ENCODEDCSRFROMSTEP3 signerName: kubernetes.io/kube-apiserver-client usages: - digital signature - key encipherment - client auth
- Apply the CSR yaml file.
kubectl apply -f test.yaml
- Approve the signing request
kubectl certificate approve ${USERNAME}-csr
- Get the certificates for the config file
KEY=`cat ${USERNAME}.key | base64 | tr -d '\n'` CERT=`kubectl get csr ${USERNAME}-csr -o jsonpath='{.status.certificate}'` echo "======KEY" echo ${KEY} echo echo "======Cert" echo $CERT echo
Update the local Kubernetes config file
Open up the ~/.kube/config
file and change out the client-certificate-data
with the value of the Cert
and client-key-data
with the value of the Key
that we got in the last step of the user creation process.
Scripts and other useful stuff
create-user.sh
- Creates and approves (if the current user can) a new user and dumps out a working config that can be given to someone
#!/bin/bash
USERNAME=${1}
echo + Creating private key: ${USERNAME}.key
openssl genrsa -out ${USERNAME}.key 4096
echo + Creating signing request: ${USERNAME}.csr
openssl req -new -key ${USERNAME}.key -out ${USERNAME}.csr -subj "/CN=${USERNAME}/O=example:masters"
cp signing-request-template.yaml ${USERNAME}-signing-request.yaml
sed -i "s@__USERNAME__@${USERNAME}@" ${USERNAME}-signing-request.yaml
B64=`cat ${USERNAME}.csr | base64 | tr -d '\n'`
sed -i "s@__CSRREQUEST__@${B64}@" ${USERNAME}-signing-request.yaml
echo + Creating signing request in kubernetes
kubectl create -f ${USERNAME}-signing-request.yaml
echo + List of signing requests
kubectl get csr
kubectl certificate approve ${USERNAME}-csr
KEY=`cat ${USERNAME}.key | base64 | tr -d '\n'`
CERT=`kubectl get csr ${USERNAME}-csr -o jsonpath='{.status.certificate}'`
echo "======KEY"
echo ${KEY}
echo
echo "======Cert"
echo $CERT
echo
echo "======Config"
cat ~/.kube/config | \
sed -r "s/^(\s*)(client-certificate-data:.*$)/\1client-certificate-data: ${CERT}/" | \
sed -r "s/^(\s*)(client-key-data:.*$)/\1client-key-data: ${KEY}/"
echo
signing-request-template.yaml
- used by the above script to generate the CertificateSigningRequest
object in Kubernetes
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: __USERNAME__-csr
spec:
groups:
- system:authenticated
- example:masters
request: __CSRREQUEST__
signerName: kubernetes.io/kube-apiserver-client
usages:
- digital signature
- key encipherment
- client auth
Conclusion
Doing this was annoying, but not as annoying as disabling the admission controller that was blocking the ability to add users to the system:masters
group.
My brother helped out a lot with the initial user creation part.
I don't generally apply manifests using kubectl
by hand, instead I'll either use a script to do it or use ArgoCD
and store my manifests in a git repo. Which is exactly what I did for my ClusterRoleBinding
.
Links
My brothers site
Kubernetes docs




