Generate Kubernetes Access Token
There are various ways to connect to a Kubernetes cluster, but for a recent event (GDBC) I needed to connect to an Azure Kubernetes Cluster using an API call. For this event, we used Docker containers to do the actual work and the underlying infrastructure needed to schedule these containers to one of the available AKS instances.
Connecting to the cluster
To talk to the AKS cluster, I used the open source KubernetesClient NuGet package. Under the hood, it will call the REST API of the cluster to perform actions.
Creating a connection is a matter of setting up a KubernetesClientConfiguration
instance.
var config = new KubernetesClientConfiguration
{
Host = clusterSetting.Host,
SkipTlsVerify = true,
AccessToken = clusterSetting.AccessToken
};
Here I used the hostname as found in the AKS blade in Azure and the access token that I retrieved as shown below. When I have a configuration, I can connect to the cluster itself and perform actions:
using (var client = new Kubernetes(config))
{
var response = await client.CreateNamespacedPodWithHttpMessagesAsync(
new V1Pod(
metadata: new V1ObjectMeta(name: message.MessageId,
namespaceProperty: "default"
, labels: new Dictionary<string, string>
{
{"messageId", message.MessageId}
}
),
spec: new V1PodSpec(containers: messageData.Containers.Select((a, index) =>
new V1Container
{
Name = $"{messageData.ChallengeId.ToLowerInvariant()}-{index + 1:D2}",
Image = a.Name,
ImagePullPolicy = "Always" }).ToList(),
terminationGracePeriodSeconds: 0,
restartPolicy: "Never")),
"default", cancellationToken: token).ConfigureAwait(false);
}
The above code will create a Pod in the default
namespace and starts one or more containers inside this Pod.
Getting the Access Token
In order to get an access token, I need to create an account first and give it the correct rights.
Assuming we have connected to the cluster in some form, we can issue commands using the kubectl tool.
Lets first create a service account called gdbc
.
kubectl create serviceaccount gdbc
Next, give this account access to the cluster:
kubectl create clusterrolebinding gdbc \
--clusterrole=cluster-admin \
--serviceaccount=default:gdbc
I can now find the secrets created and get the contents of the secret as it not such a secret that it is encrypted.
kubectl get secrets
This will return a list of secrets similar to:
NAME TYPE DATA AGE
default-token-t6j62 kubernetes.io/service-account-token 3 163d
gdbc-token-hhp2g kubernetes.io/service-account-token 3 11s
Now fetch the one that starts with the provided name:
kubectl describe secret gdbc-token-hhp2g
The output will be something like this:
Name: gdbc-token-hhp2g
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name=gdbc
kubernetes.io/service-account.uid=50266d42-9989-11e9-9728-00155df43454
Type: kubernetes.io/service-account-token
Data
====
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZheddeVzLmlvL3NlcweY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZ2RiYyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmdeS1hY2NvdW50LnVpZCI6IjUwMjY2ZDQyLTk5ODktMTFlOS05NzI4LTAwMTU1ZGY0MzQ1NCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmdkYmMifQ.Bd-inWYl4Y-wECjFkF7kEt0S-o3Ah17osJg5JGkAB2Xu7ypFS6ur6S6p6JiqjP9X9gsLfBBjXZrZn8RnOxUfuEoPFtjIFCnXI4xNsNWzSo8ahbwETb5lfGkMFFurYyxlSYqE3FO1X3L7xGQfYXaD5vEVZ01dTrZdQ87PH-lYhvwVmkIu3gmW6aLgEIapnU26PSkzv8Ca_q-3MMBSikkYrTB7GugTKRtHkgYWdN3NQXTmEBBqmmLHJKewtwacKiATpgp7J6_aMyiuY4arCvL8F0DYL3-YkuPfhpgTMEHDRuZdfQSsf8aZgTLaD3lP1MgxNqZBfWfIjO7vd2WAlvQmvQ
ca.crt: 1025 bytes
namespace: 7 bytes
The token is nothing more then a Json Web Token. This value can be used as the access token in the above API call.
Conclusion
Getting the access token to make authenticated calls to a Kubernetes cluster is not that difficult, but be aware that you need to carefully store the access token and give it the correct amount of privileges!
Leave a comment