Create a GitOps Cluster with Azure Workload Identity Federation (WIF)
In this guide, you'll set up Harness GitOps (powered by Argo CD) to connect securely to an Azure Kubernetes Service (AKS) cluster without storing kubeconfigs or static credentials.
What is Azure WIF?
Azure Workload Identity Federation (WIF) allows Kubernetes ServiceAccounts to securely access Azure resources without storing credentials or secrets in the cluster.
Instead, AKS issues short-lived tokens through its OpenID Connect (OIDC) issuer, which Azure validates before granting access to the linked Azure AD application.
With WIF:
- No kubeconfigs or static service principal secrets are stored
- Authentication is short-lived and automatically rotated
- Access is scoped to a specific Kubernetes ServiceAccount
Learn more: Azure Workload Identity Federation documentation
Prerequisites
Before setting up Azure WIF with GitOps, ensure you have:
- Azure subscription with appropriate permissions to:
- Create and manage Azure AD applications
- Create and manage Managed Identities
- Assign RBAC roles
- Manage AKS clusters
- AKS cluster with specific authentication and authorization configuration
- Harness GitOps module enabled in your account
Your AKS cluster must be configured with one of these specific authentication and authorization combinations:
- Microsoft Entra ID authentication with Azure RBAC, OR
- Microsoft Entra ID authentication with Kubernetes RBAC
Other authentication methods may cause connection failures.
Overview of the Setup Process
The Azure WIF setup involves these key steps:
- Configure AKS Security - Set up proper authentication and authorization
- Enable OIDC and Workload Identity - Enable your AKS cluster to issue trusted tokens
- Create Managed Identity - Create an Azure managed identity for your GitOps agent
- Download and Modify GitOps Agent YAML - Download the agent YAML and add workload identity annotations
- Configure Federated Credentials - Link your Kubernetes ServiceAccount to the managed identity
- Deploy GitOps Agent - Install the modified agent
- Create Cluster Secret - Configure the cluster connection with workload identity authentication
- Verify Setup - Ensure the cluster appears healthy in Harness UI
Step 1: Configure AKS Security Settings
Ensure your AKS cluster is configured with the correct authentication and authorization method.
Required Security Configuration
Your cluster must use one of these configurations:
Option 1: Microsoft Entra ID authentication with Azure RBAC
az aks update -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" \
--enable-aad \
--enable-azure-rbac
Option 2: Microsoft Entra ID authentication with Kubernetes RBAC
az aks update -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" \
--enable-aad
Using Azure Portal
- Navigate to the Azure Portal
- Go to Kubernetes services and select your AKS cluster
- In the left menu, click Authentication and authorization
- Under Authentication method, select Microsoft Entra ID
- Under Authorization, choose either:
- Azure RBAC (recommended for most scenarios)
- Kubernetes RBAC (if you prefer Kubernetes-native RBAC)
- Click Save to apply the changes
Step 2: Enable OIDC Provider and Workload Identity
Enable the OIDC issuer and Workload Identity on your AKS cluster:
Using Azure CLI
az aks update -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" \
--enable-oidc-issuer \
--enable-workload-identity
Using Azure Portal
- In your AKS cluster page, go to Settings → Security
- Under Workload Identity, toggle Enable workload identity to Enabled
- Under OIDC Issuer, toggle Enable OIDC issuer to Enabled
- Click Save to apply the changes
- After saving, note down the OIDC Issuer URL displayed - you'll need this for federated credentials
Retrieve the OIDC Issuer URL
Get the OIDC issuer URL, which you'll need for configuring federated credentials:
Using Azure CLI
OIDC_ISSUER_URL=$(az aks show -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" --query "oidcIssuerProfile.issuerUrl" -o tsv)
echo "OIDC Issuer URL: $OIDC_ISSUER_URL"
Using Azure Portal
- In your AKS cluster page, go to Settings → Security
- Under OIDC Issuer, copy the Issuer URL value
- Save this URL - you'll need it when configuring federated credentials
Step 3: Create Managed Identity
Create an Azure managed identity that will be used by your GitOps agent:
IDENTITY_NAME="gitops-managed-identity"
az identity create --name "$IDENTITY_NAME" --resource-group "$RESOURCE_GROUP"
Using Azure Portal
- In the Azure Portal, search for Managed Identities and select it
- Click + Create to create a new managed identity
- Fill in the details:
- Subscription: Select your subscription
- Resource group: Select your resource group
- Region: Select the same region as your AKS cluster
- Name: Enter
gitops-managed-identity
(or your preferred name)
- Click Review + create, then Create
- Once created, click Go to resource
Get Client ID and Tenant ID
Retrieve the client ID and tenant ID that you'll need for the service account annotations:
# Get Client ID from the managed identity
CLIENT_ID=$(az identity show --name "$IDENTITY_NAME" --resource-group "$RESOURCE_GROUP" --query clientId -o tsv)
echo "Client ID: $CLIENT_ID"
# Get Tenant ID from your Azure subscription
TENANT_ID=$(az account show --query tenantId -o tsv)
echo "Tenant ID: $TENANT_ID"
Reference Documentation:
Getting Client ID and Tenant ID via Portal
To get Client ID:
- In your managed identity page, go to Overview
- Copy the Client ID value
- Save this value - you'll need it for service account annotations
To get Tenant ID:
- In the Azure Portal, click on your profile icon (top right)
- Click Switch directory or go to Microsoft Entra ID
- In the Overview page, copy the Tenant ID value
- Alternatively, you can find it in your subscription details
Step 4: Download and Modify GitOps Agent YAML
Before you can configure workload identity authentication, you need to download the GitOps agent YAML from Harness and make specific modifications to it.
Download GitOps Agent YAML from Harness
First, let's get the agent YAML file from your Harness account:
- Log in to your Harness account and navigate to the GitOps module
- Go to GitOps → Settings → GitOps Agents
- Click + New GitOps Agent
- Fill in the agent details:
- Name: Enter a descriptive name for your agent (e.g.,
azure-wif-agent
) - Agent Type: Select Argo CD
- Namespace: Enter
argocd
(this must match the namespace in your federated credentials)
- Name: Enter a descriptive name for your agent (e.g.,
- Click Continue or Next
- Download the agent YAML file - this will be a file named something like
gitops-agent.yaml
- Save the file locally - you'll need to edit it before applying to your cluster
Do NOT apply the agent YAML to your cluster yet. You must first modify it with the workload identity annotations as described in the next steps.
Modify the Application Controller Service Account
Now that you have the agent YAML file, you need to modify it to include workload identity annotations.
Step 1: Open the downloaded YAML file in your preferred text editor.
Step 2: Find the Application Controller Service Account section. Look for this section in the file:
# Source: gitops-helm/charts/argo-cd/templates/argocd-application-controller/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
automountServiceAccountToken: true
metadata:
annotations:
azure.workload.identity/client-id: your-client-id
azure.workload.identity/tenant-id: your-tenant-id
name: argocd-application-controller
namespace: argocd
labels:
# ... existing labels
Step 3: Add the required annotations to the metadata.annotations
section:
azure.workload.identity/client-id
: Replaceyour-client-id
with the Client ID from Step 3azure.workload.identity/tenant-id
: Replaceyour-tenant-id
with the Tenant ID from Step 3
Add Workload Identity Label to Repo Server
Step 4: Find the Repo Server Deployment section. Look for this section in the same YAML file:
# Source: gitops-helm/charts/argo-cd/templates/argocd-repo-server/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: argocd-repo-server
namespace: argocd
# ... other metadata
spec:
template:
metadata:
annotations:
# ... existing annotations
labels:
azure.workload.identity/use: "true"
# ... existing labels
Step 5: Add the workload identity label to the spec.template.metadata.labels
section:
- Add
azure.workload.identity/use: "true"
This setting allows the repo server to use the workload identity.
Verify Your Modifications
Before proceeding, double-check that you've made these changes:
- Added
azure.workload.identity/client-id
annotation with your actual Client ID - Added
azure.workload.identity/tenant-id
annotation with your actual Tenant ID - Added
azure.workload.identity/use: "true"
label to the repo server deployment - Saved the modified YAML file
Keep the original downloaded file as a backup in case you need to start over with the modifications.
Step 5: Configure Federated Credentials
Create federated credentials to allow the service account to use the managed identity.
Navigate to Managed Identity
- In the Azure portal, go to Managed Identities
- Select the identity you created earlier (
gitops-managed-identity
) - Go to Settings → Federated credentials
- Click Add credential
Configure Federated Credential
Fill in the following details:
- Federated credential scenario: Select "Kubernetes accessing Azure resources"
- Cluster issuer URL: Use the OIDC issuer URL from Step 2
- Namespace:
argocd
(the namespace where you're deploying your GitOps application) - Service account:
argocd-application-controller
(must match the service account name in your agent YAML) - Name:
harness-gitops-federated-credential
(or any descriptive name)
Alternatively, use the Azure CLI:
az identity federated-credential create \
--name "harness-gitops-federated-credential" \
--identity-name "$IDENTITY_NAME" \
--resource-group "$RESOURCE_GROUP" \
--issuer "$OIDC_ISSUER_URL" \
--subject "system:serviceaccount:argocd:argocd-application-controller"
Step 6: Deploy the GitOps Agent
Apply the modified GitOps agent YAML to your cluster:
kubectl apply -f gitops-agent.yaml
Verify Agent Health
Wait for the agent to become healthy:
kubectl get pods -n argocd
Check that all pods are running and the agent shows as Healthy in the Harness UI.
Step 7: Create Cluster Secret
Create a Kubernetes secret that defines how to connect to your cluster using workload identity authentication.
Prepare Cluster Information
Get your cluster's API server endpoint and CA certificate:
# Get cluster endpoint
CLUSTER_ENDPOINT=$(az aks show -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" --query fqdn -o tsv)
echo "Cluster endpoint: https://$CLUSTER_ENDPOINT"
# Get CA certificate (base64 encoded)
CA_CERT=$(az aks get-credentials -g "$RESOURCE_GROUP" -n "$CLUSTER_NAME" --file - | grep certificate-authority-data | awk '{print $2}')
echo "CA Certificate: $CA_CERT"
Create the Secret YAML
Create a secret YAML file with the following content:
apiVersion: v1
kind: Secret
metadata:
name: gitops-cluster-secret
namespace: argocd
labels:
argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
name: azure-wif-cluster
server: https://your-cluster-endpoint
config: |
{
"execProviderConfig": {
"command": "argocd-k8s-auth",
"env": {
"AAD_ENVIRONMENT_NAME": "AzurePublicCloud",
"AZURE_CLIENT_ID": "your-client-id",
"AAD_LOGIN_METHOD": "workloadidentity"
},
"args": ["azure"],
"apiVersion": "client.authentication.k8s.io/v1beta1"
},
"tlsClientConfig": {
"insecure": false,
"caData": "your-base64-encoded-ca-cert"
}
}
Replace the following values:
your-cluster-endpoint
: Your cluster's API server endpointyour-client-id
: The client ID from your managed identityyour-base64-encoded-ca-cert
: The base64-encoded CA certificate
Apply the Secret
kubectl apply -f cluster-secret.yaml
Verify the Secret
Check that the secret was created correctly:
kubectl get secret gitops-cluster-secret -n argocd -o yaml
Step 8: Verify Setup in Harness UI
Check Cluster Status
- Navigate to GitOps → Settings → Clusters in your Harness account
- You should see your cluster listed with a Healthy status
- The cluster should show as Connected
Troubleshoot if Not Healthy
If the cluster doesn't appear healthy:
- Verify Agent Status: Ensure all GitOps agent pods are running
- Check Service Account Annotations: Verify the client ID and tenant ID are correct
- Validate Federated Credentials: Ensure the issuer URL and subject match your configuration
- Review Secret Configuration: Check that the cluster secret has the correct endpoint and authentication details