|
| 1 | +--- |
| 2 | +title: Use scripts to automate Azure Resource Manager with workload identity service connections |
| 3 | +description: Learn how to automate Azure Resource Manager service connections in Azure Pipelines with workload identity. Save time, ensure consistency, and reduce errors. |
| 4 | +ms.topic: how-to |
| 5 | +ms.author: jukullam |
| 6 | +author: juliakm |
| 7 | +ms.date: 05/28/2025 |
| 8 | +monikerRange: '= azure-devops' |
| 9 | +"recommendations": "true" |
| 10 | +ai-usage: ai-assisted |
| 11 | +ms.custom: peer-review-program |
| 12 | +--- |
| 13 | + |
| 14 | +# Use scripts to automate Azure Resource Manager with workload identity service connections |
| 15 | + |
| 16 | +[!INCLUDE [version-lt-eq-azure-devops](../../includes/version-eq-azure-devops.md)] |
| 17 | + |
| 18 | +Learn how to use scripts to create Azure Resource Manager service connections with workload identity in Azure Pipelines. Scripts ensure consistency, efficiency, and repeatability when setting up service connections, reducing the risk of human error. They save time, especially when creating multiple connections or deploying to different environments. These scripts can also be integrated into an automation process to scale and better manage large deployments. |
| 19 | + |
| 20 | +Using scripts as part of an automation process helps enforce security policies and compliance requirements by ensuring service connections use the correct permissions and configurations. It also serves as documentation for the setup process. |
| 21 | + |
| 22 | +## Prerequisites |
| 23 | + |
| 24 | +| **Product** | **Requirements** | |
| 25 | +|---|---| |
| 26 | +| **Azure DevOps** | - An Azure DevOps organization and a project. Create an [organization](../../organizations/accounts/create-organization.md) or a [project](../../organizations/projects/create-project.md#create-a-project) if you haven't already. |
| 27 | +| **Azure** | An [Azure subscription](https://azure.microsoft.com/free/).<br> **Permissions:**<br> - To create a role assignment in Azure: you must have *User Access Administrator* or *Role Based Access Control Administrator* permissions, or higher. These roles allow you to manage access and assign roles necessary for creating identities. For more information, see [Azure built-in roles](/azure/role-based-access-control/built-in-roles).| |
| 28 | +| **Entra** | **Permissions:**<br> - To create an app registration in Microsoft Entra: [App registration delegation](/entra/identity/role-based-access-control/delegate-app-roles#restrict-who-can-create-applications) should be enabled or you should have the *Application Developer* role. For more information, see [Microsoft Entra built-in roles](/entra/identity/role-based-access-control/permissions-reference#application-developer).<br/>Instead of creating an app registration in Entra, you can also create a managed identity in Azure.| |
| 29 | + |
| 30 | +## Process |
| 31 | + |
| 32 | +### Constraints |
| 33 | + |
| 34 | +- In automation, `"creationMode": "Manual"` should be used when creating service connections that need a Microsoft Entra identity. Significant Microsoft Entra privileges would be required to have Azure DevOps create all objects on behalf of the caller, therefore Azure DevOps doesn't support the use of `"creationMode": "Automatic"` for non-user principals. Instead, end-to-end automation should create each object (identity, service connection, credential, role assignment) individually. |
| 35 | +- Workload identity federation defines a bi-directional relationship between the identity and service connection. As a result, objects need to be created in a certain order and the federated credential can only be created after the service connection is created. |
| 36 | + |
| 37 | +### Command execution order |
| 38 | + |
| 39 | +This table provides an overview of the key properties exchanged between the creation commands of each object. Dependencies on output determine the order of execution. |
| 40 | + |
| 41 | +| Step | Input | Output | |
| 42 | +|-----------------------------------------------|------------------------|-------------------------| |
| 43 | +| Create identity in Microsoft Entra or Azure | `tenantId` | `appId`, `principalId` | |
| 44 | +| Create service connection in Azure DevOps | `appId` | `workloadIdentityFederationIssuer`, `workloadIdentityFederationSubject` | |
| 45 | +| Create federated credential in Microsoft Entra or Azure | `appId`, `workloadIdentityFederationIssuer`, `workloadIdentityFederationSubject` | | |
| 46 | +| Create role assignment in Azure | `principalId` | | |
| 47 | + |
| 48 | +## 1. Sign in with Azure CLI |
| 49 | + |
| 50 | +The following commands use the Azure CLI. Sign in to the intended tenant: |
| 51 | + |
| 52 | +```azurecli |
| 53 | +az login --tenant TENANT_ID |
| 54 | +``` |
| 55 | + |
| 56 | +Learn more in [Authenticate to Azure using Azure CLI](/cli/azure/authenticate-azure-cli). |
| 57 | + |
| 58 | +## 2. Create identity |
| 59 | + |
| 60 | +Create an identity using managed identity or an app registration. |
| 61 | + |
| 62 | +#### [Managed identity](#tab/managed-identity) |
| 63 | + |
| 64 | +Create a managed identity with `az identity create`. |
| 65 | + |
| 66 | +```azurecli |
| 67 | +az identity create --name MyIdentity --resource-group MyResourceGroup --query '{clientId:clientId,principalId:principalId}' |
| 68 | +``` |
| 69 | + |
| 70 | +Example output: |
| 71 | + |
| 72 | +```json |
| 73 | +{ |
| 74 | + "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444", |
| 75 | + "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222" |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +A managed identity creates a service principal in Microsoft Entra. The object ID of the service principal is also called `principalId`. Use the service principal later to assign RBAC roles. The `appId` is used to create the service connection in Azure DevOps. |
| 80 | + |
| 81 | +Learn more in [az identity create](/cli/azure/identity#az-identity-create). |
| 82 | + |
| 83 | +#### [App registration](#tab/app-registration) |
| 84 | + |
| 85 | +Create an app registration using `az ad sp create-for-rbac`. |
| 86 | + |
| 87 | +```azurecli |
| 88 | +az ad sp show --id $(az ad sp create-for-rbac -n appreg-for-rbac --create-password false -o tsv --query appId) --query '{appId:appId,principalId:id}' |
| 89 | +``` |
| 90 | + |
| 91 | +Example output: |
| 92 | + |
| 93 | +```json |
| 94 | +{ |
| 95 | + "appId": "00001111-aaaa-2222-bbbb-3333cccc4444", |
| 96 | + "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222" |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +This command creates an app and a service principal in Microsoft Entra and retrieves its `appId` and `principalId`. The object ID of the service principal is also called `principalId`. You'll use the service principal later to assign RBAC roles. The `appId` is used to create the service connection in Azure DevOps. The `--create-password false` flag ensures no password is created for the service principal. |
| 101 | + |
| 102 | +For more information, see [az ad sp create-for-rbac](/cli/azure/ad/sp#az-ad-sp-create-for-rbac). |
| 103 | + |
| 104 | +--- |
| 105 | + |
| 106 | +## 3. Create a service connection |
| 107 | + |
| 108 | +This example uses the [Azure DevOps Azure CLI extension](/azure/devops/cli) and a configuration file to create the service connection. This configures the identity created in a new Azure service connection. The `servicePrincipalId` authorization parameter is populated with the `appId` of the identity. |
| 109 | + |
| 110 | +You'll need an `appId` to use as input. |
| 111 | + |
| 112 | +The first code snippet is a configuration file, `ServiceConnectionGeneric.json`. |
| 113 | + |
| 114 | +> [!div class="tabbedCodeSnippets"] |
| 115 | +```json |
| 116 | +{ |
| 117 | + "data": { |
| 118 | + "subscriptionId": "SUBSCRIPTION_ID", |
| 119 | + "subscriptionName": "My Azure Subscription", |
| 120 | + "environment": "AzureCloud", |
| 121 | + "scopeLevel": "Subscription", |
| 122 | + "creationMode": "Manual" |
| 123 | + }, |
| 124 | + "name": "MyNewServiceEndpoint", |
| 125 | + "type": "AzureRM", |
| 126 | + "url": "https://management.azure.com/", |
| 127 | + "authorization": { |
| 128 | + "parameters": { |
| 129 | + "tenantid": "aaaabbbb-0000-cccc-1111-dddd2222eeee", |
| 130 | + "serviceprincipalid": "00001111-aaaa-2222-bbbb-3333cccc4444" |
| 131 | + }, |
| 132 | + "scheme": "WorkloadIdentityFederation" |
| 133 | + }, |
| 134 | + "isShared": false, |
| 135 | + "isReady": true, |
| 136 | + "serviceEndpointProjectReferences": [ |
| 137 | + { |
| 138 | + "projectReference": { |
| 139 | + "id": "c7e5f0b3-71fa-4429-9fb3-3321963a7c06", |
| 140 | + "name": "TestProject" |
| 141 | + }, |
| 142 | + "name": "MyNewServiceEndpoint" |
| 143 | + } |
| 144 | + ] |
| 145 | +} |
| 146 | +``` |
| 147 | + |
| 148 | +```azurecli |
| 149 | +az devops service-endpoint create -service-endpoint-configuration ./ServiceConnectionGeneric.json --query authorization.parameters |
| 150 | +``` |
| 151 | + |
| 152 | +`az devops service-endpoint create` automates creating a service connection in Azure DevOps using `ServiceConnectionGeneric.json`. The output includes authorization parameters you'll use in future steps. |
| 153 | + |
| 154 | +Example output: |
| 155 | + |
| 156 | +```json |
| 157 | +{ |
| 158 | + "serviceprincipalid": "00001111-aaaa-2222-bbbb-3333cccc4444", |
| 159 | + "tenantid": "aaaabbbb-0000-cccc-1111-dddd2222eeee", |
| 160 | + "workloadIdentityFederationIssuer": "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0", |
| 161 | + "workloadIdentityFederationIssuerType": "EntraID", |
| 162 | + "workloadIdentityFederationSubject": "<federation-subject>" |
| 163 | +} |
| 164 | +``` |
| 165 | + |
| 166 | +For more information about this command, see [Azure DevOps CLI service endpoint](/azure/devops/cli/service-endpoint). |
| 167 | + |
| 168 | +## 4. Create a federated identity credential |
| 169 | + |
| 170 | +Create a federated credential using the `workloadIdentityFederationIssuer` and `workloadIdentityFederationSubject` output from the __Create a service connection__ step. |
| 171 | + |
| 172 | +#### [Managed identity](#tab/managed-identity) |
| 173 | + |
| 174 | +```azurecli |
| 175 | +az identity federated-credential create --name fic-for-sc |
| 176 | + --identity-name MyIdentity |
| 177 | + --resource-group MyResourceGroup |
| 178 | + --issuer "https://login.microsoftonline.com/TENANT_ID/v2.0" |
| 179 | + --subject "<federation-subject>" |
| 180 | + --subscription MSI_SUBSCRIPTION_ID |
| 181 | +``` |
| 182 | + |
| 183 | +`az identity federated-credential create` links a federated identity credential to a managed identity, enabling the managed identity to authenticate with Microsoft Entra ID using the provided subject claim. |
| 184 | + |
| 185 | +> [!TIP] |
| 186 | +> Add a line continuation character (Bash: backslash, PowerShell: backquote) at the end of any lines that don't complete the command. |
| 187 | +
|
| 188 | +The managed identity doesn't have to be created in the same subscription that it's granted to access in the [Create role assignment step](#5-create-role-assignment). |
| 189 | + |
| 190 | +For more information about this command, see [az identity federated-credential create](/cli/azure/identity/federated-credential#az-identity-federated-credential-create). |
| 191 | + |
| 192 | +#### [App registration](#tab/app-registration) |
| 193 | + |
| 194 | +```json |
| 195 | +{ |
| 196 | + "name": "fic-for-sc", |
| 197 | + "issuer": "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0", |
| 198 | + "subject": "<federation-subject>", |
| 199 | + "audiences": [ |
| 200 | + "api://AzureADTokenExchange" |
| 201 | + ] |
| 202 | +} |
| 203 | +``` |
| 204 | + |
| 205 | +```azurecli |
| 206 | +az ad app federated-credential create --id APP_ID --parameters credential.json |
| 207 | +``` |
| 208 | + |
| 209 | +`az ad app federated-credential create` links a federated identity credential to an app registration, enabling the application to authenticate with the specified identity provider using the details in the `credential.json` file. |
| 210 | + |
| 211 | +For more information about this command, see [az ad app federated-credential create](/cli/azure/ad/app/federated-credential#az-ad-app-federated-credential-create). |
| 212 | + |
| 213 | +--- |
| 214 | + |
| 215 | +## 5. Create role assignment |
| 216 | + |
| 217 | +Add a role assignment to your managed identity or app registration with `az role assignment create`. For available roles, see [Azure built-in roles](/azure/role-based-access-control/built-in-roles). The assignee of the role is the service principal associated with the app registration or managed identity. A service principal is identified by its ID, also called `principalId`. The `principalId` is in the output of the __Create identity__ command. |
| 218 | + |
| 219 | +```azurecli |
| 220 | +az role assignment create --role Contributor --scope /subscriptions/SUBSCRIPTION_ID --assignee-object-id PRINCIPAL_ID --assignee-principal-type ServicePrincipal |
| 221 | +``` |
| 222 | + |
| 223 | +`az role assignment create --role Contributor` command assigns the Contributor role to a service principal at the subscription level. This allows the service principal to manage resources within the specified subscription. |
| 224 | + |
| 225 | +For more information on this command, see [az role assignment create](/cli/azure/role/assignment#az-role-assignment-create). |
0 commit comments