Skip to content

Commit 02d3da0

Browse files
Merge pull request #249231 from scottaddie/scottaddie/workload-identity
Add code samples to Azure Identity SDK section
2 parents 3eb9ee9 + bd81961 commit 02d3da0

File tree

1 file changed

+175
-22
lines changed

1 file changed

+175
-22
lines changed

articles/aks/workload-identity-overview.md

Lines changed: 175 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
---
2-
title: Use an Azure AD workload identities on Azure Kubernetes Service (AKS)
2+
title: Use an Azure AD workload identity on Azure Kubernetes Service (AKS)
33
description: Learn about Azure Active Directory workload identity for Azure Kubernetes Service (AKS) and how to migrate your application to authenticate using this identity.
44
ms.topic: article
55
ms.custom: build-2023
6-
ms.date: 08/18/2023
6+
ms.date: 08/24/2023
77
---
88

99
# Use Azure AD workload identity with Azure Kubernetes Service (AKS)
@@ -29,36 +29,189 @@ In the Azure Identity client libraries, choose one of the following approaches:
2929
- Create a `ChainedTokenCredential` instance that includes `WorkloadIdentityCredential`.
3030
- Use `WorkloadIdentityCredential` directly.
3131

32-
The following table provides the **minimum** package version required for each language's client library.
32+
The following table provides the **minimum** package version required for each language ecosystem's client library.
3333

