-
Notifications
You must be signed in to change notification settings - Fork 256
blog post: azure-native v3.8 #15897
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+360
−0
Merged
blog post: azure-native v3.8 #15897
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
96874ad
draft: blog post
EronWright e9dc7e0
meta image, updated text
EronWright fdab06b
Update content/blog/azure-native-defaultazurecredential-and-private-c…
EronWright f096c78
Update content/blog/azure-native-defaultazurecredential-and-private-c…
EronWright a40e334
Update content/blog/azure-native-defaultazurecredential-and-private-c…
EronWright 7f2dcd1
Update content/blog/azure-native-defaultazurecredential-and-private-c…
EronWright e55616e
Update content/blog/azure-native-defaultazurecredential-and-private-c…
EronWright 4e17c57
minor updates
EronWright 32797b8
updated with a walkthrough
EronWright 52236d5
tweaks
EronWright 54c506f
move section
EronWright File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
360 changes: 360 additions & 0 deletions
360
content/blog/azure-native-defaultazurecredential-and-private-cloud/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,360 @@ | ||
--- | ||
title: "Azure Native 3.8: Unified Credentials and Private Clouds" | ||
|
||
# The date represents the post's publish date, and by default corresponds with | ||
# the date and time this file was generated. Dates are used for display and | ||
# ordering purposes only; they have no effect on whether or when a post is | ||
# published. To influence the ordering of posts published on the same date, use | ||
# the time portion of the date value; posts are sorted in descending order by | ||
# date/time. | ||
date: 2025-09-04T12:00:00-07:00 | ||
|
||
# The draft setting determines whether a post is published. Set it to true if | ||
# you want to be able to merge the post without publishing it. | ||
draft: false | ||
|
||
# Use the meta_desc property to provide a brief summary (one or two sentences) | ||
# of the content of the post, which is useful for targeting search results or | ||
# social-media previews. This field is required or the build will fail the | ||
# linter test. Max length is 160 characters. | ||
meta_desc: | | ||
Pulumi Azure Native v3.8 delivers new credential modes (based on DefaultAzureCredential) | ||
and private cloud support (based on ARM_METADATA_HOSTNAME). | ||
|
||
# The meta_image appears in social-media previews and on the blog home page. A | ||
# placeholder image representing the recommended format, dimensions and aspect | ||
# ratio has been provided for you. | ||
meta_image: meta.png | ||
|
||
# At least one author is required. The values in this list correspond with the | ||
# `id` properties of the team member files at /data/team/team. Create a file for | ||
# yourself if you don't already have one. | ||
authors: | ||
- eron-wright | ||
|
||
# At least one tag is required. Lowercase, hyphen-delimited is recommended. | ||
tags: | ||
- azure-native | ||
- azure | ||
- features | ||
- releases | ||
|
||
# The social copy used to promote this post on Twitter and Linkedin. These | ||
# properties do not actually create the post and have no effect on the | ||
# generated blog page. They are here strictly for reference. | ||
|
||
# Here are some examples of posts we have made in the past for inspiration: | ||
# https://www.linkedin.com/feed/update/urn:li:activity:7171191945841561601 | ||
# https://www.linkedin.com/feed/update/urn:li:activity:7169021002394296320 | ||
# https://www.linkedin.com/feed/update/urn:li:activity:7155606616455737345 | ||
# https://twitter.com/PulumiCorp/status/1763265391042654623 | ||
# https://twitter.com/PulumiCorp/status/1762900472489185492 | ||
# https://twitter.com/PulumiCorp/status/1755637618631405655 | ||
|
||
social: | ||
twitter: | ||
linkedin: | ||
|
||
--- | ||
|
||
Today we're excited to announce Azure Native Provider v3.8, featuring several enhancements that simplify authentication | ||
and extend support to private Azure environments. These updates make it easier than ever to manage Azure infrastructure | ||
using credentials provided by the hosting environment, such as in Azure Kubernetes Service (AKS), Azure VM, and Azure Cloud Shell. | ||
|
||
<!--more--> | ||
|
||
## Simplified Authentication Across Environments | ||
|
||
The highlight of this release is a new authentication mode based on [DefaultAzureCredential][doc1], | ||
a feature of the Azure SDK that unifies authentication-related settings across deployment environments. | ||
|
||
[doc1]: https://learn.microsoft.com/en-us/azure/developer/go/sdk/authentication/credential-chains#defaultazurecredential-overview | ||
|
||
### What's New | ||
|
||
`DefaultAzureCredential` automatically discovers and uses the best available authentication method for your environment, | ||
eliminating the need for an environment-specific configuration. It follows the Azure SDK's standard credential chain: | ||
|
||
| Order | Credential | Description | | ||
|-------|---------------------------|------------------------------------------------------------------------------------------------------------------| | ||
| 1 | [Environment][o1] | Reads environment variables (e.g., `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`) to authenticate as a service principal. | | ||
| 2 | [Workload Identity][o2] | For programs run on an Azure Kubernetes Service (AKS) cluster. | | ||
| 3 | [Managed Identity][o3] | For programs deployed to an Azure compute resource (e.g., Azure Virtual Machines) or App hosting platform. | | ||
| 4 | [Azure CLI][o4] | For local development using Azure CLI's `az login` command. | | ||
| 5 | [Azure Developer CLI][o5] | For local development using Azure Developer CLI's `azd auth login` command. | | ||
|
||
[o1]: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/azidentity#EnvironmentCredential | ||
[o2]: https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview?tabs=go | ||
[o3]: https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview | ||
[o4]: https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli?view=azure-cli-latest | ||
[o5]: https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/overview?tabs=windows | ||
|
||
### Real-World Benefits | ||
|
||
This means your Pulumi programs can now run seamlessly across: | ||
|
||
- Local development machines using Azure CLI credentials | ||
- CI/CD pipelines with service principals via environment variables | ||
- Azure Kubernetes Service with Workload Identity | ||
- Azure VMs and App Services with Managed Identity | ||
|
||
All without changing a single line of configuration code. | ||
|
||
### Getting Started | ||
|
||
Enable DefaultAzureCredential using Pulumi configuration: | ||
|
||
```bash | ||
pulumi config set azure-native:useDefaultAzureCredential true | ||
pulumi config set azure-native:subscriptionId <your-subscription-id> | ||
``` | ||
|
||
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. | ||
|
||
## Private Azure Cloud Support | ||
|
||
This release brings improved support for [Azure private clouds][docprivatecloud]. | ||
A private cloud is a dedicated cloud computing environment used by a single organization. | ||
|
||
The provider can now automatically discover, and configure itself for, any Azure cloud based on | ||
the `ARM_METADATA_HOSTNAME` environment variable. Note that this takes precedence over the `ARM_ENVIRONMENT` variable. | ||
|
||
[docprivatecloud]: https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-a-private-cloud | ||
|
||
### How To Use | ||
|
||
The provider can query the Azure metadata service to automatically configure itself for your specific Azure environment: | ||
|
||
```bash | ||
# Using environment variable | ||
export ARM_METADATA_HOSTNAME=management.azure.example | ||
|
||
# Or via Pulumi configuration | ||
pulumi config set azure-native:metadataHost management.azure.example | ||
``` | ||
|
||
The provider expects the `2022-09-01` metadata schema, which resembles: | ||
|
||
```json | ||
{ | ||
"authentication": { | ||
"loginEndpoint": "https://login.microsoftonline.com", | ||
"audiences": [ | ||
"https://management.core.windows.net/", | ||
"https://management.azure.com/" | ||
] | ||
}, | ||
"name": "AzureCloud", | ||
"suffixes": { | ||
"keyVaultDns": "vault.azure.net", | ||
"storage": "core.windows.net" | ||
}, | ||
"resourceManager": "https://management.azure.com/", | ||
"microsoftGraphResourceId": "https://graph.microsoft.com/" | ||
} | ||
``` | ||
|
||
The provider automatically retrieves the correct endpoints for authentication, resource management, and other services. | ||
|
||
## Disabling Instance Discovery | ||
|
||
Also in this release is a new setting, `disableInstanceDiscovery`, to determine whether the provider requests | ||
Microsoft Entra instance metadata from the login endpoint (https://login.microsoftonline.com) before authenticating. | ||
This setting is for Pulumi programs authenticating in disconnected clouds or private clouds. | ||
|
||
Setting `disableInstanceDiscovery` to `true` will completely disable both instance discovery and authority validation. | ||
Please ensure that the configured authority host is valid and trustworthy. | ||
|
||
### How To Use | ||
|
||
The provider can be configured to disable instance discovery: | ||
|
||
```bash | ||
# Using environment variable | ||
export ARM_DISABLE_INSTANCE_DISCOVERY=true | ||
|
||
# Or via Pulumi configuration | ||
pulumi config set azure-native:disableInstanceDiscovery true | ||
``` | ||
|
||
## Authentication in AKS with Workload Identity | ||
|
||
For programs run in a pod on an Azure Kubernetes Service (AKS) cluster, DefaultAzureCredential automatically uses the | ||
workload identity of the pod's service account. This workload identity could then be granted roles in Azure to deploy stack resources. | ||
|
||
{{% notes type="info" %}} | ||
|
||
Ensure that the application pods using workload identity include the label `azure.workload.identity/use: "true"` in the pod spec. | ||
|
||
{{% /notes %}} | ||
|
||
### Walkthough | ||
|
||
Let's use [Pulumi Kubernetes Operator (PKO)][pko1] to demonstrate a use case where you'd run Pulumi deployment operations in a pod | ||
and could benefit from workload identity. | ||
|
||
The operator allocates a dedicated pod for each Pulumi stack under its management, to serve as the execution environment for stack operations. | ||
Each stack may use the same or a different service account. With AKS, that service account has a _workload identity_ that providers | ||
may use to authenticate to Azure cloud and even to Pulumi cloud. | ||
|
||
[pko1]: https://www.pulumi.com/docs/iac/using-pulumi/continuous-delivery/pulumi-kubernetes-operator/ | ||
|
||
#### Create an AKS Cluster | ||
|
||
Please follow the steps in ["Deploy and configure workload identity on an Azure Kubernetes Service (AKS) cluster"][aks1] | ||
to create an AKS cluster, managed identity, and Kubernetes service account. Those steps are: | ||
|
||
1. [Create an AKS cluster](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-an-aks-cluster) | ||
2. [Retrieve the OIDC issuer URL](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#retrieve-the-oidc-issuer-url) | ||
3. [Create a managed identity](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-a-managed-identity) | ||
4. [Create a Kubernetes service account](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-a-kubernetes-service-account) | ||
5. [Create the federated identity credential](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster#create-the-federated-identity-credential) | ||
|
||
You now have an Azure managed identity and associated Kubernetes service account that DefaultAzureCredential can use to authenticate to Azure cloud. | ||
|
||
Take note of the `clientId` that represents the managed identity: | ||
|
||
```shell | ||
az identity show --name "${USER_ASSIGNED_IDENTITY_NAME}" --resource-group "${RESOURCE_GROUP}" --query clientId | ||
"c2bbe0f5-6349-480a-9f6f-3a5cb3e4ecf9" | ||
``` | ||
|
||
[aks1]: https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster | ||
|
||
#### Install the Pulumi Kubernetes Operator | ||
|
||
Install the operator into the `pulumi-kubernetes-operator` namespace: | ||
|
||
```shell | ||
kubectl apply -f https://raw.githubusercontent.com/pulumi/pulumi-kubernetes-operator/refs/tags/v2.0.0/deploy/quickstart/install.yaml | ||
``` | ||
|
||
#### Configure a Pulumi Cloud Access Token | ||
|
||
By default, the operator uses Pulumi Cloud as the state backend for your stacks. | ||
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. | ||
|
||
```shell | ||
kubectl create secret generic -n ${SERVICE_ACCOUNT_NAMESPACE} pulumi-api-secret --from-literal=accessToken=${PULUMI_ACCESS_TOKEN} | ||
``` | ||
|
||
[doctokens]: https://www.pulumi.com/docs/pulumi-cloud/access-management/access-tokens/ | ||
|
||
#### Update the Kubernetes Service Account | ||
|
||
To use the service account that was created earlier, we need to grant it the `system:auth-delegator` role: | ||
|
||
```shell | ||
cat <<EOF | kubectl apply -f - | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: "${SERVICE_ACCOUNT_NAMESPACE}-${SERVICE_ACCOUNT_NAME}:system:auth-delegator" | ||
roleRef: | ||
apiGroup: rbac.authorization.k8s.io | ||
kind: ClusterRole | ||
name: system:auth-delegator | ||
subjects: | ||
- kind: ServiceAccount | ||
name: "${SERVICE_ACCOUNT_NAME}" | ||
namespace: "${SERVICE_ACCOUNT_NAMESPACE}" | ||
EOF | ||
``` | ||
|
||
#### Define an Example Program | ||
|
||
Let's define a simple Pulumi program that uses Azure Native 3.8 and calls the ["getClientConfig"][azdoc1] function to | ||
access the current identity of the provider. | ||
|
||
[azdoc1]: https://www.pulumi.com/registry/packages/azure-native/api-docs/authorization/getclientconfig/ | ||
|
||
```shell | ||
cat <<"EOF" | kubectl apply -n ${SERVICE_ACCOUNT_NAMESPACE} -f - | ||
apiVersion: pulumi.com/v1 | ||
kind: Program | ||
metadata: | ||
name: sample-workload-identity | ||
program: | ||
variables: | ||
clientConfig: | ||
fn::invoke: | ||
function: azure-native:authorization:getClientConfig | ||
clientToken: | ||
fn::secret: | ||
fn::invoke: | ||
function: azure-native:authorization:getClientToken | ||
outputs: | ||
clientConfig: ${clientConfig} | ||
clientToken: ${clientToken} | ||
EOF | ||
``` | ||
|
||
#### Run the Program using Workload Identity | ||
|
||
Create a Stack object to run the Pulumi program using your service account and with `azure-native:useDefaultAzureCredential` enabled. | ||
|
||
```shell | ||
cat <<EOF | kubectl apply -f - | ||
apiVersion: pulumi.com/v1 | ||
kind: Stack | ||
metadata: | ||
name: sample-workload-identity | ||
namespace: "${SERVICE_ACCOUNT_NAMESPACE}" | ||
spec: | ||
programRef: | ||
name: sample-workload-identity | ||
stack: sample-workload-identity | ||
envRefs: | ||
PULUMI_ACCESS_TOKEN: | ||
type: Secret | ||
secret: | ||
name: pulumi-api-secret | ||
key: accessToken | ||
serviceAccountName: "${SERVICE_ACCOUNT_NAME}" | ||
config: | ||
azure-native:useDefaultAzureCredential: "true" | ||
azure-native:subscriptionId: "${SUBSCRIPTION}" | ||
workspaceTemplate: | ||
spec: | ||
podTemplate: | ||
metadata: | ||
labels: | ||
azure.workload.identity/use: "true" | ||
EOF | ||
``` | ||
|
||
Checking the stack outputs, we see a `clientId` matching that of the managed identity! | ||
|
||
```shell | ||
kubectl get stack/sample-workload-identity -oyaml | ||
``` | ||
|
||
```yaml | ||
apiVersion: pulumi.com/v1 | ||
kind: Stack | ||
metadata: | ||
name: sample-workload-identity | ||
namespace: default | ||
status: | ||
conditions: | ||
- lastTransitionTime: "2025-09-04T23:32:11Z" | ||
message: the stack has been processed and is up to date | ||
reason: ProcessingCompleted | ||
status: "True" | ||
type: Ready | ||
outputs: | ||
clientConfig: | ||
clientId: c2bbe0f5-6349-480a-9f6f-3a5cb3e4ecf9 | ||
objectId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
subscriptionId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
tenantId: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx | ||
clientToken: '[secret]' | ||
``` | ||
|
||
## Conclusion | ||
|
||
Azure Native Provider v3.8 represents our commitment to making Azure infrastructure management work seamlessly across all deployment scenarios, | ||
from local development to production, from public cloud to private cloud. | ||
|
||
Have questions or feedback? [Open an issue on GitHub](https://github.com/pulumi/pulumi-azure-native/issues) | ||
or join the conversation in our [Community Slack](https://slack.pulumi.com/) (#azure channel). |
Binary file added
BIN
+582 KB
content/blog/azure-native-defaultazurecredential-and-private-cloud/meta.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.