Simon
Simon

Reputation: 1312

How to programmatically authenticate to Azure Kubernetes (AKS)

I'm having an AKS cluster setup and recently enabled the Azure Active Directory integration. I'm having a C# application that is running outside of the Kubernetes cluster that is creating Kubernetes Jobs. Therefore, I'm using the C# KubernetesClient package which has been working fine before (and still is). However, it is using a so called "local account" (so the local admin user) which is not integrated with the Active Directory. My goal is to completely deactivate the local accounts in the long run, meaning I need a different way of authenticating. As the Kubernetes Cluster is now fully integrated with the AAD, I preferrably want to use a service principal for authentication.

Microsoft is not providing any documentation on how to achieve this and the support hasn't been particular helpful.

Upvotes: 3

Views: 2493

Answers (1)

Simon
Simon

Reputation: 1312

You need to manually get an Access Token for the Kubernetes environment. This can be done with the following code:

var credFactory = new AzureCredentialsFactory();
var credentials = credFactory.FromServicePrincipal(
    "CLIENT_ID",
    "CLIENT_SECRET",
    "TENANT_ID",
    AzureEnvironment.AzureGlobalCloud
);

var azure = Microsoft.Azure.Management.Fluent.Azure
    .Authenticate(credentials)
    .WithSubscription("SUBSCRIPTION_ID");

var kubeConfigBytes = azure.KubernetesClusters.GetUserKubeConfigContents(
    "K8S_RESOURCE_GROUP",
    "K8S_CLUSTER_NAME"
);


var kubeConfigRaw = KubernetesClientConfiguration.LoadKubeConfig(new MemoryStream(kubeConfigBytes));
var authProvider  = kubeConfigRaw.Users.Single().UserCredentials.AuthProvider;
if (!authProvider.Name.Equals("azure", StringComparison.OrdinalIgnoreCase))
    throw new Exception("Invalid k8s auth provider!");

// Token Helper is a small helper utility that I use instead of MSAL
// This method is doing a POST call to https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token
var token = TokenHelper.GetTokenByClientCredentials(
    "CLIENT_ID",
    "CLIENT_SECRET",
    "TENANT_ID",
    "6dae42f8-4368-4678-94ff-3960e28e3630/.default" // This scope is always the same. It's the "Azure Kubernetes Service AAD Server" app from Microsoft. (az ad sp show --id 6dae42f8-4368-4678-94ff-3960e28e3630)
).GetAwaiter().GetResult();

authProvider.Config["access-token"] = token.AccessToken;
authProvider.Config["expires-on"]   = DateTimeOffset.UtcNow.AddSeconds(token.ExpiresIn).ToUnixTimeSeconds().ToString();

var kubeConfig    = KubernetesClientConfiguration.BuildConfigFromConfigObject(kubeConfigRaw);
var kubernetes = new Kubernetes(kubeConfig);

Please keep in mind that the token expires every hour, so you need to creat a new Kubernetes instance regularly. Also note that this only takes care of the Authentication, not Authorization. Meaning, you will be able to login, but your service principal might not be allowed to read/edit any kubernetes resources. For that to work you need to assign a Role or CluterRole to your service principal as described HERE.

Upvotes: 1

Related Questions