Notice something off about this package? Help us keep the marketplace safe and trustworthy by reporting inappropriate content or behavior.
Report this packageA Crossplane Configuration package that simplifies the creation and management of Azure Workload Identity resources, enabling secure authentication between Kubernetes workloads and Azure services using OIDC federation.
This configuration automates the setup of Azure Workload Identity by creating and managing:
Before using this configuration, ensure you have:
provider-family-azure v2+provider-kubernetes v1+function-go-templating v0.10.0+function-auto-ready v0.5.0+If you haven't already installed Crossplane:
kubectl create namespace crossplane-system
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane \
--namespace crossplane-system \
crossplane-stable/crossplane \
--version 2.0.2
# Install providers
kubectl apply -f examples/providers.yaml
# Install functions
kubectl apply -f examples/functions.yaml
# Wait for providers to become healthy
kubectl wait --for=condition=Healthy \
--timeout=300s \
provider.pkg.crossplane.io --all
Create a secret with your Azure service principal credentials:
# Create a JSON file with your Azure credentials
cat > azure-credentials.json <<EOF
{
"clientId": "YOUR_CLIENT_ID",
"clientSecret": "YOUR_CLIENT_SECRET",
"subscriptionId": "YOUR_SUBSCRIPTION_ID",
"tenantId": "YOUR_TENANT_ID"
}
EOF
# Create the secret
kubectl create secret generic provider-azure \
--from-file=credential=./azure-credentials.json \
--namespace crossplane-system
# Clean up the credentials file
rm azure-credentials.json
Build and push the configuration package:
# Build the package
crossplane xpkg build
# Login to your registry (if using Upbound)
crossplane xpkg login
# Push the package
crossplane xpkg push -f *.xpkg livewyer-ops/crossplane-configuration-azure-workload-identity:v1.0.0
Or install directly from the registry:
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Configuration
metadata:
name: configuration-azure-workload-identity
spec:
package: xpkg.upbound.io/livewyer-ops/crossplane-configuration-azure-workload-identity:v1.0.0
EOF
Create a WorkloadIdentity resource with basic role assignments:
apiVersion: azure.livewyer.io/v1alpha1
kind: WorkloadIdentity
metadata:
name: my-app-identity
namespace: default
spec:
forProvider:
location: eastus
resourceGroupName: my-resource-group
serviceAccountName: my-app-sa
oidcIssuerURL: https://eastus.oic.prod-aks.azure.com/00000000-0000-0000-0000-000000000000/11111111-1111-1111-1111-111111111111/
roleAssignments:
- roleDefinitionName: Reader
scope: /subscriptions/YOUR_SUBSCRIPTION_ID
tags:
environment: production
app: my-app
apiVersion: azure.livewyer.io/v1alpha1
kind: WorkloadIdentity
metadata:
name: storage-operator
namespace: storage-system
spec:
forProvider:
location: westeurope
resourceGroupName: storage-rg
serviceAccountName: storage-operator-sa
serviceAccountTokenExpiration: 3600 # 1 hour
oidcIssuerURL: https://oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE
roleAssignments:
# Built-in role
- roleDefinitionName: "Storage Account Contributor"
scope: /subscriptions/SUB_ID/resourceGroups/storage-rg
description: "Manage storage accounts in storage-rg"
# Custom role with specific permissions
- roleDefinitionName: "CustomBlobReader"
scope: /subscriptions/SUB_ID
permissions:
- actions:
- "Microsoft.Storage/storageAccounts/listKeys/action"
- "Microsoft.Storage/storageAccounts/read"
dataActions:
- "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"
- "Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
notActions:
- "Microsoft.Storage/storageAccounts/delete"
tags:
team: platform
cost-center: engineering
Once the WorkloadIdentity is created, you can use the service account in your pods:
apiVersion: v1
kind: Pod
metadata:
name: my-app
namespace: default
spec:
serviceAccountName: my-app-sa # The service account created by WorkloadIdentity
containers:
- name: app
image: myapp:latest
env:
- name: AZURE_CLIENT_ID
valueFrom:
fieldRef:
fieldPath: metadata.annotations['azure.workload.identity/client-id']
| Field | Type | Required | Description |
|---|---|---|---|
forProvider.location | string | Yes | Azure region (e.g., eastus, westeurope) |
forProvider.resourceGroupName | string | Yes | Name of the Azure Resource Group |
forProvider.oidcIssuerURL | string | Yes | OIDC issuer URL of your Kubernetes cluster |
forProvider.roleAssignments | array | Yes | List of role assignments to grant |
forProvider.serviceAccountName | string | No | Kubernetes service account name to create |
forProvider.serviceAccountTokenExpiration | integer | No | Token expiration in seconds (default: 86400) |
forProvider.tags | object | No | Azure resource tags |
providerConfigRef | object | No | Reference to provider configuration |
| Field | Type | Description |
|---|---|---|
roleDefinitionName | string | Name of built-in or custom role |
scope | string | Azure resource scope for the assignment |
permissions | array | Permissions for custom role (optional) |
permissions[].actions | array | Allowed management operations |
permissions[].dataActions | array | Allowed data operations |
permissions[].notActions | array | Denied management operations |
permissions[].notDataActions | array | Denied data operations |
condition | string | Condition expression for conditional access |
conditionVersion | string | Version of condition syntax |
principalType | string | Type of principal (default: ServicePrincipal) |
kubectl get configurations
kubectl get xrds | grep workloadidentity
kubectl get compositions | grep workloadidentity
kubectl apply -f examples/workload-identity.yaml
# Check the composite resource
kubectl get workloadidentity -n test
# Check the managed resources
kubectl get managed -n test
# Check Azure resources
kubectl get userassignedidentity -n test
kubectl get federatedidentitycredential -n test
kubectl get roleassignment -n test
Using Azure CLI:
# List managed identities
az identity list --resource-group example-group
# Check role assignments
az role assignment list --assignee <PRINCIPAL_ID>
# Verify federated credentials
az identity federated-credential list \
--resource-group example-group \
--identity-name simple-example
Deploy a test pod to verify authentication:
apiVersion: v1
kind: Pod
metadata:
name: test-workload-identity
namespace: test
spec:
serviceAccountName: simple-example
containers:
- name: azure-cli
image: mcr.microsoft.com/azure-cli:latest
command: ["/bin/bash", "-c", "--"]
args:
- |
# Login using workload identity
az login --federated-token $(cat $AZURE_FEDERATED_TOKEN_FILE) \
--service-principal -u $AZURE_CLIENT_ID -t $AZURE_TENANT_ID
# Test access
az account show
az group list
# Get detailed status
kubectl describe workloadidentity -n test simple-example
# Check conditions
kubectl get workloadidentity -n test simple-example -o jsonpath='{.status.conditions}'
# Crossplane pod logs
kubectl logs -n crossplane-system deployment/crossplane -f
# Provider logs
kubectl logs -n crossplane-system -l pkg.crossplane.io/provider=provider-azure-managedidentity
az aks show --name <cluster> --resource-group <rg> --query "oidcIssuerProfile.issuerUrl"aws eks describe-cluster --name <cluster> --query "cluster.identity.oidc.issuer"# Get all events
kubectl get events -n test --sort-by='.lastTimestamp'
# Check composition pipeline
kubectl get composite -n test simple-example -o yaml | less
# View rendered resources
kubectl get managed -n test -o yaml | grep -A 5 "forProvider"
To remove a WorkloadIdentity and all its resources:
kubectl delete workloadidentity -n test simple-example
To uninstall the configuration:
kubectl delete configuration configuration-azure-workload-identity
We welcome contributions! Please see our Contributing Guide for details.
# Build the package locally
crossplane xpkg build
# Install for testing
kubectl apply -f apis/definition.yaml
kubectl apply -f apis/composition.yaml
# Test with examples
kubectl apply -f examples/workload-identity.yaml
This project is licensed under the MIT License - see the LICENSE file for details.