Auth’ing w/ Kubernetes Engine service accounts

Caveat Developer

Daz Wilkin
Google Cloud - Community
5 min readMar 7, 2019

--

You can authenticate against Kubernetes Engine resources using Kubernetes (!) service accounts. I was unable to find examples of this approach in Kubernetes (Engine) documentation so — please — treat with discretion and, if you’ve any security concerns about this approach, don’t employ it.

Our ambition is to use a Kubernetes Engine service account to authenticate and authorize some software process, e.g. a CI|CD pipeline.

NB When I initially looked into this problem, I assumed the service account would need to be a Google Cloud Platform service account not a Kubernetes Engine service account.

Cluster

I assume you’ve a (sacrifical) cluster (called cluster) that you are willing to use to test this and a context called root.

Context

To ensure we’re explicit about which context we’re using, let’s unset the default context; this will require us to explicitly reference our desired context for each kubectl command:

Namespace

To scope our work, let’s create and use a namespace for this:

Service Account

Let’s create a Kubernetes Engine service account. For simplicity, we’ll create the service account in ${NAMESPACE} but it need not be created in nor is limited to this namespace:

NB My apologies if you dislike my overloading the name test. Because each resource is distinct, it isn’t a problem. Use your preferred values.

Authentication

Kubernetes Engine leverages Google [Cloud Platform] [OAuth2] authentication. If you inspect your Kubernetes configuration file, you’ll see that your credentials are obtained using gcloud config config-helper:

If you run this command, you’ll see the access_token obtained by the gcloud command and used by kubectl to authenticate you to the cluster.

One side-effect of the approach outlined in this post is that it doesn’t require gcloud to be available for the software to repeatedly auth against the cluster.

We’re going to create a new user (called ${NAME}) to represent the service account:

NB The set-credentials command is adding a bearer token to your Kubernetes configuration file. It is imperative that you control access to this token and the file. If you lose control of either, revoke the Secret (!) using kubectl delete secret/${SECRET} --namespace=${NAMESPACE} --context=root.

NB In the last command, we’re going to create a context that’s named after ${NAME}. You may prefer to name the context distinctly from the name of the user.

NB If you kubectl describe secret/${SECRET} ... you get given the base64 decoded value. But kubectl get secret/${SECRET} ... returns the base64 encoded value. We want the decoded value.

Now, if you review the ~/.kube/config file, you should see the addition of a user entry for ${NAME} and a context entry:

But:

Authenticated but not authorized.

Authorization

This account has no permissions on the cluster.

We’re going to grant ${NAME} the ability to use deployments. To do so we’ll need to a create a Role (I’m using Role rather than ClusterRole for specificity) and then a RoleBinding between ${NAME} and the Role.

Test

Let’s create test deployments in namespace default and ${NAMESPACE}:

Our root context has full authorization but our ${NAME} context (representing our ${NAME} user) should only be able to enumerate deployments in ${NAMESPACE}:

NB kubectl run creates Deployments using extensions rather than the new apps API Group.

Conclusion

Kubernetes Engine auth powered by Google OAuth is excellent and generally the way to go.

As has been shown here, if you have software (rather than a human) that’s external to a cluster and needs to interact with the cluster, you may use Kubernetes Service Accounts to authenticate and grant the account precise permissions (authorization).

Going directly cuts out the need to include gcloud in the external software’s configuration. Although — please remember — that the token that’s added to the ~/.kube/config file is a bearer token. Whatever has the token can access the cluster with the service account’s permissions. If you lose control of the token or a Kubernetes config file that references it, delete the secret:

This will then disable use of the token:

The result is not instantaneous but it should be prompt.

Tidy up!

A sledge-hammer approach to tidying-up is:

Because the Service Account, Role , RoleBinding and one Deployment were created in this namespace, they will be deleted with it.

To delete the other Deployment:

To remove the configuration file changes:

That’s all!

--

--