Sunday, May 12, 2019

Kubernetes RBAC

Role based access control (RBAC) is an important part of any multi user or multi tenant system, and kubernetes is no different. Once you get things out of the lab and into the real world you'll need an ability to control portions of the system, so this guide is meant to create a couple of the basics; a global administrator and a namespace specific administrator. There are two key elements to achieving this:
  • Role - Connects a resource or set of resources, the item, to verbs, or operations that can be performed against those items
  • RoleBinding - Connects subjects, either a user, group, or service account to a role

Identifying A User

Kubernetes doesn't actually handle user identity. The options can be long and confusing, but kubernetes relies on external mechanisms to do this such as certificates, tokens, OAuth2, or others (https://kubernetes.io/docs/reference/access-authn-authz/authentication/). Hopefully, better, free tools will start to emerge to manage this ecosystem over time, but for now we'll be using certificate based authentication. Doing this can be a little complicated at first, but basically what's happening here is we're generating a certificate signing request and signing it with the cluster's root certificate. The user is identified with the common name (CN) and the group is identified using the organization (O). The process looks like this:
[root@k8s-master ~]# openssl genrsa -out mengland.key 2048
Generating RSA private key, 2048 bit long modulus
...+++
...................................+++
e is 65537 (0x10001)
[root@k8s-master ~]# openssl req -new -key mengland.key -out mengland.csr -subj "/CN=mengland/O=cluster-admins"
[root@k8s-master ~]# openssl x509 -req -in mengland.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out mengland.crt -days 730
Signature ok
subject=/CN=mengland/O=cluster-admins
Getting CA Private Key
The above will create a certificate valid for two years to the user mengland who belongs to the group cluster-admins. We can then distribute these keys to the user which they can add to their kubernetes client configuration. Two files should have been created which need to be transferred to the client, in this case, mengland.crt and mengland.key.

The last thing we'll need is the certificate for the cluster itself. There are a couple ways you can do this. I prefer keeping the certificate within kubectl conf file as it's done by default when you install a new cluster, but you can also reference a file which will be covered in a future blog post. The file is located as /etc/kubernetes/pki/ca.crt.

Global Admin Role

Because I want my user to be a global admin, I'll be using a ClusterRole and ClusterRoleBinding rather than just a role and role binding. My two yaml files will look like this and be applied to the cluster:
[root@k8s-master ~]# cat global-admin.yaml 
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: global-admin
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
[root@k8s-master ~]# cat global-admin-binding.yaml 
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: global-admin-binding
subjects:
- kind: User
  name: mengland
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: global-admin
  apiGroup: rbac.authorization.k8s.io
[root@k8s-master ~]# kubectl create -f global-admin.yaml
[root@k8s-master ~]# kubectl create -f global-admin-binding.yaml
If you wanted multiple users in the global admin role, you'd modify the global-admin-binding.yaml file with multiple -kind: User subjects and apply the changes with kubectl apply -f global-admin-binding.yaml. A lot of examples have the apiGroups set to [""] which indicates the core API group but this doesn't give the user access to the whole cluster.

Namespace Admin Role

Creating a role and binding giving users access to everything within a namespace is very similar to the global admin above, however, we're no longer at the cluster level so we'll use just a role and rolebinding. We'll also need to identify the namespace to be used like this:
[root@k8s-master ~]# cat monitoring-admin.yaml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: monitoring-admin
  namespace: monitoring
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["*"]
[root@k8s-master ~]# cat monitoring-admin-binding.yaml 
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: monitoring-admin-binding
  namespace: monitoring
subjects:
- kind: User
  name: mengland
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: monitoring-admin
  apiGroup: rbac.authorization.k8s.io
[root@k8s-master ~]# kubectl create namespace monitoring
namespace/monitoring created
[root@k8s-master ~]# kubectl create -f monitoring-admin.yaml 
krole.rbac.authorization.k8s.io/monitoring-admin created
[root@k8s-master ~]# kubectl create -f monitoring-admin-binding.yaml 
rolebinding.rbac.authorization.k8s.io/monitoring-admin-binding created
If users are admins in a specific namespace, they'll need to specify that in their command line with -n or --namespace. In the next post I'll show you how to configure the users kubectl client to make use of this user and role.

No comments:

Post a Comment