Skip to content

Commit 08e9a8f

Browse files
blog post: azure-native v3.8 (#15897)
* draft: blog post * meta image, updated text * Update content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md Co-authored-by: Guinevere Saenger <[email protected]> * Update content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md Co-authored-by: Guinevere Saenger <[email protected]> * Update content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md Co-authored-by: Guinevere Saenger <[email protected]> * Update content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md Co-authored-by: Guinevere Saenger <[email protected]> * Update content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md Co-authored-by: Guinevere Saenger <[email protected]> * minor updates * updated with a walkthrough * tweaks * move section --------- Co-authored-by: Guinevere Saenger <[email protected]>
1 parent e76f3ca commit 08e9a8f

File tree

2 files changed

+360
-0
lines changed
  • content/blog/azure-native-defaultazurecredential-and-private-cloud

2 files changed

+360
-0
lines changed
Lines changed: 360 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,360 @@
1+
---
2+
title: "Azure Native 3.8: Unified Credentials and Private Clouds"
3+
4+
# The date represents the post's publish date, and by default corresponds with
5+
# the date and time this file was generated. Dates are used for display and
6+
# ordering purposes only; they have no effect on whether or when a post is
7+
# published. To influence the ordering of posts published on the same date, use
8+
# the time portion of the date value; posts are sorted in descending order by
9+
# date/time.
10+
date: 2025-09-04T12:00:00-07:00
11+
12+
# The draft setting determines whether a post is published. Set it to true if
13+
# you want to be able to merge the post without publishing it.
14+
draft: false
15+
16+
# Use the meta_desc property to provide a brief summary (one or two sentences)
17+
# of the content of the post, which is useful for targeting search results or
18+
# social-media previews. This field is required or the build will fail the
19+
# linter test. Max length is 160 characters.
20+
meta_desc: |
21+
Pulumi Azure Native v3.8 delivers new credential modes (based on DefaultAzureCredential)
22+
and private cloud support (based on ARM_METADATA_HOSTNAME).
23+
24+
# The meta_image appears in social-media previews and on the blog home page. A
25+
# placeholder image representing the recommended format, dimensions and aspect
26+
# ratio has been provided for you.
27+
meta_image: meta.png
28+
29+
# At least one author is required. The values in this list correspond with the
30+
# `id` properties of the team member files at /data/team/team. Create a file for
31+
# yourself if you don't already have one.
32+
authors:
33+
- eron-wright
34+
35+
# At least one tag is required. Lowercase, hyphen-delimited is recommended.
36+
tags:
37+
- azure-native
38+
- azure
39+
- features
40+
- releases
41+
42+
# The social copy used to promote this post on Twitter and Linkedin. These
43+
# properties do not actually create the post and have no effect on the
44+
# generated blog page. They are here strictly for reference.
45+
46+
# Here are some examples of posts we have made in the past for inspiration:
47+
# https://www.linkedin.com/feed/update/urn:li:activity:7171191945841561601
48+
# https://www.linkedin.com/feed/update/urn:li:activity:7169021002394296320
49+
# https://www.linkedin.com/feed/update/urn:li:activity:7155606616455737345
50+
# https://twitter.com/PulumiCorp/status/1763265391042654623
51+
# https://twitter.com/PulumiCorp/status/1762900472489185492
52+
# https://twitter.com/PulumiCorp/status/1755637618631405655
53+
54+
social:
55+
twitter:
56+
linkedin:
57+
58+
---
59+
60+
Today we're excited to announce Azure Native Provider v3.8, featuring several enhancements that simplify authentication
61+
and extend support to private Azure environments. These updates make it easier than ever to manage Azure infrastructure
62+
using credentials provided by the hosting environment, such as in Azure Kubernetes Service (AKS), Azure VM, and Azure Cloud Shell.
63+
64+
<!--more-->
65+
66+
## Simplified Authentication Across Environments
67+
68+
The highlight of this release is a new authentication mode based on [DefaultAzureCredential][doc1],
69+
a feature of the Azure SDK that unifies authentication-related settings across deployment environments.
70+
71+
[doc1]: https://learn.microsoft.com/en-us/azure/developer/go/sdk/authentication/credential-chains#defaultazurecredential-overview
72+
73+
### What's New
74+
75+
`DefaultAzureCredential` automatically discovers and uses the best available authentication method for your environment,
76+
eliminating the need for an environment-specific configuration. It follows the Azure SDK's standard credential chain:
77+
78+
| Order | Credential | Description |
79+
|-------|---------------------------|------------------------------------------------------------------------------------------------------------------|
80+
| 1 | [Environment][o1] | Reads environment variables (e.g., `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`) to authenticate as a service principal. |
81+
| 2 | [Workload Identity][o2] | For programs run on an Azure Kubernetes Service (AKS) cluster. |
82+
| 3 | [Managed Identity][o3] | For programs deployed to an Azure compute resource (e.g., Azure Virtual Machines) or App hosting platform. |
83+
| 4 | [Azure CLI][o4] | For local development using Azure CLI's `az login` command. |
84+
| 5 | [Azure Developer CLI][o5] | For local development using Azure Developer CLI's `azd auth login` command. |
85+
86+
[o1]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential
87+
[o2]: https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview?tabs=go
88+
[o3]: https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview
89+
[o4]: https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest
90+
[o5]: https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview?tabs=windows
91+
92+
### Real-World Benefits
93+
94+
This means your Pulumi programs can now run seamlessly across:
95+
96+
- Local development machines using Azure CLI credentials
97+
- CI/CD pipelines with service principals via environment variables
98+
- Azure Kubernetes Service with Workload Identity
99+
- Azure VMs and App Services with Managed Identity
100+
101+
All without changing a single line of configuration code.
102+
103+
### Getting Started
104+
105+
Enable DefaultAzureCredential using Pulumi configuration:
106+
107+
```bash
108+
pulumi config set azure-native:useDefaultAzureCredential true
109+
pulumi config set azure-native:subscriptionId <your-subscription-id>
110+
```
111+
112+
Note that `subscriptionId` is a required configuration setting in this (and most) authentication modes; it ensures your resources are deployed to the correct Azure subscription.
113+
114+
## Private Azure Cloud Support
115+
116+
This release brings improved support for [Azure private clouds][docprivatecloud].
117+
A private cloud is a dedicated cloud computing environment used by a single organization.
118+
119+
The provider can now automatically discover, and configure itself for, any Azure cloud based on
120+
the `ARM_METADATA_HOSTNAME` environment variable. Note that this takes precedence over the `ARM_ENVIRONMENT` variable.
121+
122+
[docprivatecloud]: https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-a-private-cloud
123+
124+
### How To Use
125+
126+
The provider can query the Azure metadata service to automatically configure itself for your specific Azure environment:
127+
128+
```bash
129+
# Using environment variable
130+
export ARM_METADATA_HOSTNAME=management.azure.example
131+
132+
# Or via Pulumi configuration
133+
pulumi config set azure-native:metadataHost management.azure.example
134+
```
135+
136+
The provider expects the `2022-09-01` metadata schema, which resembles:
137+
138+
```json
139+
{
140+
"authentication": {
141+
"loginEndpoint": "https://login.microsoftonline.com",
142+
"audiences": [
143+
"https://management.core.windows.net/",
144+
"https://management.azure.com/"
145+
]
146+
},
147+
"name": "AzureCloud",
148+
"suffixes": {
149+
"keyVaultDns": "vault.azure.net",
150+
"storage": "core.windows.net"
151+
},
152+
"resourceManager": "https://management.azure.com/",
153+
"microsoftGraphResourceId": "https://graph.microsoft.com/"
154+
}
155+
```
156+
157+
The provider automatically retrieves the correct endpoints for authentication, resource management, and other services.
158+
159+
## Disabling Instance Discovery
160+
161+
Also in this release is a new setting, `disableInstanceDiscovery`, to determine whether the provider requests
162+
Microsoft Entra instance metadata from the login endpoint (https://login.microsoftonline.com) before authenticating.
163+
This setting is for Pulumi programs authenticating in disconnected clouds or private clouds.
164+
165+
Setting `disableInstanceDiscovery` to `true` will completely disable both instance discovery and authority validation.
166+
Please ensure that the configured authority host is valid and trustworthy.
167+
168+
### How To Use
169+
170+
The provider can be configured to disable instance discovery:
171+
172+
```bash
173+
# Using environment variable
174+
export ARM_DISABLE_INSTANCE_DISCOVERY=true
175+
176+
# Or via Pulumi configuration
177+
pulumi config set azure-native:disableInstanceDiscovery true
178+
```
179+
180+
## Authentication in AKS with Workload Identity
181+
182+
For programs run in a pod on an Azure Kubernetes Service (AKS) cluster, DefaultAzureCredential automatically uses the
183+
workload identity of the pod's service account. This workload identity could then be granted roles in Azure to deploy stack resources.
184+
185+
{{% notes type="info" %}}
186+
187+
Ensure that the application pods using workload identity include the label `azure.workload.identity/use: "true"` in the pod spec.
188+
189+
{{% /notes %}}
190+
191+
### Walkthough
192+
193+
Let's use [Pulumi Kubernetes Operator (PKO)][pko1] to demonstrate a use case where you'd run Pulumi deployment operations in a pod
194+
and could benefit from workload identity.
195+
196+
The operator allocates a dedicated pod for each Pulumi stack under its management, to serve as the execution environment for stack operations.
197+
Each stack may use the same or a different service account. With AKS, that service account has a _workload identity_ that providers
198+
may use to authenticate to Azure cloud and even to Pulumi cloud.
199+
200+
[pko1]: https://www.pulumi.com/docs/iac/using-pulumi/continuous-delivery/pulumi-kubernetes-operator/
201+
202+
#### Create an AKS Cluster
203+
204+
Please follow the steps in ["Deploy and configure workload identity on an Azure Kubernetes Service (AKS) cluster"][aks1]
205+
to create an AKS cluster, managed identity, and Kubernetes service account. Those steps are:
206+
207+
1. [Create an AKS cluster](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-an-aks-cluster)
208+
2. [Retrieve the OIDC issuer URL](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#retrieve-the-oidc-issuer-url)
209+
3. [Create a managed identity](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-a-managed-identity)
210+
4. [Create a Kubernetes service account](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-a-kubernetes-service-account)
211+
5. [Create the federated identity credential](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-the-federated-identity-credential)
212+
213+
You now have an Azure managed identity and associated Kubernetes service account that DefaultAzureCredential can use to authenticate to Azure cloud.
214+
215+
Take note of the `clientId` that represents the managed identity:
216+
217+
```shell
218+
az identity show --name "${USER_ASSIGNED_IDENTITY_NAME}" --resource-group "${RESOURCE_GROUP}" --query clientId
219+
"c2bbe0f5-6349-480a-9f6f-3a5cb3e4ecf9"
220+
```
221+
222+
[aks1]: https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster
223+
224+
#### Install the Pulumi Kubernetes Operator
225+
226+
Install the operator into the `pulumi-kubernetes-operator` namespace:
227+
228+
```shell
229+
kubectl apply -f https://raw.githubusercontent.com/pulumi/pulumi-kubernetes-operator/refs/tags/v2.0.0/deploy/quickstart/install.yaml
230+
```
231+
232+
#### Configure a Pulumi Cloud Access Token
233+
234+
By default, the operator uses Pulumi Cloud as the state backend for your stacks.
235+
Please create a `Secret` containing a Pulumi access token to be used to authenticate to Pulumi Cloud. Follow [these instructions][doctokens] to create a personal, organization, or team access token.
236+
237+
```shell
238+
kubectl create secret generic -n ${SERVICE_ACCOUNT_NAMESPACE} pulumi-api-secret --from-literal=accessToken=${PULUMI_ACCESS_TOKEN}
239+
```
240+
241+
[doctokens]: https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/
242+
243+
#### Update the Kubernetes Service Account
244+
245+
To use the service account that was created earlier, we need to grant it the `system:auth-delegator` role:
246+
247+
```shell
248+
cat <<EOF | kubectl apply -f -
249+
apiVersion: rbac.authorization.k8s.io/v1
250+
kind: ClusterRoleBinding
251+
metadata:
252+
name: "${SERVICE_ACCOUNT_NAMESPACE}-${SERVICE_ACCOUNT_NAME}:system:auth-delegator"
253+
roleRef:
254+
apiGroup: rbac.authorization.k8s.io
255+
kind: ClusterRole
256+
name: system:auth-delegator
257+
subjects:
258+
- kind: ServiceAccount
259+
name: "${SERVICE_ACCOUNT_NAME}"
260+
namespace: "${SERVICE_ACCOUNT_NAMESPACE}"
261+
EOF
262+
```
263+
264+
#### Define an Example Program
265+
266+
Let's define a simple Pulumi program that uses Azure Native 3.8 and calls the ["getClientConfig"][azdoc1] function to
267+
access the current identity of the provider.
268+
269+
[azdoc1]: https://www.pulumi.com/registry/packages/azure-native/api-docs/authorization/getclientconfig/
270+
271+
```shell
272+
cat <<"EOF" | kubectl apply -n ${SERVICE_ACCOUNT_NAMESPACE} -f -
273+
apiVersion: pulumi.com/v1
274+
kind: Program
275+
metadata:
276+
name: sample-workload-identity
277+
program:
278+
variables:
279+
clientConfig:
280+
fn::invoke:
281+
function: azure-native:authorization:getClientConfig
282+
clientToken:
283+
fn::secret:
284+
fn::invoke:
285+
function: azure-native:authorization:getClientToken
286+
outputs:
287+
clientConfig: ${clientConfig}
288+
clientToken: ${clientToken}
289+
EOF
290+
```
291+
292+
#### Run the Program using Workload Identity
293+
294+
Create a Stack object to run the Pulumi program using your service account and with `azure-native:useDefaultAzureCredential` enabled.
295+
296+
```shell
297+
cat <<EOF | kubectl apply -f -
298+
apiVersion: pulumi.com/v1
299+
kind: Stack
300+
metadata:
301+
name: sample-workload-identity
302+
namespace: "${SERVICE_ACCOUNT_NAMESPACE}"
303+
spec:
304+
programRef:
305+
name: sample-workload-identity
306+
stack: sample-workload-identity
307+
envRefs:
308+
PULUMI_ACCESS_TOKEN:
309+
type: Secret
310+
secret:
311+
name: pulumi-api-secret
312+
key: accessToken
313+
serviceAccountName: "${SERVICE_ACCOUNT_NAME}"
314+
config:
315+
azure-native:useDefaultAzureCredential: "true"
316+
azure-native:subscriptionId: "${SUBSCRIPTION}"
317+
workspaceTemplate:
318+
spec:
319+
podTemplate:
320+
metadata:
321+
labels:
322+
azure.workload.identity/use: "true"
323+
EOF
324+
```
325+
326+
Checking the stack outputs, we see a `clientId` matching that of the managed identity!
327+
328+
```shell
329+
kubectl get stack/sample-workload-identity -oyaml
330+
```
331+
332+
```yaml
333+
apiVersion: pulumi.com/v1
334+
kind: Stack
335+
metadata:
336+
name: sample-workload-identity
337+
namespace: default
338+
status:
339+
conditions:
340+
- lastTransitionTime: "2025-09-04T23:32:11Z"
341+
message: the stack has been processed and is up to date
342+
reason: ProcessingCompleted
343+
status: "True"
344+
type: Ready
345+
outputs:
346+
clientConfig:
347+
clientId: c2bbe0f5-6349-480a-9f6f-3a5cb3e4ecf9
348+
objectId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
349+
subscriptionId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
350+
tenantId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
351+
clientToken: '[secret]'
352+
```
353+
354+
## Conclusion
355+
356+
Azure Native Provider v3.8 represents our commitment to making Azure infrastructure management work seamlessly across all deployment scenarios,
357+
from local development to production, from public cloud to private cloud.
358+
359+
Have questions or feedback? [Open an issue on GitHub](https://github.com/pulumi/pulumi-azure-native/issues)
360+
or join the conversation in our [Community Slack](https://slack.pulumi.com/) (#azure channel).
582 KB
Loading

0 commit comments

Comments
 (0)