NOTE: This post assumes that you already have some experience working with Azure and Kubernetes.
What we will do
In this post, we will go through the steps for how to consume the API in your Azure Kubernetes Cluster programmatically, with C#.
Simplified, we will:
- Create a service principal
- Use the Azure Management SDK to authenticate
- Use the Azure Manager to fetch the Administrator token from Kubernetes
- Execute a HTTP request against the Kubernetes API
Ready? Let's do it!
Create a service principal
Open your browser and go to portal.azure.com
In the Portal, open the Active Directory blade.
Go to App registrations.
Click + New registration and follow the wizard to create your service principal.
The Service Principal (App Registration) will be the "user" you will use to access Kubernetes via the Azure Management SDK.
Take a careful note of your Application (client) ID and Directory (tenant) ID.
Under Manage in the menu, open Certificates & secrets.
Click + New client secret to add a new client secret and make a careful note of the Value once it has been created!
Grant access to the service principal in Kubernetes
Go to the portal home again and open the Kubernetes services blade.
Open your desired Kubernetes serice and click Access control (IAM) in the menu.
Here, we need to grant permission to the service principal (app registration) we just created, so that we can later retrieve the administrator token for the cluster.
In the usual way, grant a role assignment for the service principal. The role "Contributor" should be OK.
When you've done that, let's open up Visual Studio and get ready to code!
Authenticate with the Azure Management SDK
I'm going to be programming this in a Console Application, but really, this technique applies to any platform, be it a desktop application, Web API, Azure Function, etc.
When you've got your project set up, you'll need to install a NuGet package.
Open the package manager and install Microsoft.Azure.Management.Fluent
When that's installed, find a suitable place to write your C# code. We'll be using await, so make sure you are working in an async Task method.
Add these using directives to the top of the file:
using Microsoft.Azure.Management.ResourceManager.Fluent;
using Microsoft.Azure.Management.Fluent;
using System.Text;
using System.Text.RegularExpressions;
using System.Net.Http;
Since we want to use the Azure management SDK, we better start off by creating the credentials. For this, we use the Azure Credentials Factory in the SDK Context.
var credentials = SdkContext.AzureCredentialsFactory
.FromServicePrincipal(
clientId: APPLICATION_ID,
clientSecret: CLIENT_SECRET,
tenantId: DIRECTORY_ID,
environment: AzureEnvironment.AzureGlobalCloud);
Obviously, you need to replace the constants (in capital letters) with the values that you carefully made a note of earlier 🤓
The next thing to do is create an instance of an implemented IAzure interface by using the Fluent API.
IAzure azure = Azure
.Configure()
.Authenticate(credentials)
.WithSubscription(SUBSCRIPTION_ID);
The SUBSCRIPTION_ID should be the GUID which is found in the portal on the Overview of your Kubernetes service.
Get the Kubernetes admin config
Next, we need to get the administrator configuration for Kubernetes:
var bytes = await azure.KubernetesClusters.GetAdminKubeConfigContentsAsync(
resourceGroupName: RESOURCE_GROUP,
kubernetesClusterName: CLUSTER_NAME);
This is a bit strange, as it actually returns an array of bytes, which is not exactly intuitive from an SDK-perspective.
To convert these bytes to a string, use:
var str = Encoding.UTF8.GetString(bytes);
The payload received is actually a YAML file, not JSON.
Extract the token
We need to extract the token from this YAML string. The token is effectively a SHA-512 hash (128 character hex), so we can use regex to accomplish this.
var regex = new Regex("[ ]{4}token: ([0-9a-f]{128})([ ]|$)");
var match = regex.Match(str);
string token;
if (match.Success)
{
token = match.Groups[1].Value;
}
else throw new Exception("Unable to extract token!");
Now we've got the token, we can use this as a Bearer token for the Kubernetes API request.
This document describes how to use Bearer tokens for OAuth in detail:
tools.ietf.org
Kubernetes API targeting
Back in the portal, you need to determine the link to your Kubernetes API.
This is found under your Kubernetes service Overview, under API server address. This typically ends in .azmk8s.io
Make a note of this host name, you'll use it in the next step...
Create a message request
You can use the HttpRequestMessage class to create the request message.
The URL you want to target is:
https:// mykubernetescluster.azmk8s.io /api/v1/namespaces/my-namespace/pods
Replace the host with your actual Kubernetes API server address.
Replace my-namespace with your desired Kubernetes namespace.
See the Kubernetes documentation:
kubernetes.io
You may use some code similar to this:
var builder = new UriBuilder("https", API_SERVER_ADDRESS);
builder.Path = "/api/v1/namespaces/default/pods";
var message = new HttpRequestMessage();
message.Method = new HttpMethod("GET");
message.RequestUri = builder.Uri;
message.Headers.Add("Authorization", "Bearer " + token);
See the Kubernetes API reference:
kubernetes.io
Send the request message
Be aware, that in some case, you may experience SSL errors when targeting the Kubernetes API error in Azure. If this happens, you can use a Http client handler with a custom certificate validation callback function. I've included this in the example below.
var client = new HttpClient(new HttpClientHandler()
{
ServerCertificateCustomValidationCallback = (w, x, y, z) => true
});
var response = await client.SendAsync(message);
var content = await response.Content.ReadAsStringAsync();
And that's it! The content string will usually be some sort of JSON representing the object returned by the server.
Summary
A service principal must have permissions granted to it for the Kubernetes cluster. Use the Azure Management SDK to fetch the Adminstrator token. Use HTTP requests to target the API and execute GET or POST requests.
Happy coding! Please support me by leaving a comment and sharing this article 👍