34-
| Language | Library | Minimum Version | Example |
35-
|------------|------------------------------------------------------------------------------------------------------------------|-----------------|-----------------------------------------------------------------------------------------------------------------------------------|
36-
| .NET | [Azure.Identity](/dotnet/api/overview/azure/identity-readme) | 1.9.0 | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/dotnet) |
37-
| C++ | [azure-identity-cpp](https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md) | 1.6.0-beta.1 | [Link](https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/samples/workload_identity_credential.cpp) |
38-
| Go | [azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) | 1.3.0 | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/go) |
39-
| Java | [azure-identity](/java/api/overview/azure/identity-readme) | 1.9.0 | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/java) |
40-
| JavaScript | [@azure/identity](/javascript/api/overview/azure/identity-readme) | 3.2.0 | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/node) |
41-
| Python | [azure-identity](/python/api/overview/azure/identity-readme) | 1.13.0 | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/python) |
34+
| Ecosystem | Library | Minimum version |
35+
|-----------|------------------------------------------------------------------------------------------------------------------|-----------------|
36+
| .NET | [Azure.Identity](/dotnet/api/overview/azure/identity-readme) | 1.9.0 |
37+
| C++ | [azure-identity-cpp](https://github.com/Azure/azure-sdk-for-cpp/blob/main/sdk/identity/azure-identity/README.md) | 1.6.0-beta.1 |
38+
| Go | [azidentity](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity) | 1.3.0 |
39+
| Java | [azure-identity](/java/api/overview/azure/identity-readme) | 1.9.0 |
40+
| Node.js | [@azure/identity](/javascript/api/overview/azure/identity-readme) | 3.2.0 |
41+
| Python | [azure-identity](/python/api/overview/azure/identity-readme) | 1.13.0 |
4242

4343
† In the C++ library, `WorkloadIdentityCredential` isn't part of the `DefaultAzureCredential` authentication flow.
4444

45+
In the following code samples, the credential type will use the environment variables injected by the Azure Workload Identity mutating webhook to authenticate with Azure Key Vault.
46+
47+
## [.NET](#tab/dotnet)
48+
49+
```csharp
50+
using Azure.Identity;
51+
using Azure.Security.KeyVault.Secrets;
52+
53+
string keyVaultUrl = Environment.GetEnvironmentVariable("KEYVAULT_URL");
54+
string secretName = Environment.GetEnvironmentVariable("SECRET_NAME");
55+
56+
var client = new SecretClient(
57+
new Uri(keyVaultUrl),
58+
new DefaultAzureCredential());
59+
60+
KeyVaultSecret secret = await client.GetSecretAsync(secretName);
61+
```
62+
63+
## [C++](#tab/cpp)
64+
65+
```cpp
66+
#include <cstdlib>
67+
#include <azure/identity.hpp>
68+
#include <azure/keyvault/secrets/secret_client.hpp>
69+
70+
using namespace Azure::Identity;
71+
using namespace Azure::Security::KeyVault::Secrets;
72+
73+
// * AZURE_TENANT_ID: Tenant ID for the Azure account.
74+
// * AZURE_CLIENT_ID: The client ID to authenticate the request.
75+
std::string GetTenantId() { return std::getenv("AZURE_TENANT_ID"); }
76+
std::string GetClientId() { return std::getenv("AZURE_CLIENT_ID"); }
77+
std::string GetTokenFilePath() { return std::getenv("AZURE_FEDERATED_TOKEN_FILE"); }
78+
79+
int main()
80+
{
81+
const char* keyVaultUrl = std::getenv("KEYVAULT_URL");
82+
const char* secretName = std::getenv("SECRET_NAME");
83+
auto credential = std::make_shared<WorkloadIdentityCredential>(
84+
GetTenantId(), GetClientId(), GetTokenFilePath());
85+
86+
SecretClient client(keyVaultUrl, credential);
87+
Secret secret = client.GetSecret(secretName).Value;
88+
89+
return 0;
90+
}
91+
```
92+
93+
## [Go](#tab/go)
94+
95+
```go
96+
package main
97+
98+
import (
99+
"context"
100+
"os"
101+
102+
"github.com/Azure/azure-sdk-for-go/sdk/azidentity"
103+
"github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azsecrets"
104+
"k8s.io/klog/v2"
105+
)
106+
107+
func main() {
108+
keyVaultUrl := os.Getenv("KEYVAULT_URL")
109+
secretName := os.Getenv("SECRET_NAME")
110+
111+
credential, err := azidentity.NewDefaultAzureCredential(nil)
112+
if err != nil {
113+
klog.Fatal(err)
114+
}
115+
116+
client, err := azsecrets.NewClient(keyVaultUrl, credential, nil)
117+
if err != nil {
118+
klog.Fatal(err)
119+
}
120+
121+
secret, err := client.GetSecret(context.Background(), secretName, "", nil)
122+
if err != nil {
123+
klog.ErrorS(err, "failed to get secret", "keyvault", keyVaultUrl, "secretName", secretName)
124+
os.Exit(1)
125+
}
126+
}
127+
```
128+
129+
## [Java](#tab/java)
130+
131+
```java
132+
import java.util.Map;
133+
134+
import com.azure.security.keyvault.secrets.SecretClient;
135+
import com.azure.security.keyvault.secrets.SecretClientBuilder;
136+
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;
137+
import com.azure.identity.DefaultAzureCredentialBuilder;
138+
import com.azure.identity.DefaultAzureCredential;
139+
140+
public class App {
141+
public static void main(String[] args) {
142+
Map<String, String> env = System.getenv();
143+
String keyVaultUrl = env.get("KEYVAULT_URL");
144+
String secretName = env.get("SECRET_NAME");
145+
146+
SecretClient client = new SecretClientBuilder()
147+
.vaultUrl(keyVaultUrl)
148+
.credential(new DefaultAzureCredentialBuilder().build())
149+
.buildClient();
150+
KeyVaultSecret secret = client.getSecret(secretName);
151+
}
152+
}
153+
```
154+
155+
## [Node.js](#tab/javascript)
156+
157+
```nodejs
158+
import { DefaultAzureCredential } from "@azure/identity";
159+
import { SecretClient } from "@azure/keyvault-secrets";
160+
161+
const main = async () => {
162+
const keyVaultUrl = process.env["KEYVAULT_URL"];
163+
const secretName = process.env["SECRET_NAME"];
164+
165+
const credential = new DefaultAzureCredential();
166+
const client = new SecretClient(keyVaultUrl, credential);
167+
168+
const secret = await client.getSecret(secretName);
169+
}
170+
171+
main().catch((error) => {
172+
console.error("An error occurred:", error);
173+
process.exit(1);
174+
});
175+
```
176+
177+
## [Python](#tab/python)
178+
179+
```python
180+
import os
181+
182+
from azure.keyvault.secrets import SecretClient
183+
from azure.identity import DefaultAzureCredential
184+
185+
def main():
186+
keyvault_url = os.getenv('KEYVAULT_URL', '')
187+
secret_name = os.getenv('SECRET_NAME', '')
188+
189+
client = SecretClient(vault_url=keyvault_url, credential=DefaultAzureCredential())
190+
secret = client.get_secret(secret_name)
191+
192+
if __name__ == '__main__':
193+
main()
194+
```
195+
196+
---
197+
45198
## Microsoft Authentication Library (MSAL)
46199

47-
The following client libraries are the **minimum** version required
200+
The following client libraries are the **minimum** version required.
48201

49-
| Language | Library | Image | Example | Has Windows |
202+
| Ecosystem | Library | Image | Example | Has Windows |
50203
|-----------|-----------|----------|----------|----------|
51-
| .NET | [microsoft-authentication-library-for-dotnet](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) | ghcr.io/azure/azure-workload-identity/msal-net:latest | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-net/akvdotnet) | Yes |
52-
| Go | [microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | ghcr.io/azure/azure-workload-identity/msal-go:latest | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-go) | Yes |
53-
| Java | [microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java) | ghcr.io/azure/azure-workload-identity/msal-java:latest | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-java) | No |
54-
| JavaScript | [microsoft-authentication-library-for-js](https://github.com/AzureAD/microsoft-authentication-library-for-js) | ghcr.io/azure/azure-workload-identity/msal-node:latest | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-node) | No |
55-
| Python | [microsoft-authentication-library-for-python](https://github.com/AzureAD/microsoft-authentication-library-for-python) | ghcr.io/azure/azure-workload-identity/msal-python:latest | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-python) | No |
204+
| .NET | [microsoft-authentication-library-for-dotnet](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) | `ghcr.io/azure/azure-workload-identity/msal-net:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-net/akvdotnet) | Yes |
205+
| Go | [microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | `ghcr.io/azure/azure-workload-identity/msal-go:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-go) | Yes |
206+
| Java | [microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java) | `ghcr.io/azure/azure-workload-identity/msal-java:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-java) | No |
207+
| JavaScript | [microsoft-authentication-library-for-js](https://github.com/AzureAD/microsoft-authentication-library-for-js) | `ghcr.io/azure/azure-workload-identity/msal-node:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-node) | No |
208+
| Python | [microsoft-authentication-library-for-python](https://github.com/AzureAD/microsoft-authentication-library-for-python) | `ghcr.io/azure/azure-workload-identity/msal-python:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-python) | No |
56209

57210
## Limitations
58211

59212
- You can only have 20 federated identity credentials per managed identity.
60213
- It takes a few seconds for the federated identity credential to be propagated after being initially added.
61-
- [Virtual nodes][aks-virtual-nodes] add on, based on the open source project [Virtual Kubelet][virtual-kubelet], is not supported.
214+
- [Virtual nodes][aks-virtual-nodes] add on, based on the open source project [Virtual Kubelet][virtual-kubelet], isn't supported.
62215

63216
## How it works
64217

@@ -96,7 +249,7 @@ If you've used [Azure AD pod-managed identity][use-azure-ad-pod-identity], think
96249

97250
### Service account annotations
98251

99-
All annotations are optional. If the annotation is not specified, the default value will be used.
252+
All annotations are optional. If the annotation isn't specified, the default value will be used.
100253

101254
|Annotation |Description |Default |
102255
|-----------|------------|--------|
@@ -115,12 +268,12 @@ All annotations are optional. If the annotation is not specified, the default va
115268

116269
### Pod annotations
117270

118-
All annotations are optional. If the annotation is not specified, the default value will be used.
271+
All annotations are optional. If the annotation isn't specified, the default value will be used.
119272

120273
|Annotation |Description |Default |
121274
|-----------|------------|--------|
122275
|`azure.workload.identity/service-account-token-expiration` |Represents the `expirationSeconds` field for the projected service account token. It's an optional field that you configure to prevent any downtime caused by errors during service account token refresh. Kubernetes service account token expiry isn't correlated with Azure AD tokens. Azure AD tokens expire in 24 hours after they're issued. <sup>1</sup> |3600<br> Supported range is 3600-86400. |
123-
|`azure.workload.identity/skip-containers` |Represents a semi-colon-separated list of containers to skip adding projected service account token volume. For example `container1;container2`. |By default, the projected service account token volume is added to all containers if the service account is labeled with `azure.workload.identity/use: true`. |
276+
|`azure.workload.identity/skip-containers` |Represents a semi-colon-separated list of containers to skip adding projected service account token volume. For example, `container1;container2`. |By default, the projected service account token volume is added to all containers if the service account is labeled with `azure.workload.identity/use: true`. |
124277
|`azure.workload.identity/inject-proxy-sidecar` |Injects a proxy init container and proxy sidecar into the pod. The proxy sidecar is used to intercept token requests to IMDS and acquire an Azure AD token on behalf of the user with federated identity credential. |true |
125278
|`azure.workload.identity/proxy-sidecar-port` |Represents the port of the proxy sidecar. |8000 |
126279

0 commit comments

Comments
 (0)