Skip to content

Instantly share code, notes, and snippets.

@surajssd
Last active July 11, 2023 13:41
Show Gist options
  • Save surajssd/1bb59c7df719f953d1e82677d09c3584 to your computer and use it in GitHub Desktop.
Save surajssd/1bb59c7df719f953d1e82677d09c3584 to your computer and use it in GitHub Desktop.
Using Azure's user managed identity for the Kubernetes workloads
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
func main() {
clientID := os.Getenv("AZURE_CLIENT_ID")
tenantID := os.Getenv("AZURE_TENANT_ID")
tokenFilePath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
authorityHost := os.Getenv("AZURE_AUTHORITY_HOST")
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
if clientID == "" {
log.Fatal("AZURE_CLIENT_ID environment variable is not set")
}
if tenantID == "" {
log.Fatal("AZURE_TENANT_ID environment variable is not set")
}
if tokenFilePath == "" {
log.Fatal("AZURE_FEDERATED_TOKEN_FILE environment variable is not set")
}
if authorityHost == "" {
log.Fatal("AZURE_AUTHORITY_HOST environment variable is not set")
}
if subscriptionID == "" {
log.Fatal("AZURE_SUBSCRIPTION_ID environment variable is not set")
}
ctx := context.Background()
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatal(err)
}
vmSizesClient, err := armcompute.NewVirtualMachineSizesClient(subscriptionID, cred, nil)
if err != nil {
log.Fatal(err)
}
pager := vmSizesClient.NewListPager("eastus", &armcompute.VirtualMachineSizesClientListOptions{})
for pager.More() {
nextResult, err := pager.NextPage(ctx)
if err != nil {
err:= fmt.Errorf("getting next page of VM sizes: %w", err)
log.Fatal(err)
}
for _, vmSize := range nextResult.VirtualMachineSizeListResult.Value {
log.Printf("VM Size: %s", *vmSize.Name)
}
}
}
# Here we will use the workload identity in AKS.
export AZURE_RESOURCE_GROUP=""
export AZURE_REGION="eastus"
az group create --name "${AZURE_RESOURCE_GROUP}" \
--location "${AZURE_REGION}"
export AZURE_SUBSCRIPTION_ID=$(az account show --query id --output tsv)
export CLUSTER_NAME="caa"
export AKS_WORKER_USER_NAME="azuser"
export SSH_KEY=~/.ssh/id_rsa.pub
export AKS_RG="${AZURE_RESOURCE_GROUP}-aks"
az aks create \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--node-resource-group "${AKS_RG}" \
--name "${CLUSTER_NAME}" \
--location "${AZURE_REGION}" \
--node-count 1 \
--node-vm-size Standard_F4s_v2 \
--ssh-key-value "${SSH_KEY}" \
--admin-username "${AKS_WORKER_USER_NAME}" \
--enable-addons http_application_routing \
--enable-oidc-issuer \
--enable-workload-identity \
--os-sku Ubuntu
az aks show --resource-group "${AZURE_RESOURCE_GROUP}" \
--name "${CLUSTER_NAME}" \
--query addonProfiles.httpApplicationRouting.config.HTTPApplicationRoutingZoneName -o table
az aks get-credentials \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--name "${CLUSTER_NAME}"
export AKS_OIDC_ISSUER="$(az aks show \
--name "${CLUSTER_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--query "oidcIssuerProfile.issuerUrl" -otsv)"
# -----
export USER_ASSIGNED_IDENTITY_NAME="caa-${AZURE_RESOURCE_GROUP}1"
az identity create \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--location "${AZURE_REGION}" \
--subscription "${AZURE_SUBSCRIPTION_ID}"
export PRINCIPAL_ID="$(az identity show \
--name "${USER_ASSIGNED_IDENTITY_NAME}" \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--subscription "${AZURE_SUBSCRIPTION_ID}" --query principalId -otsv)"
az role assignment create \
--role Contributor \
--assignee-object-id "${PRINCIPAL_ID}" \
--scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}/resourceGroups/${AZURE_RESOURCE_GROUP}"
az role assignment create \
--role Contributor \
--assignee-object-id "${PRINCIPAL_ID}" \
--scope "/subscriptions/${AZURE_SUBSCRIPTION_ID}/resourceGroups/${AKS_RG}"
export USER_ASSIGNED_CLIENT_ID="$(az identity show \
--resource-group "${AZURE_RESOURCE_GROUP}" \
--name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)"
# ----
export SERVICE_ACCOUNT_NAMESPACE=foo
export SERVICE_ACCOUNT_NAME=foo
export FEDERATED_IDENTITY_CREDENTIAL_NAME=foo
az identity federated-credential create \
--name ${FEDERATED_IDENTITY_CREDENTIAL_NAME} \
--identity-name ${USER_ASSIGNED_IDENTITY_NAME} \
--resource-group ${AZURE_RESOURCE_GROUP} \
--issuer ${AKS_OIDC_ISSUER} \
--subject system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}
kubectl create ns ${SERVICE_ACCOUNT_NAMESPACE}
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: ${USER_ASSIGNED_CLIENT_ID}
labels:
azure.workload.identity/use: "true"
name: ${SERVICE_ACCOUNT_NAME}
namespace: ${SERVICE_ACCOUNT_NAMESPACE}
EOF
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: quick-start
namespace: ${SERVICE_ACCOUNT_NAMESPACE}
labels:
azure.workload.identity/use: "true"
spec:
serviceAccountName: ${SERVICE_ACCOUNT_NAME}
containers:
- image: ubuntu
name: ubuntu
command:
- sleep
args:
- infinity
EOF
kubectl -n $SERVICE_ACCOUNT_NAMESPACE exec -it quick-start -- bash
#----
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v4"
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
)
func main() {
clientID := os.Getenv("AZURE_CLIENT_ID")
tenantID := os.Getenv("AZURE_TENANT_ID")
tokenFilePath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
authorityHost := os.Getenv("AZURE_AUTHORITY_HOST")
subscriptionID := os.Getenv("AZURE_SUBSCRIPTION_ID")
if clientID == "" {
log.Fatal("AZURE_CLIENT_ID environment variable is not set")
}
if tenantID == "" {
log.Fatal("AZURE_TENANT_ID environment variable is not set")
}
if tokenFilePath == "" {
log.Fatal("AZURE_FEDERATED_TOKEN_FILE environment variable is not set")
}
if authorityHost == "" {
log.Fatal("AZURE_AUTHORITY_HOST environment variable is not set")
}
if subscriptionID == "" {
log.Fatal("AZURE_SUBSCRIPTION_ID environment variable is not set")
}
ctx := context.Background()
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
log.Fatal(err)
}
computeClientFactory, err := armcompute.NewClientFactory(subscriptionID, cred, nil)
if err != nil {
log.Fatal(err)
}
// This code works where I am getting the virtual machine
vmClient := computeClientFactory.NewVirtualMachinesClient()
resp, err := vmClient.Get(ctx, "suraj-rg2", "azure-dev-box", nil)
if err != nil {
log.Fatalf("getting vm: %v", err)
}
fmt.Printf("this is the resp: %#v\n", *resp.ID)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment