Skip to content

Commit 5901e78

Browse files
authored
Merge pull request #5 from ronaldbosma/add-user-assigned-identities
Add user-assigned managed identities
2 parents 1077754 + d4ed3d4 commit 5901e78

File tree

9 files changed

+100
-12
lines changed

9 files changed

+100
-12
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ As mentioned in the [Overview](#overview) section, this template deploys a set o
186186

187187
When the `includeApiManagement` parameter or the corresponding `INCLUDE_API_MANAGEMENT` environment variable is set to `true`, a Consumption tier API Management service is deployed via the [api-management.bicep](./infra/modules/services/api-management.bicep) module:
188188

189-
- The system-assigned managed identity is enabled to provide access to other services. See the [Role Assignments](#role-assignments) section for more information.
189+
- Both a user-assigned managed identity and system-assigned managed identity are deployed to provide access to other services. See the [Role Assignments](#role-assignments) section for more information.
190190
- The primary key of the default `master` subscription is stored in a Key Vault secret called `apim-master-subscription-key`. This key can be used, for example, by the Function App to access APIs hosted on API Management.
191191
- The deployment also includes backends for the Service Bus (\*), various Storage Account endpoints and the Event Hubs namespace (\*).
192192
_Note: The `*` indicates that the backend is only deployed if the corresponding service is included._
@@ -198,7 +198,7 @@ When the `includeFunctionApp` parameter or the corresponding `INCLUDE_FUNCTION_A
198198

199199
- The `Y1` (Consumption) pricing tier is used.
200200
- The worker runtime is configured to .NET 9 isolated.
201-
- The system-assigned managed identity is enabled to provide access to other services. See the [Role Assignments](#role-assignments) section for more information.
201+
- Both a user-assigned managed identity and system-assigned managed identity are deployed to provide access to other services. See the [Role Assignments](#role-assignments) section for more information.
202202

203203
The following app settings (environment variables) are configured to facilitate connections to other services.
204204

@@ -223,7 +223,7 @@ When the `includeLogicApp` parameter or the corresponding `INCLUDE_LOGIC_APP` en
223223

224224
- The `WS1` (Workflow Standard) pricing tier is used.
225225
- The worker runtime is configured to .NET 9 to enable the use of [custom .NET code](https://learn.microsoft.com/en-us/azure/logic-apps/create-run-custom-code-functions).
226-
- The system-assigned managed identity is enabled and provides access to other services. See the [Role Assignments](#role-assignments) section for more information.
226+
- Both a user-assigned managed identity and system-assigned managed identity are deployed to provide access to other services. See the [Role Assignments](#role-assignments) section for more information.
227227

228228
The following app settings (environment variables) are configured to facilitate connections to other services. These are used in the [connections.json](./src/logicApp/connections.json) file of the sample application.
229229

@@ -250,7 +250,7 @@ When the `includeEventHubsNamespace` parameter or the corresponding `INCLUDE_EVE
250250

251251
#### Role Assignments
252252

253-
The [assign-roles-to-principal.bicep](./infra/modules/shared/assign-roles-to-principal.bicep) module is used to assign roles to the principal of the deployer and to the system-assigned managed identity of API Management, the Function App and Logic App. These role assignments are:
253+
The [assign-roles-to-principal.bicep](./infra/modules/shared/assign-roles-to-principal.bicep) module is used to assign roles to the principal of the deployer and to the user-assigned & system-assigned managed identities of API Management, the Function App and Logic App. These role assignments are:
254254

255255
- Event Hubs namespace roles:
256256
- Azure Event Hubs Data Receiver

azure.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
name: azure-integration-services-quickstart
44
metadata:
5-
template: tdd-azure-integration-services-quickstart@1.1.0
5+
template: tdd-azure-integration-services-quickstart@1.2.0
66
services:
77
functionApp:
88
project: ./src/functionApp

images/deployed-resources.png

1.09 KB
Loading

infra/main.bicep

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ var resourceGroupName = getResourceName('resourceGroup', environmentName, locati
5959

6060
var apiManagementSettings = !includeApiManagement ? null : {
6161
serviceName: getResourceName('apiManagement', environmentName, location, instanceId)
62+
identityName: getResourceName('managedIdentity', environmentName, location, 'apim-${instanceId}')
6263
publisherName: '[email protected]'
6364
publisherEmail: '[email protected]'
6465
}
@@ -75,12 +76,14 @@ var eventHubSettings = !includeEventHubsNamespace ? null : {
7576

7677
var functionAppSettings = !includeFunctionApp ? null : {
7778
functionAppName: getResourceName('functionApp', environmentName, location, instanceId)
79+
identityName: getResourceName('managedIdentity', environmentName, location, 'functionapp-${instanceId}')
7880
appServicePlanName: getResourceName('appServicePlan', environmentName, location, 'functionapp-${instanceId}')
7981
netFrameworkVersion: 'v9.0'
8082
}
8183

8284
var logicAppSettings = !includeLogicApp ? null : {
8385
logicAppName: getResourceName('logicApp', environmentName, location, instanceId)
86+
identityName: getResourceName('managedIdentity', environmentName, location, 'logicapp-${instanceId}')
8487
appServicePlanName: getResourceName('appServicePlan', environmentName, location, 'logicapp-${instanceId}')
8588
netFrameworkVersion: 'v9.0'
8689
}

infra/modules/services/api-management.bicep

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,26 @@ resource masterSubscription 'Microsoft.ApiManagement/service/subscriptions@2023-
6666
// Resources
6767
//=============================================================================
6868

69+
// Create API Management user-assigned identity and assign roles to it
70+
71+
resource apimIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = {
72+
name: apiManagementSettings.identityName
73+
location: location
74+
tags: tags
75+
}
76+
77+
module assignRolesToApimUserAssignedIdentity '../shared/assign-roles-to-principal.bicep' = {
78+
name: 'assignRolesToApimUserAssignedIdentity'
79+
params: {
80+
principalId: apimIdentity.properties.principalId
81+
principalType: 'ServicePrincipal'
82+
eventHubSettings: eventHubSettings
83+
keyVaultName: keyVaultName
84+
serviceBusSettings: serviceBusSettings
85+
storageAccountName: storageAccountName
86+
}
87+
}
88+
6989
// API Management - Consumption tier (see also: https://learn.microsoft.com/en-us/azure/api-management/quickstart-bicep?tabs=CLI)
7090

7191
resource apiManagementService 'Microsoft.ApiManagement/service@2023-09-01-preview' = {
@@ -81,7 +101,10 @@ resource apiManagementService 'Microsoft.ApiManagement/service@2023-09-01-previe
81101
publisherEmail: apiManagementSettings.publisherEmail
82102
}
83103
identity: {
84-
type: 'SystemAssigned'
104+
type: 'SystemAssigned, UserAssigned'
105+
userAssignedIdentities: {
106+
'${apimIdentity.id}': {}
107+
}
85108
}
86109
}
87110

infra/modules/services/function-app.bicep

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,26 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing
107107
// Resources
108108
//=============================================================================
109109

110+
// Create Function App user-assigned identity and assign roles to it
111+
112+
resource functionAppIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = {
113+
name: functionAppSettings.identityName
114+
location: location
115+
tags: tags
116+
}
117+
118+
module assignRolesToFunctionAppUserAssignedIdentity '../shared/assign-roles-to-principal.bicep' = {
119+
name: 'assignRolesToFunctionAppUserAssignedIdentity'
120+
params: {
121+
principalId: functionAppIdentity.properties.principalId
122+
principalType: 'ServicePrincipal'
123+
eventHubSettings: eventHubSettings
124+
keyVaultName: keyVaultName
125+
serviceBusSettings: serviceBusSettings
126+
storageAccountName: storageAccountName
127+
}
128+
}
129+
110130
// Create the App Service Plan for the Function App
111131

112132
resource hostingPlan 'Microsoft.Web/serverfarms@2024-04-01' = {
@@ -130,7 +150,10 @@ resource functionApp 'Microsoft.Web/sites@2024-04-01' = {
130150
tags: serviceTags
131151
kind: 'functionapp'
132152
identity: {
133-
type: 'SystemAssigned'
153+
type: 'SystemAssigned, UserAssigned'
154+
userAssignedIdentities: {
155+
'${functionAppIdentity.id}': {}
156+
}
134157
}
135158
properties: {
136159
serverFarmId: hostingPlan.id

infra/modules/services/logic-app.bicep

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,26 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing
110110
// Resources
111111
//=============================================================================
112112

113+
// Create Logic App user-assigned identity and assign roles to it
114+
115+
resource logicAppIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2024-11-30' = {
116+
name: logicAppSettings.identityName
117+
location: location
118+
tags: tags
119+
}
120+
121+
module assignRolesToLogicAppUserAssignedIdentity '../shared/assign-roles-to-principal.bicep' = {
122+
name: 'assignRolesToLogicAppUserAssignedIdentity'
123+
params: {
124+
principalId: logicAppIdentity.properties.principalId
125+
principalType: 'ServicePrincipal'
126+
eventHubSettings: eventHubSettings
127+
keyVaultName: keyVaultName
128+
serviceBusSettings: serviceBusSettings
129+
storageAccountName: storageAccountName
130+
}
131+
}
132+
113133
// Create the App Service Plan for the Logic App
114134

115135
resource hostingPlan 'Microsoft.Web/serverfarms@2024-04-01' = {
@@ -135,7 +155,10 @@ resource logicApp 'Microsoft.Web/sites@2024-04-01' = {
135155
tags: serviceTags
136156
kind: 'functionapp,workflowapp'
137157
identity: {
138-
type: 'SystemAssigned'
158+
type: 'SystemAssigned, UserAssigned'
159+
userAssignedIdentities: {
160+
'${logicAppIdentity.id}': {}
161+
}
139162
}
140163
properties: {
141164
serverFarmId: hostingPlan.id

infra/modules/shared/assign-roles-to-principal.bicep

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import { eventHubSettingsType, serviceBusSettingsType } from '../../types/settin
1616
@description('The id of the principal that will be assigned the roles')
1717
param principalId string
1818

19+
@description('The type of the principal that will be assigned the roles')
20+
param principalType string?
21+
1922
@description('The flag to determine if the principal is an admin or not')
2023
param isAdmin bool = false
2124

@@ -85,44 +88,48 @@ resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' existing
8588

8689
// Assign role on Event Hubs namespace to the principal (if Event Hubs namespace is included)
8790

88-
resource assignRolesOnEventHubNamespaceToManagedIdentity 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in eventHubRoles: if (eventHubSettings != null) {
91+
resource assignRolesOnEventHubNamespaceToPrincipal 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in eventHubRoles: if (eventHubSettings != null) {
8992
name: guid(principalId, eventHubsNamespace.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role))
9093
scope: eventHubsNamespace
9194
properties: {
9295
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role)
9396
principalId: principalId
97+
principalType: principalType
9498
}
9599
}]
96100

97101
// Assign role on Key Vault to the principal
98102

99-
resource assignRolesOnKeyVaultToManagedIdentity 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
103+
resource assignRolesOnKeyVaultToPrincipal 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
100104
name: guid(principalId, keyVault.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultRole))
101105
scope: keyVault
102106
properties: {
103107
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultRole)
104108
principalId: principalId
109+
principalType: principalType
105110
}
106111
}
107112

108113
// Assign roles on Service Bus to the principal (if Service Bus is included)
109114

110-
resource assignRolesOnServiceBusToManagedIdentity 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in serviceBusRoles: if (serviceBusSettings != null) {
115+
resource assignRolesOnServiceBusToPrincipal 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in serviceBusRoles: if (serviceBusSettings != null) {
111116
name: guid(principalId, serviceBusNamespace.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role))
112117
scope: serviceBusNamespace
113118
properties: {
114119
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role)
115120
principalId: principalId
121+
principalType: principalType
116122
}
117123
}]
118124

119125
// Assign roles on Storage Account to the principal
120126

121-
resource assignRolesOnStorageAccountToManagedIdentity 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in storageAccountRoles: {
127+
resource assignRolesOnStorageAccountToPrincipal 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for role in storageAccountRoles: {
122128
name: guid(principalId, storageAccount.id, subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role))
123129
scope: storageAccount
124130
properties: {
125131
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', role)
126132
principalId: principalId
133+
principalType: principalType
127134
}
128135
}]

infra/types/settings.bicep

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ type apiManagementSettingsType = {
66
@description('The name of the API Management service')
77
serviceName: string
88

9+
@description('The name of the user-assigned managed identity for the API Management service')
10+
identityName: string
11+
912
@description('The name of the owner of the API Management service')
1013
publisherName: string
1114

@@ -48,6 +51,9 @@ type functionAppSettingsType = {
4851
@description('The name of the Function App')
4952
functionAppName: string
5053

54+
@description('The name of the user-assigned managed identity for the Function App')
55+
identityName: string
56+
5157
@description('The name of the App Service for the Function App')
5258
appServicePlanName: string
5359

@@ -64,6 +70,9 @@ type logicAppSettingsType = {
6470
@description('The name of the Logic App')
6571
logicAppName: string
6672

73+
@description('The name of the user-assigned managed identity for the Logic App')
74+
identityName: string
75+
6776
@description('The name of the App Service for the Logic App')
6877
appServicePlanName: string
6978

0 commit comments

Comments
 (0)