Authorization of developers working on a Kubernetes cluster

Authorization of developers working on a Kubernetes cluster

When a lot of developers need to work on your Kubernetes cluster, we need a way to:

  1. identify a single developer
  2. grant proper permissions to each of them (as a group or as a single user)
  3. remove/modify grants

In Kubernetes a developer can interact with the API using self-generated certificates, provided that they're signed by the cluster authority certificate. Using certificates we can rely on Kubernetes' built-in mechanisms (RBAC) to fulfill our three requirements.

The following image shows the process involving every single developer and the Kubernetes cluster administrator.

K8S_credentials_1.png

Step 1: as developer

  • Create private key for user:

openssl genrsa -out nicola.key 2048

  • Create certificate signing request (CSR):

openssl req -new -key nicola.key -out nicola.csr -subj "/CN=nbenaglia@sorint.it/O=devs/O=archs"

Common Name (CN) will be treated by Kubernetes as User

Organization (O) will be treated by Kubernetes as Group (in the above command the developer belongs to two groups)

  • Send the CSR to the administrator

Step 2: as K8S admin

  • Check the content and the declared groups with the command:

openssl req -new -key nicola.key -out nicola.csr -subj "/CN=nbenaglia@sorint.it/O=devs/O=archs"

The output will be similar to:

Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: CN = nbenaglia@sorint.it, O = devs, O = archs
        Subject Public Key Info: [...]
  • Download the cluster authority certificate (on your master in /etc/kubernetes/pki/ca.crt), which is a public distributable certificate. You can see its content with the following:

openssl x509 -in ca.crt -noout -text

  • Create certificate from CSR using the cluster authority and set certificate expiration:

openssl x509 -req -in nicola.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out nicola.crt -days 500

  • Send ca.crt and nicola.crt to developer

  • Grant the User or the Group in RoleBinding or ClusterRoleBinding.

Take the following file role.yml as example for a role in a namespace devs:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: devs
  name: devs-reader
rules:
- apiGroups: [""]
  verbs: ["get", "list"]
  resources: ["pods","services"]
```	

`kubectl create -f role.yml`

Group binding:

`kubectl create rolebinding devs-rb -n devs --group devs --role devs-reader`

User binding:

`kubectl create rolebinding devs-reader-nbenaglia -n devs --user nbenaglia@sorint.it --role devs-reader`



###  Step 3: as developer

* Add the new cluster to kubectl config:

`kubectl config set-cluster devs-cluster --certificate-authority=ca.crt --embed-certs=true --server=https://PUBLIC_ADDRESS_OF_CLUSTER:6443`

The PUBLIC_ADDRESS_OF_CLUSTER is provided by the k8s admin. 

* Add the new credentials to kubectl config:

`kubectl config set-credentials nicola --client-certificate=nicola.crt --client-key=nicola.key --embed-certs=true`

* Add the new context to kubectl config:

`kubectl config set-context dev-nicola --cluster=devs-cluster --user=nicola`

* Check the config:

`kubectl config view`

* Set the context:

`kubectl config use-context dev-nicola`


### Pros and cons
We could set fine-graned permissions for each developer to work on our kubernetes cluster.
The above described process, like every solution, has pros and cons:

**Pros**
1. Fine-grained permissions to a single developer or group 
2. Developer self-generates his private key and CSR 
                
**Cons**
1. Belonging organizations (K8S groups) must be carefully designed before CSR generation
2. Admin cannot revoke a single user from a group binding (*thanks* to Maxim Filatov for the note)
3. Admin must check the developer self-generated certificate 
4. Generation and distribution of a certificate for each developer 
5. When Kubernetes CA expires, we need to regenerate and redistribute all certificates 


### Conclusion
Embedding Organization units (O) inside the certificate may lead to a overhead for the K8S administrator, because every change inside the organization requires a new certificate.

So in my opinion it's better to use only Common Name (CN) during the CSR:

`openssl req -new -key nicola.key -out nicola.csr -subj "/CN=nbenaglia@sorint.it"`

and manage roles using Kubernetes' RoleBindings and ClusterRoleBindings.

The described flow can be further simplified by using the Kubernetes' `CertificateSigningRequest` object. We'll see that in another post.

Simplicity is a better approach.

Related Posts

Azure Kubernetes Service - Apache Superset deployment

Azure Kubernetes Service - Apache Superset deployment

Apache Superset deployment in Azure Kubernetes Service

KubeCon + CloudNativeCon 2024 Day Four

KubeCon + CloudNativeCon 2024 Day Four

Past and the future of Kubernetes

KubeCon + CloudNativeCon 2024 Day Three

KubeCon + CloudNativeCon 2024 Day Three

Sustainable Computing

KubeCon + CloudNativeCon 2024 Day Two

KubeCon + CloudNativeCon 2024 Day Two

Powering the AI

KubeCon + CloudNativeCon 2024 Day One

KubeCon + CloudNativeCon 2024 Day One

Events everywhere

Best of Modern Application Infrastructure in 2023

Best of Modern Application Infrastructure in 2023

From Be Part of IT Magazine 2023

The Experience of a Technological Transition

The Experience of a Technological Transition

Case Study

CASE STUDY - Extension of Containerization Project

CASE STUDY - Extension of Containerization Project

GitOps and DevOps