Using Azure Kubernetes Workload Identity for Humanitec Terraform Container Runner
Following recommended practice, Kubernets workloads should authenticate to the surrounding cloud infrastructure using workload identities. In Azure and for Azure Kubernetes Service (AKS), this is supported by Azure Managed Identities being projected to Kubernetes service accounts.
The Humanitec Plattform Orchestrator provides the Terraform and OpenTofu Container Runner Drivers that allow to apply Terraform and OpenTofu code from within your infrastructure, running for instance on a AKS cluster.
This post shows the configuration necessary for configuring the Terraform Container Runner to use Azure Workload Identity.
| All IDs have been redacted. |
First, create the service account and roles and role bindings (see
Configure
AKS for the Container runner). Create the namespace humanitec-runner if it doesn’t already exist. Its name is predetermined and
it is created automatically by the Humanitec orchestrator.
For the service account:
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
azure.workload.identity/client-id: "00000000-0000-0000-0000-000000000000"
name: humanitec-runner
namespace: humanitec-runner
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: humanitec-runner
name: humanitec-runner
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create", "get", "delete", "list", "update", "deletecollection"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create", "get", "list", "update", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: humanitec-runner
namespace: humanitec-runner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: humanitec-runner
subjects:
- kind: ServiceAccount
name: humanitec-runner
namespace: humanitec-runnerSimilarly, for the Azure managed identity to be used by the driver:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: container-driver-role
namespace: humanitec-runner
rules:
- apiGroups: ["batch"]
resources: ["jobs"]
verbs : ["create", "delete"]
- apiGroups: [""]
resources: ["configmaps","secrets"]
verbs : ["create", "delete", "deletecollection","get"]
- apiGroups: [""]
resources: ["pods","events"]
verbs : ["list"]
- apiGroups: [""]
resources: ["pods/log"]
verbs : ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: container-driver-deploy-access
namespace: humanitec-runner
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: container-driver-role
subjects:
- kind: User
name: 00000000-0000-0000-0000-000000000000 # The object ID of the Humanitec driver's Azure managed identity
apiGroup: rbac.authorization.k8s.ioFor each Humanitec resource type, a resource definition is needed, specifying which driver type should handle that resource type.
In the context of this post, this is the humanitec/terraform-container-runner driver type. In each resource definition, the
runner’s pod specification needs to be extended to specify that Azure Workload Identity should be used:
driver_inputs = {
runner = {
pod_template = <<EOT
metadata:
labels:
azure.workload.identity/use: "true"
EOT
}
credentials_config = {
"variables" = {
"oidc_token" = "oidc_token"
}
}Finally, make sure that the configuration of the azurerm Terraform provider used in the root module referenced by the Humanitec
resource definition specifies that AKS workload identity is to be used:
provider "azurerm" {
features {}
use_aks_workload_identity = true
use_cli = false
subscription_id = var.subscription_id
}Note that the Humanitec Terraform container runner does not include the az command line interface. Also, in general, the Azure
subscription needs to specified in the provider configuration, unless it is set magically as an environment variable.
Happy platforming!