A Practical Approach to Understanding Kubernetes Authentication

In a production environment, Kubernetes administrators use namespaces to isolate resources and deployments. Namespaces act as a logical boundary to enforce basic access control.
Let’s say we have Bob, new admin that joined the DevOps team to manage the Kubernetes deployments for the engineering group. We now have to provide him with just enough access to manage the engineering namespace. Assuming you are the cluster administrator with permissions to manage global resources and objects, you would onboard Bob and help him with the credentials needed to access Kubernetes cluster.
This scenario is based on Minikube but it should work with any other configuration where you are the cluster administrator.
Create a directory called cred and run the below commands to generate a private key for Bob.
1 2 |
mkdir cred cd cred |
1 2 3 4 5 |
openssl genrsa -out bob.key 2048 Generating RSA private key, 2048 bit long modulus ..................................................................................................................+++ ................................................+++ e is 65537 (0x10001) |
We also need a Certificate Signing Request which can be generated from the key.
1 |
openssl req -new -key bob.key -out bob.csr -subj "/CN=bob/O=eng"\n |
Move the key to the parent folder and encode that in Base64.
1 2 3 4 |
cp bob.key .. cd .. cat cred/bob.csr | base64 | tr -d '\n' LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1lqQ0NBVW9DQVFBd0hURU1NQW9HQTFVRUF3d0RZbTlpTVEwd0N3WURWUVFLREFSbGJtZHVNSUlCSWpBTgpCZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEzSU9oUTArMFJUakpqZjBKTkd2Rmo0YWFlN1hYCkkrZWkzTzZWTEpqMHNKNDBvengyUTVndXBmeFc5b0lEYTJETnhVZjZkNHVMOUJ3V2lhdFdQdnBDNm80MHJQc2EKTjBUdEhEekFYeWppc0E5VXVRMVNKMWg5Mkg0TU9XWEpWNWJWaTlXYjBKU3hLbXVrSUVtaERJcW9TcEh6MU5xaApQMWNXOFFpNXpoVVBmWlpnOUhSaWVUQ2xEMmR3bWRtS1JjbU9uenNGVWhJWmZWanVZNzZJUm9KbksyaHNzVjZoCmMyY1JNTVNEdFA0ZDArYkxOY1BKdExpS3JjQkdwUGxLUEdrSHovM2NNbVhpVi8wY2xqUlppMzJCb3B4NlI1NUIKc0Z6cXZwcWgzNWxLNUVOUGxPZy9sdURFdllGeUtzOUY2aERBRFhDNzQxU0ZCQTI0TERzcTFiWWtVUUlEQVFBQgpvQUF3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUxTejgxL2N3bjQxbVRrUDhabWhhUUx3MkpIRkN4ZUlaOFdpCkZOV0U1cnRVd3hrSjJGWVJKRlFUL1hJN0FoL0pXTkhqeHlhOUNyN3c0OThmanN3bDF2ZzQ1QUgrR29DeVEwTWkKOU1MMHl0WmZyaG5jYmtpRG9oSUpuaWhJTjlCUGpHVkw2SG1USytGc0sybG1ZZ1JDdk9Cclg3Rkh6ZjgwM0ZFNAp4ZkgrZlFsdGxDdEZTSEhuaUlzZTFEQ2J4cFVTdnRISXpYMFcyb2hXV3RPVkRpOTAzOW8zY2VaWmdVK3VRYno0Cmp2djJoeVdRNDhORFl3RWF1UUU2S3NBQTFLT0IyUkI2dE45bjFTVWoxU1B2WnBsQkVieDZ5MTkzaUJSVFJRM2wKM2JhdFRNUUEzelBsdk01ZEE2Vy8rQWcwVm0xMk1SR091VFRLSEU2bE5INE1DbHQvRGZZPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K |
We need to embed the generated base64-encoded string in a YAML file and submit that to Kubernetes as a Certificate Signing Request. This step will essentially associate Bob’s private key with Kubernetes cluster.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
apiVersion: certificates.k8s.io/v1beta1 kind: CertificateSigningRequest metadata: name: bob-csr spec: groups: - system:authenticated request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1lqQ0NBVW9DQVFBd0hURU1NQW9HQTFVRUF3d0RZbTlpTVEwd0N3WURWUVFLREFSbGJtZHVNSUlCSWpBTgpCZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUEzSU9oUTArMFJUakpqZjBKTkd2Rmo0YWFlN1hYCkkrZWkzTzZWTEpqMHNKNDBvengyUTVndXBmeFc5b0lEYTJETnhVZjZkNHVMOUJ3V2lhdFdQdnBDNm80MHJQc2EKTjBUdEhEekFYeWppc0E5VXVRMVNKMWg5Mkg0TU9XWEpWNWJWaTlXYjBKU3hLbXVrSUVtaERJcW9TcEh6MU5xaApQMWNXOFFpNXpoVVBmWlpnOUhSaWVUQ2xEMmR3bWRtS1JjbU9uenNGVWhJWmZWanVZNzZJUm9KbksyaHNzVjZoCmMyY1JNTVNEdFA0ZDArYkxOY1BKdExpS3JjQkdwUGxLUEdrSHovM2NNbVhpVi8wY2xqUlppMzJCb3B4NlI1NUIKc0Z6cXZwcWgzNWxLNUVOUGxPZy9sdURFdllGeUtzOUY2aERBRFhDNzQxU0ZCQTI0TERzcTFiWWtVUUlEQVFBQgpvQUF3RFFZSktvWklodmNOQVFFTEJRQURnZ0VCQUxTejgxL2N3bjQxbVRrUDhabWhhUUx3MkpIRkN4ZUlaOFdpCkZOV0U1cnRVd3hrSjJGWVJKRlFUL1hJN0FoL0pXTkhqeHlhOUNyN3c0OThmanN3bDF2ZzQ1QUgrR29DeVEwTWkKOU1MMHl0WmZyaG5jYmtpRG9oSUpuaWhJTjlCUGpHVkw2SG1USytGc0sybG1ZZ1JDdk9Cclg3Rkh6ZjgwM0ZFNAp4ZkgrZlFsdGxDdEZTSEhuaUlzZTFEQ2J4cFVTdnRISXpYMFcyb2hXV3RPVkRpOTAzOW8zY2VaWmdVK3VRYno0Cmp2djJoeVdRNDhORFl3RWF1UUU2S3NBQTFLT0IyUkI2dE45bjFTVWoxU1B2WnBsQkVieDZ5MTkzaUJSVFJRM2wKM2JhdFRNUUEzelBsdk01ZEE2Vy8rQWcwVm0xMk1SR091VFRLSEU2bE5INE1DbHQvRGZZPQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K usages: - digital signature - key encipherment - server auth |
1 2 |
kubectl create -f signing-request.yaml certificatesigningrequest.certificates.k8s.io/bob-csr created |
Verify the CSR with the below kubectl command:
1 2 3 |
kubectl get csr NAME AGE REQUESTOR CONDITION bob-csr 41s minikube-user Pending |
Notice that the request is still pending. The cluster admin has to approve it before it becomes active.
1 2 |
kubectl certificate approve bob-csr certificatesigningrequest.certificates.k8s.io/bob-csr approved |
1 2 3 |
kubectl get csr NAME AGE REQUESTOR CONDITION bob-csr 104s minikube-user Approved,Issued |
Now that the certificated has been approved and issued, we need to get the signed certificate from the cluster. This is the most critical step in onboarding Bob.
1 |
kubectl get csr bob-csr -o jsonpath='{.status.certificate}' | base64 --decode > bob.crt |
The file, bob.crt is the client certificate that’s used to authenticate Bob. We now have the combination of the private key (bob.key) and the approved certificate (bob.crt) from Kubernetes. As long as Bob has these two assets, he can get authenticated with the cluster.
It’s time to add Bob as a user to Kubernetes.
1 2 |
kubectl config set-credentials bob --client-certificate=bob.crt --client-key=bob.key User "bob" set. |
Open ~/.kube/config file to verify that the credentials are set.
Let’s also create a new namespace called engineering for which Bob is the administrator.
1 2 |
kubectl create namespace engineering namespace/engineering created |
1 2 3 4 5 6 7 |
kubectl get namespace NAME STATUS AGE default Active 37m engineering Active 0s kube-node-lease Active 37m kube-public Active 37m kube-system Active 37m |
The kubectl CLI has a very useful switch in the form of auth which can verify the permissions for a specific user. Let’s check if the current user who is the admin has access to the engineering namespace. Given that you are the cluster admin, it’s not surprising to see the output.
1 2 |
kubectl auth can-i list pods --namespace engineering yes |
We can also check if Bob has got access to the engineering namespace.
1 2 |
kubectl auth can-i list pods --namespace engineering --as bob no |
It’s obvious that Bob doesn’t have access to the namespace. That’s because we have created the credentials but not explicitly authorized Bob for any specific action on any object.
In the next part of this tutorial series, I will walk you through the steps involved in authorizing Bob. It would also give us an opportunity to learn about roles and role bindings. Stay tuned!
Janakiram MSV’s Webinar series, “Machine Intelligence and Modern Infrastructure (MI2)” offers informative and insightful sessions covering cutting-edge technologies. Sign up for the upcoming MI2 webinar at http://mi2.live.