Table of contents
1 Azure Workload Identity 簡介
顧名思義,Azure Workload Identity 係一種用到 workload 黎做身份驗證既驗證方式。呢種驗證方式可以用喺 Azure K8s(AKS),令我地既 microservices 唔需要用到 password 都可以驗證到 Azure PaaS。
因為係 passwordless 既驗證方式,我地可以同舊時用到 password 既驗證方式(例如 Azure Service Principal 既 client secret)say goodbye。
1.1 好處
Passwordless 既驗證方式既好處有:
- 通常 password 既 expiry 都好長,所以因為唔再存在 password,就會冇咁容易 leak 到,從而避免被黑客攻擊。
- 作為用家,唔需要去考慮更新任何野。
- 如果係用 Azure Service Principal 既 client secret,一般都會有 expiry,咁我地就需要每隔一段時間去更新個 client secret,再更新所有 client secret 既 references。如果數量多,就會好難管理。
1.2 Service principal vs user-assigned managed identity
我地可以用 service principal(SPN)或者 user-assigned managed identity 去做 Workload Identity,但因為 SPN 比較好,所以我地應該揀用 SPN。
1.2.1 共通點
- User-assigned managed identity 係 SPN 既一種,所以兩者好相似。
- 我地可以喺 Azure PaaS 裡面新增 role assignments 黎授權兩者使用呢個 Azure PaaS。
- 兩者都可以新增 federated credential。
- 兩者都係支援最多
20
個 federated credentials。
1.2.2 差異
- SPN 一定會有一個關聯既 application object,但 user-assigned managed identity 就冇。
- User-assigned managed identity 唔係 multi-tenant(Azure tenant)。
- User-assigned managed identity 有一個反向授權既操作方式,可以畀我地喺個 managed identity 裡面新增 role assignments。呢個功能目前喺 preview 階段。
- 某啲 Azure regions 唔支援喺 user-assigned managed identity 裡面新增 federated credential。
2 準備功夫
- 我地既 AKS cluster 需要 enable OpenID Connect(OIDC)以及 Workload Identity。
- 我地需要有一個 K8s
ServiceAccount
。
- 我地既 K8s
Deployment
既 pod template:
- 需要有
azure.workload.identity/use: "true"
既 pod label,用黎 enable Workload Identity。
- 需要用
serviceAccountName
去 reference 個 K8s ServiceAccount
。
- 我地既 Azure SPN 需要新增一個 federated credential。
- Scenario:
Kubernetes accessing Azure resources
- Cluster issuer URL:OIDC issuer URL
- Namespace:我地個 K8s
Pod
所屬既 K8s Namespace
。
- Service account name:我地既 K8s
ServiceAccount
。
- Name:任何 value 都可以,日後冇需要 reference 呢個 value。
3 原理
- 我地運行一個 K8s
Pod
。
- AKS platform 會見到個 K8s
Pod
想用 Workload Identity 以及佢所 reference 既 K8s ServiceAccount
,然後生成一個 service account JWT token 喺 container 既 /var/run/secrets/azure/tokens/azure-identity-token
檔案作為 volume mount。
- 當我地既 K8s
Pod
裡面既 container 運行緊既 microservice 需要使用一個 Azure PaaS,就會用到 Azure Identity SDK 去做驗證。
- Azure Identity SDK 會喺上述檔案讀取 service account JWT token,然後透過 Azure Active Directory 去獲得一個 Azure AD token。
- Azure Active Directory 會透過 OpenID Connect 既方式,訪問 AKS cluster 既 OIDC issuer URL 去驗證 Azure AD token。
- 如果驗證成功,Azure Active Directory 會返回一個 Azure AD token。
- Azure SDK 會用呢個 Azure AD token 去驗證目標既 Azure PaaS。
- 如果驗證成功,呢個 K8s
Pod
裡面既 container 運行緊既 microservice 就可以操作目標既 Azure PaaS。
3.1 Azure Identity SDK
Azure Identity SDK 會根據以下既野去做驗證:
- 我地傳入 Azure SDK
TokenCredential
object 既 parameters,例如 Azure SPN client ID。
- Container 既 environment variables,包括:
AZURE_CLIENT_ID
(如果用 K8s ServiceAccount
既 azure.workload.identity/client-id
annotation 黎傳入 Azure SPN client ID,AKS platform 就會自動 set 呢個 environment variable)
AZURE_TENANT_ID
AZURE_FEDERATED_TOKEN_FILE
(默認係 /var/run/secrets/azure/tokens/azure-identity-token
)
- Container 既 service account JWT token 檔案(path 係
AZURE_FEDERATED_TOKEN_FILE
environment variable 既 value)。
4 Java 例子
4.1 Spring Boot/Cloud Azure 配置例子
我地可以直接用 Spring Boot、Spring Cloud Azure 既 auto-configuration 方式,令底層既 Azure SDK 幫我地用 Workload Identity。
呢個方法唔需要將 Azure SPN client ID 放入 K8s ServiceAccount
。
4.1.1 Azure SQL
重點既 Maven dependencies:
Type | Group ID | Artifact ID | Version |
---|
Dependency management | org.springframework.boot | spring-boot-starter-parent | 3.3.1 |
Dependency management | com.azure.spring | spring-cloud-azure-dependencies | 5.14.0 |
Dependency | com.azure | azure-identity | (Managed by Azure BOM) |
Dependency | org.springframework.boot | spring-boot-starter-data-jpa | (Managed by Spring BOM) |
Dependency | com.microsoft.sqlserver | mssql-jdbc | (Managed by Spring BOM) |
Spring Data JDBC 配置:
spring:
datasource:
url: "jdbc://sqlserver://xxxxxx.database.windows.net:1433;databaseName=xxxxxx;authentication=ActiveDirectoryDefault"
username: "<Azure SPN client ID>"
4.1.2 Azure Service Bus
重點既 Maven dependencies:
Type | Group ID | Artifact ID | Version |
---|
Dependency management | com.azure.spring | spring-cloud-azure-dependencies | 5.14.0 |
Dependency | com.azure | azure-identity | (Managed by Azure BOM) |
Dependency | com.azure.spring | spring-cloud-azure-stream-binder-servicebus | (Managed by Azure BOM) |
Spring Cloud Stream + ASB binder 配置:
1spring:
2 cloud:
3 function:
4 definition: demoConsume;demoProduce
5
6 stream:
7# default-binder: demoBinder1 # 因為我地有 2 個 binders,所以唔需要配置 default binder
8 output-bindings: demoProduce-out-0
9
10 binders:
11 demoBinder1:
12 type: servicebus
13 environment:
14 spring.cloud.azure.credential.managed-identity-enabled: true
15 spring.cloud.azure.credential.client-id: "<Azure SPN client ID>"
16 spring.cloud.azure.servicebus.namespace: xxxxxx
17 demoBinder2:
18 type: servicebus
19 environment:
20 spring.cloud.azure.credential.managed-identity-enabled: true
21 spring.cloud.azure.credential.client-id: "<Azure SPN client ID>"
22 spring.cloud.azure.servicebus.namespace: xxxxxx
23
24 bindings:
25 demoProduce-out-0:
26 destination: demo-topic-1
27 binder: demoBinder1
28 demoConsume-in-0:
29 destination: demo-topic-1
30 group: demo-subscription-1
31 binder: demoBinder2
32
33 servicebus:
34 bindings:
35 demoProduce-out-0:
36 producer:
37 entity-type: topic
38 demoConsume-in-0:
39 consumer:
40 entity-type: topic
41 auto-complete: true
4.2 Azure SDK for Java 例子
4.2.1 Azure Service Bus
重點既 Maven dependencies:
Type | Group ID | Artifact ID | Version |
---|
Dependency management | com.azure | azure-sdk-bom | 1.2.25 |
Dependency | com.azure | azure-identity | (Managed by Azure BOM) |
Dependency | com.azure | azure-messaging-servicebus | (Managed by Azure BOM) |
Java code:
1final TokenCredential credential = new DefaultAzureCredentialBuilder()
2 .workloadIdentityClientId("<Azure SPN client ID>")
3 .build();
4
5final ServiceBusSenderClient senderClient = new ServiceBusClientBuilder()
6 .fullyQualifiedNamespace("xxxxxx.servicebus.windows.net")
7 .credential(credential)
8 .sender()
9 .topicName("<ASB topic>")
10 .buildClient();
4.2.2 Azure Key Vault
重點既 Maven dependencies:
Type | Group ID | Artifact ID | Version |
---|
Dependency management | com.azure | azure-sdk-bom | 1.2.25 |
Dependency | com.azure | azure-identity | (Managed by Azure BOM) |
Dependency | com.azure | azure-security-keyvault-secrets | (Managed by Azure BOM) |
Java code:
1final TokenCredential credential = new DefaultAzureCredentialBuilder()
2 .workloadIdentityClientId("<Azure SPN client ID>")
3 .build();
4
5final SecretClient secretClient = new SecretClientBuilder()
6 .vaultUrl("https://xxxxxx.vault.azure.net")
7 .credential(credential)
8 .buildClient();
5 注意事項
注意事項 | 意味 |
---|
一個 Azure subscription 只支援最多 4000 個 role assignments | 如果一個 microservice 用一個或多個 SPNs 黎驗證 Azure PaaS,喺一間擁有過千 microservices 既大企業裡面,呢個會係一個需要考慮既因素。 |
一個 Azure SPN 只支援最多 20 個 federated credentials | 因為 federated credential 係 per K8s ServiceAccount ,如果多個 microservices 會用不同既 K8s ServiceAccount 而都係共用同一個 Azure SPN,就好易會達到上限。 |
6 參考資料