\ /
kubernetes 

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.

comments powered by Disqus