Authenticate a Google Kubernetes cluster certificate over https?

11/25/2020

I'm a little lost trying to get acccess to a Kubernetes cluster hosted on Google Kubernetes Engine.

I would like to use a cluster certificate to authenticate to the provided kubernetes endpoint, so that I can run API requests to the kubernetes api, like creating deployments for example.

I'm trying to create deployments from an external API (from a NodeJS app, hosted on google app engine), where I will automatically create deployments on various different kubernetes clusters, not necessarily in the same google project.

I used to use basic auth to authenticate to the kubernetes api, this was trivial, all I needed was the username and password for a cluster, and then to base64 encode the two and put it in an Authentication header. I did this using axios and had no problems at all.

Now I'd like to switch over to using client certificates and I think I lack some understanding.

I guess I need to get the provided endpoint ip of the cluster, download the cluster certificate provided by google... that looks something like this:

enter image description here

...possibly base64 encode it and save it as a .crt, .cert, or ??.pem file and point axios to the file using a httpagent? (I tried saving the raw data as a .crt and .cert file, setting it as a httpagent and this unsurprisingly didn't work).

Do I need some kind of client/server key pair for the certificate, or maybe an API key?

I also read something about setting a Bearer token as an Authorization header, I guess this needs to be paired with the certificate, but I'm unsure where I can find/generate this token?

If there's anyone who can help with this obscure issue I'd be very grateful,

Thanks in advance!

P.S. I've been trying to decipher the K8s docs and I think I'm close, but I'm still not sure I'm looking at the right docs: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/

-- Emile Esterhuizen
axios
google-kubernetes-engine
javascript
kubernetes
node.js

2 Answers

11/27/2020

I've resolved the issue and I thought I'd post an answer in case someone is in my situation and needs a reference.

Alberto's answer is a great one, and I think this is the most secure mindset to have, its definitely preferable to keep everything internal to the google environment. But in my case, even if just for testing, I really needed to interface with the kubernetes API over https from another domain.

It turns out that it was simpler than I anticipated, instead of using the CA certificate, what I needed to do was to fetch a service account token from google cloud shell and place this in the Authorization header (very similar to basic auth). (In addition I should check the validity of the kubernetes endpoint by using the service account's client certificate, but I did not so this.)

Once in the google cloud shell and authenticated to the relevant cluster run the following:

  1. kubectl get serviceaccount
  2. kubectl get serviceaccount default -o yaml
  3. kubectl get secret-default-token-some_id_string -o yaml
  4. kubectl create clusterrolebinding default-serviceaccount-admin --clusterrole=cluster-admin --serviceaccount=default:default

Point 1 displays whether there is in fact a default service account present, this should be the case with a cluster created on Google Kubernetes Engine.

Point 2 prints out which service account is the default and should provide a service account name, something like "secret-default-token-abcd"

Point 3 prints out the token as well as its corresponding certificate. The token is printed as a base64 encoded string and needs to be decoded before it can be used in a http request.

Point 4 assigns the default service account a role (part of the Kubernetes RBAC thing) so that it has the correct permissions to create and delete deployments in the cluster.

Then in postman or wherever you're making the Kubernetes api call, set an Authorization header as follows:

Authorization: Bearer <base64 decoded token received in point 3>

Now you can make calls directly to the kubernetes api, for example, to create or delete deployments.

As mentioned above the certificate also provided as a base64 encoded string in Point 3, can be used to verify the kubernetes endpoint, but I haven't tested this (definitely more secure way of doing things).

In addition I was making the http call in a nodejs script and I had to set an environment variable process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; to override the certificate check... definitely not a safe way to go and not recommended.

-- Emile Esterhuizen
Source: StackOverflow

11/26/2020

I'm not sure if using manual authentication is the best for this case, as one of the good features of Kubernetes Engine is that it will provide authentication configuration for kubectl for you automatically, via the ‘gcloud container clusters get-credentials’ command. There are also some resources (like connecting to another cluster) that are controlled via GCP IAM permissions instead of inside Kubernetes.
I would advise you to take a deep look at this page:
https://cloud.google.com/kubernetes-engine/docs/how-to/api-server-authentication
This should also handle the certificate for you.

In general I would advise you to check the GKE documentation first before the kubernetes one, as GKE is not only just Kubernetes but it also makes managing some things way easier.

-- Alberto Pau
Source: StackOverflow