Now we know a little about Authentication and the protocols OAuth2 and OIDC and the terminology involved in these flows, we’re now going to see how these protocols relate back to AKS.
Client and Server Tenant Application
To enable Azure Active Directory integration in your AKS cluster, we require two Tenant Applications, Client and Server. Both of which are registered with the Microsoft Identity Platform.
In legacy AKS clusters, you were required to create your own Azure Client and Server applications (https://docs.microsoft.com/en-us/azure/aks/azure-ad-integration-cli) but now Azure have this built in during the Cluster creation process.
The Client in this case acts on the users behalf to generate an ID token, very much like MyCoolApp used it’s Google Client ID when acting on behalf of a user to access their Google Profile info and sign them in.
The Server is an application, who’s job it is to validate an ID token as well as retrieve all the AD Groups the user identified with the ID Token has access to in Azure Active Directory.
So if you think about it, when you login to your AKS Cluster, you will use the client to generate an ID token on your behalf. You then present this ID token to the Kubernetes cluster when performing cluster management operations, and the AKS Cluster uses the Server App to validate your ID token to make sure you are who you say you are as well as checking what AD Groups you have access to.
AZ AKS CLI and Kubectl Flow
Let’s look at the flow, when you get what I like to call the skeleton Kubeconfig file via the az cli, and then get your Identity section in the Kubeconfig file via kubectl.
- First up you will run the az aks get-credentials … command to get the skeleton kubeconfig file. If you look at your kubeconfig file now, you will notice it’s missing your user identity fields (access-token, refresh-token, expires-in and expires-on)
- If there is no existing access-token in the kubeconfig file for this cluster, kubectl will call the device code flow (https://github.com/kubernetes/client-go/tree/master/plugin/pkg/client/auth/azure) against the Microsoft Identity Platform. As part of this flow, kubectl will use the client-id as the client and the apiserver-id as the resource we want to access.
- This device code endpoint will return information including the url to be displayed to the user and a code that the user will input after navigating to the url. The code will be used to identify the session initiated via the /devicecode endpoint. The user must now open the url and enter the device code.
- The user will now be prompted to authenticate their identity via the client application, like in our earlier examples where we had to enter our username and password
- In the meantime, kubectl will continuously poll the tenant oauth token endpoint to check if a token has been issued for the device code and client application.
- Once the user has successfully signed in, the polling kubectl code will successfully get an access token, refresh token and token expiry information and write it to the kubeconfig file alongside the auth provider section.
- Now kubectl will continue it’s call to the api server.
- The webhook auth then will check the ID token passed to it. It will use the server app id and secret we talked about earlier to query the Microsoft Identity Platform to verify users JWT token and also get a list of all the AD groups the user is part of.
- Using this information coupled with the kubernetes roles and rolebindings, kubernetes will determine if you have access to the namespace and/or resource in question in the kubernetes cluster
That’s the Interactive Authentication Flow!
Kubeconfig Identity Items
So let’s just finish this Part by looking at the Identity Items in the Kubeconfig file.
access-token as we already mentioned is our ID token or JWT token, which when decoded identifies a unique identity. The JWT token can only be verified by the issuing OAuth2 Server. It’s a relatively short lived token and is only valid for 1 hour.
refresh-token is an opaque token, only understandable by the OAuth2 Server, and this token is what allows us to refresh our access-token (ID token). You can see the code here https://github.com/kubernetes/client-go/blob/master/plugin/pkg/client/auth/azure/azure.go#L208 that will refresh the token when it’s expired. The refresh token is usually valid for 90 days.
expires-in is the time in seconds when the access-token will expire
expires-on is the epoch date/time when the access-token will expire
All Right! We’re ready to write some code and implement our own solution for Non Interactively Connecting to an AKS Cluster.