Popis problému: Máme k dispozici Kubernetes Cluster a v něm běžící aplikaci u které chceme, aby měla přístup k vybraným službám na cloudu (např. Azure Key Vault). Jak nejlépe zajistit autorizaci, propojení a vzájemnou konfiguraci?
Secrets a jejich správa byla vždy výzvou. Ve světě Azure se svatý grál nazývá Service Principal (SP) známý také jako „App Registration“ nebo „Application“, v poslední době také alternativa „Managed Identity“ (MI). SP i MI jsou obvykle spojována s přiřazením práv pro přístup ke službám v Azure.
V tomto případě je velkým omezením doba expirace secretu u SP, což znamená, že se musí pravidelně nahrazovat novým. Taková rotace přináší nezanedbatelnou složitost do infrastruktury a každodenní údržby. Při porovnání s AWS IAM, kde pro uživatele obdobně generujeme credentials jako je „AWS Secret Access Key“, zjistíme že jejich credentials jsou věčné a není je nutné rotovat. Hodnocení takového přístupu nechám na čtenáři.
Jak to vyřešit?
Managed Identity – je skvělá odpověď. Umožňuje přiřadit tuto identitu k určitým Azure službám a pomocí IAM rolí a přiřazení oprávnění řídit přístupová práva. To všechno bez využití tradičních generovaných hesel, automaticky a v principu passwordless.
Nevýhodou je, že Managed Identity nelze přiřadit k identitám mimo ekosystém Azure (např lokální vývoj). To stejné dlouho platilo i pro Kubernetes Cluster, nicméně právě funkcí Workload Identity, která využívá federovanou identitu, tento problém řešíme.
Konečně se dostáváme k původnímu tématu článku, využít Workload Identity, která nám nabízí vše, co potřebujeme: Na jedné straně máme Kubernetes Pod a jeho potřebu mít práva přistupovat do služeb Azure a na druhém Azure Service Principal nebo Managed Identity, jejíž práva chceme využívat.
V článku se zaměříme na používání Workload Identity společně s clusterem Azure AKS, který poskytuje nejběžnější případ použití. Jako Cloud identitu využijeme Managed Identity.
Jak to funguje?
V tomto scénáři přebírá Kubernetes Cluster roli vydavatele tokenů. Generuje tokeny speciálně pro potřeby Kubernetes Service Account. Tyto tokeny lze nakonfigurovat tak, aby jim Azure AD aplikace nebo manažované identity důvěřovaly, a díky tomu má možnost Kubernetes Service Account přistupovat ke službám, ke kterým má vzdálená Azure identita přístup.
Předpoklady:
Azure Portal:
- vytvořená Resource Group: workload-identity
- práva pro přiřazování Azure rolí
Celý postup se dá shrnout do 4 kroků:
- Vytvoření Azure AD identity
- Service Principal nebo Managed Identity (na tento se zaměříme my)
- Nastavení AKS Clusteru
- Povolení OIDC and Workload Identity
- Vytvoření Kubernetes Service Account
- Vytvoření důvěry (vazby) mezi Kubernetes Service Accountem a Azure AD identitou
- Testování Workload Identity na zkušební aplikaci
- Založení testovacího Azure Key Vault
- Vytvoření aplikace – Kubernetes Deployment
- Nastavení práv Aplikace pro přístup do Azure Key Vault
- Ověření funkčnosti
Návod
1. Vytvoření identity Azure AD
V našem případě zvolíme metodu (b) Managed Identity, kterou si můžeme vytvořit použitím Azure CLI (příkazové řádky):
S využitím azure cli a příkazové řádky:
az identity create --name our_app_identity --resource-group workload-identity
a nebo přímo v Azure portálu:
Při vytvoření si poznamenejte hodnotu Client ID této identity. V případě příkazu je výstupem soubor ve formátu JSON obsahující hodnotu clientId. V portálu lze hodnotu nalézt v detailu spravované identity.
2. Nastavení AKS Clusteru
Druhým krokem je nastavení AKS clusteru, aby podporoval flagy oidc-issuer a Workload Identity. A následně uvnitř clusteru vytvoření Service Accountu, který bude reprezentovat Managed Identity, kterou jsme vytvořili v Azure.
a) Příprava AKS clusteru:
Vytvoření nového clusteru
az aks create --name WORKLOAD-IDENTITY --resource-group workload-identity --enable-oidc-issuer --enable-workload-identity
Upravení již existujícího clusteru
Pomocí Azure CLI:
az aks update --name WORKLOAD-IDENTITY --resource-group workload-identity --enable-oidc-issuer --enable-workload-identity
Pomocí Terraform:
resource "azurerm_resource_group" "west_europe" { name = "workload-identity" location = "West Europe" } resource "azurerm_kubernetes_cluster" "example" { name = "WORKLOAD-IDENTITY" location = azurerm_resource_group.west_europe.location resource_group_name = azurerm_resource_group.west_europe.name # přídáme parametry pro workload-identity a oidc-issuer workload_identity_enabled = true oidc_issuer_enabled = true # ostatní parametry byly vynechány pro stručnost }
b) Vytvoření Service Account uvnitř Kubernetes Clusteru
Nejprve je nutné se přihlásit do clusteru
V Azure portále vyhledejte AKS → Otevřete detail našeho clusteru WORKLOAD-IDENTITY → Connect → Spusťte příkazy v bash Cloudshell:
Vytvoření Service Account
Pro vytvoření Kubernetes Recource Service Account upravte příkaz níže, obsahující dvě vstupní hodnoty: TenantID a ClientId naší identity v Azure
export TENANT_ID="<nahrad-vlastnim-tenant-id>" #také známé jako directoryID lze získat https://portal.azure.com/#settings/directory export MANAGED_IDENTITY_CLIENT_ID="<nahrad-vlastnim-cliend-id>" # Výstup kroku 1 kubectl apply -f - <<EOF apiVersion: v1 kind: ServiceAccount metadata: annotations: azure.workload.identity/client-id: ${MANAGED_IDENTITY_CLIENT_ID} azure.workload.identity/tenant-id: ${TENANT_ID} labels: azure.workload.identity/use: "true" name: root-cz EOF
3. Vytvoření vazby mezi Azure Managed Identity a Kubernetes Service Account
export SERVICE_ACCOUNT_NAMESPACE="default" export SERVICE_ACCOUNT_NAME="root-cz" export AKS_CLUSTER_NAME="WORKLOAD-IDENTITY" export RESOURCE_GROUP="workload-identity" export USER_ASSIGNED_MANAGED_IDENTITY_NAME="our_app_identity" # Output the OIDC issuer URL SERVICE_ACCOUNT_ISSUER=`az aks show --resource-group "${RESOURCE_GROUP}" --name "${AKS_CLUSTER_NAME}" --query "oidcIssuerProfile.issuerUrl" -otsv` # Vytvoření federovaných přístupových údajů az identity federated-credential create \ --name "kubernetes-federated-identity-${SERVICE_ACCOUNT_NAMESPACE}-${SERVICE_ACCOUNT_NAME}" \ --identity-name „${USER_ASSIGNED_MANAGED_IDENTITY_NAME}" \ --resource-group "${RESOURCE_GROUP}" \ --issuer "${SERVICE_ACCOUNT_ISSUER}" \ --subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}"
4. Testování Workload Identity na zkušební aplikaci
a) Založení testovacího Azure Key Vault
export KEY_VAULT_NAME="workload-identity" #unique name # Create KeyVault az keyvault create --name "${KEY_VAULT_NAME}" --resource-group "workload-identity" --location "WestEurope" # Create a secret az keyvault secret set --vault-name "${KEY_VAULT_NAME}" --name "testPassword" --value "passw0rd"
b) Vytvoření aplikace – Kubernetes Deployment
kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: demo-app spec: replicas: 1 selector: matchLabels: app: demo-app template: metadata: labels: app: demo-app azure.workload.identity/use: "true" spec: serviceAccountName: root-cz containers: - name: demo-app image: python:3.9 command: ["sh", "-c"] args: - | pip install azure-identity azure-keyvault-secrets python -c ' from azure.identity import DefaultAzureCredential from azure.keyvault.secrets import SecretClient # Set the Azure Key Vault details vault_url = "https://workload-identity.vault.azure.net/" secret_name = "testPassword" # Create an instance of the DefaultAzureCredential class to authenticate credential = DefaultAzureCredential() # Create an instance of the SecretClient class secret_client = SecretClient(vault_url=vault_url, credential=credential) # Retrieve the secret value from Azure Key Vault secret_value = secret_client.get_secret(secret_name).value # Print the secret value print(f"The secret value for '{secret_name}' is: {secret_value}") ' workingDir: / EOF
Ve skriptu výše si povšimněte především:
- labelu
azure.workload.identity/use: "true"
ten právě označuje tento deployment jako využivající workload-identity. - dále pak associace deploymentu s dříve vytvořeným service-accountem root-cz:
serviceAccountName: root-cz
Následně jsou pak automaticky k podu přidané 4 ENV Variables:
AZURE_CLIENT_ID
AZURE_TENANT_ID
AZURE_FEDERATED_TOKEN_FILE
AZURE_AUTHORITY_HOST
ty obsahují hodnoty sloužící k přístupu do Azure. A právě hodnotu AZURE_FEDERATED_TOKEN_FILE
Workoad Identity pravidelně rotuje
c) Nastavení práv aplikace pro přístup do Azure Key Vault
Následuje poslední a nejdůležitější část tohoto tutoriálu. Důvod, proč toto cvičení děláme, a to samotné nastavení práv Managed Identity k přístupu do vytvořeného Azure Key Vault.
!Pro tento úkon jsou nezbytná práva přiřazování rolí v Azure AD
Pro přístup do Azure Key Vault jsou potřeba celkem dvě práva:
1. Azure Key Vault Reader role na vytvořený workload-identity
Key Vault:
Tato role umožňuje Managed Identity přístup k objektům Azure Key Vault (ne k samotné hodnotě).
2. Access policies – Get and List permissions na Secrets:
Tato permission umožňuje Managed Identity přístup k hodnotě uloženého secretu.
d) Ověření funkčnosti
Vše máme nastavené, deployment vytvořený a potřebujeme se podívat na jeho logy:
kubectl logs deployment/demo-ap
Pokud vidíte v logu tento řádek, gratuluji vám. Znamená to, že Kubernetes pod přistupuje k Azure Key Vault bez manuálně spravovaných přístupů, ale za použití Workload Identity.
The secret value for testPassword is: passw0rd
Workload Identity je skvělý nástroj, jak federovat identitu Azure na jiné aplikace a služby. V našem případě to byla aplikace v rámci spravovaného Kubernetes clusteru, nicméně nic nebrání využít ji například při běhu CI/CD jobů (Github Actions,…).
Alternativy
Kdo se problematikou federované identity v clusteru a Azure zabýval, jistě ví, že existuje zdánlivá alternativa Pod-identity. Ta skutečně umožňuje vytvoření obdobného nastavení. Je však nutno říct, že byla označena jako DEPRECATED, jejím následníkem je právě Workload Identity.
- Ne již úplně koncepční, ale spíše implementační alternativou je potom využití Azure Workload Identity CLI (azwi)
Odkazy
- azure.github.io/azure-workload-identity/docs/topics/azwi/serviceaccount-create.html
- learn.microsoft.com/en-us/azure/active-directory/workload-identities/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-rest
- github.com/Azure-Samples/aks-workload-identity
(Autorem obrázků je Ondřej Trojan.)