How to use an existing OpenStack username and password to authenticate a Kubernetes cluster.

image

Saverio Proto is a cloud engineer at SWITCH, a national research and education network in Switzerland, which runs a public cloud for national universities.

At SWITCH we’re looking to provide a container platform-as-a-service solution. To that end, we’re working on Kubernetes and OpenShift to gauge what’s possible and how a service could be structured. It would be really nice to use the existing OpenStack username and password to authenticate to Kubernetes. We tested this solution and it works great.

How does it work? Let’s start from the client side.

Kubernetes users use the kubectl client to access the cluster. The good news is that since version v1.8.0 of the client, kubectl is able to read the usual openstack env variables, contact Keystone to request a token and forward the request to the Kubernetes cluster using the token. This was merged August 7, 2017. However, I couldn’t find anywhere how to correctly configure the client to use this functionality so eventually I wrote some documentation notes here.

How does it work on the Kubernetes master side ?

The Kubernetes API receives a request with a Keystone token. In Kubernetes language, this is a Bearer Token. To verify the Keystone token the Kubernetes API server will use a WebHook. What does it mean? That the Kubernetes API will contact yet another Kubernetes component that’s capable of authenticating the Keystone token.

The k8s-keystone-auth component developed by Dims makes exactly this. I tested his code and I created a Docker container to integrate the k8s-keystone-auth in my kube-system namespace. When you run the k8s-keystone-auth container your pass as an argument the URL of your keystone server.

If you’re deploying your cluster with k8s-on-openstack, you can find this integration summarized in a single commit.

Now that everything’s set up, I can try:

source ~/openstackcredentials
kubectl get pods

I will be correctly authenticated by Keystone, but I'll have no authorization to do anything:

Error from server (Forbidden): pods is forbidden: User "[email protected]" cannot list pods in the namespace "default"

This is because we need to set up some authorization for this Keystone user. You can find detailed documentation about role-based access control (RBAC), but here's a simple example:

kubectl create rolebinding saverio-view --clusterrole view --user [email protected] --namespace default

Now my user is able to view anything in the default namespace and I'll be able to do kubectl get pods.

Of course, setting up RBAC specific rules for every user is not optimal. You can at least use the Keystone projects that are mapped to kind: Group in Kubernetes.

Here's an example:


kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: read-pods
 namespace: default
subjects:
- kind: Group
 name: <openstack_project_uuid>
 apiGroup: rbac.authorization.k8s.io
roleRef:
 kind: Role
 name: pod-reader
 apiGroup: rbac.authorization.k8s.io

You can then achieve a “soft multi-tenancy” where every user belonging to a specific Keystone project has limited permissions to a specific namespace. I call it soft multi-tenancy because all the pods from all the namespaces, depending on your networking solution, could end up on the same network with a completely open policy.

I'd like to thank Dims and the other people on the Kubernetes Slack channel #sig-openstack for all their help while developing this deployment.

 

This post first appeared on the SWITCH blog. Superuser is always interested in community content, get in touch at editorATopenstack.org.

Cover Photo // CC BY NC