Notes for: TGIK 004: RBAC

How to do Authentication and Authorization for k8s.

The kubeconfig file:

- cluster:
        <This is the root CA that I am going to trust since its a TLS connection to the server>
    server: <URL>
  name: <c-name>

With this you could connect (hitting) but you cannot Authenticate to the server, you need:

- name: admin
    client-certificate-data: <>
    client-key-data: <>

The client-key-data is basically the password.

Then the context maps a cluster with a user:

- context:
    cluster: gke_continuum-compute_us-central1-a_daniel-ml
    user: gke_continuum-compute_us-central1-a_daniel-ml
  name: gke_continuum-compute_us-central1-a_daniel-ml

Recommendation: Use a single file per cluster. You can tell kubectl which file to use with KUBECONFIG

How certificates work

You create one public and one private key. You never share the private key and leave it at one place all the time. To enable trust you make the public key public, saying "I want someone to identify me this way".

You sign something with a public key and that becomes a CSR (Certificate Signing Request). You hand the CSR to the server, the server says "i know this is you" (via some out of band mechanism) and is able to trust that and stamp and you get a Signed Certificate.

When you present the Signed Certificate to somebody and if you have the Private Key you can prove that you are who you say you are.


a.k.a Who is this?

The idea of who you are in a k8s cluster is very flexible so it can be integrated with a lot of stuff but it also can be confusing.

The full list of methods to authenticate to k8s can be found here:

For example for using x509 certificates you can add users by adding k8s CSR like:

kind: CertificateSigningRequest
  name: user-request-jakub
  - system:authenticated
  request: <>
  - digital signature
  - key encipherment
  - client auth

And running:

kubectl create -f ...
kubectl certificate approve user-request-jakub
kubectl get csr user-request-jakub -o jsonpath='{.status.certificate}' | base64 -d > jakub.crt

Now we can modify the k8s config file and use the generated key and CSR to login

kubectl config set-credentials jakub --client-certificate=jakub.crt --client-key=jakub.pem --embed-certs=true

What happens when we try to do something?

kubectl get pods

> Error from server (Forbidden): User "jakub" cannot list pods in the namespace "default". (get pods)

We can hit the server but we cannot do any action until we create some roles.


a.k.a What can you do?

There is a plugin model in k8s: There is an interface and a couple of implementations and you can change which one to use with some CLI flags. Docs:

Role Base Access Control (RBAC) is the new one.

There is 4 things you have to think about in RBAC:

  1. Role and ClusterRole
  2. RoleBinding and ClusterRoleBinding

How this work together make more sense when you understand how namespaces work in k8s.

  • When we create a k8s object we make a decision on whether this live under a namespace or not. Pods/Service do live under a namespace. Some (CRS, Nodes) do not live under a namespace since are cluster wide settings resources are one that are not namespaced.
  • Roles are namespaced - ClusterRole are cluster wide resources
  • RolesBinding are namespaced - ClusterRoleBinding are cluster wide
  • So the actions you can do with Role and ClusterRole are basically the same but one is namespaced and one is not. Same for the RoleBinding types. The question is: Do I want this permission to be in the whole cluster or just in one namespace?

Role / ClusterRole

- apiGrous:
    - selfsubjectaccessreviews
    - create

This is saying that we can create objects of The way we identify objects is by apiGroups ( that segment the API surface area of k8s and the resource type (selfsubjectaccessreviews), you could also narrow it down to an specific resource but its usually not the case.

RoleBinding / ClusterRoleBinding

This grant permission of an existing role to a group of users.

  kind: ClusterRole
  name: admin
- apiGroup:
  kind: User
  name: users:joe

This is saying: Let the ClusterRole named admin (that has its own permissions) and apply it to the User users:joe.