Skip to content

Commit f8af48d

Browse files
Service bus managed identity integration (#253)
* Enable service bus managed identity integration * Add custom ACA module to support latest API version * Disable local auth on Service Bus * Remove networkAcls from storage account in dev deployments --------- Co-authored-by: Taylor Southwick <[email protected]>
1 parent 9fa95a7 commit f8af48d

12 files changed

+194
-338
lines changed

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
> :mega: **Got feedback?** Fill out [this survey](https://aka.ms/eap/mwa/dotnet/survey) to help us shape the future of Enterprise App Patterns and understand whether we're focusing on the business goals and features important to you. [Microsoft Privacy Statement](https://go.microsoft.com/fwlink/?LinkId=521839)
44
5-
The reference implementation provides a production-grade web application that uses best practices from our guidance and gives developers concrete examples to build their own Modern Web Application in Azure. This repository specifically demonstrates a concert ticketing application for the fictional company Relecloud, embodying the modern web app pattern with a focus on .NET technologies. It guides developers through a simulated migration from an on-premises ASP.NET application to Azure, detailing the architectural changes and enhancements that capitalize on the cloud's strengths during the initial adoption phase.
5+
The reference implementation provides a production-grade web application that uses best practices from our guidance and gives developers concrete examples to build their own Modern Web Application in Azure. This repository specifically demonstrates a concert ticketing application for the fictional company Relecloud, embodying the modern web app pattern with a focus on .NET technologies. It guides developers through a simulated migration from an on-premises ASP.NET application to Azure, detailing the architectural changes and enhancements that capitalize on the cloud's strengths during the initial adoption phase.
66

77
This project has [a companion article in the Azure Architecture Center](https://aka.ms/eap/mwa/dotnet/doc) that describes design patterns and best practices <!--and [a six-part video series (YouTube)](https://aka.ms/eap/mwa/dotnet/videos) that details the modern web app pattern for .NET web app -->. Here's an outline of the contents in this readme:
88

@@ -32,7 +32,7 @@ This diagram describes the production deployment which is described in the [prod
3232
## Workflow
3333

3434
This description details the workflow for Relecloud's concert ticketing application. It highlights key components and functionality to help you emulate its design:
35-
35+
3636
- Global traffic routing: Azure Front Door acts as a global traffic manager, routing users to the primary region for optimal performance and failing over to a secondary region during outages for uninterrupted service.
3737
- Security inspection: Incoming traffic is inspected by Azure Web Application Firewall to protect against web vulnerabilities before reaching the web app.
3838
- Static and dynamic content delivery: Users receive static content, like the home page, immediately upon request. Dynamic content, such as 'Upcoming Concerts', is generated by making API calls to the backend, which fetches data from Azure SQL Database and returns it in a JSON format.
@@ -57,7 +57,7 @@ The following detailed deployment steps assume you are using a Dev Container ins
5757
5858
### 1. Clone the repo
5959

60-
> For Windows users, we recommend using Windows Subsystem for Linux (WSL) to [improve Dev Container performance](https://code.visualstudio.com/remote/advancedcontainers/improve-performance).
60+
> For Windows users, we recommend using Windows Subsystem for Linux (WSL) to [improve Dev Container performance and reliability](https://code.visualstudio.com/remote/advancedcontainers/improve-performance).
6161
6262
```pwsh
6363
wsl
@@ -194,8 +194,8 @@ azd down --purge --force
194194

195195
## Trademarks
196196

197-
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
198-
trademarks or logos is subject to and must follow
197+
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
198+
trademarks or logos is subject to and must follow
199199
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
200200
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
201201
Any use of third-party trademarks or logos are subject to those third-party's policies.

azure.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ hooks:
2424
posix:
2525
interactive: true
2626
shell: sh
27-
run: ./infra/scripts/predeploy/call-configure-aca-secrets.sh && ./infra/scripts/predeploy/call-set-app-configuration.sh
27+
run: ./infra/scripts/predeploy/call-set-app-configuration.sh
2828
windows:
2929
interactive: true
3030
shell: pwsh
31-
run: ./infra/scripts/predeploy/call-configure-aca-secrets.ps1 &&./infra/scripts/predeploy/call-set-app-configuration.ps1
31+
run: ./infra/scripts/predeploy/call-set-app-configuration.ps1
3232
postdeploy:
3333
posix:
3434
interactive: true

infra/core/containers/container-registry-replication.bicep

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ targetScope = 'resourceGroup'
1010
** Creates an Azure Container Registry resource, including permission grants and diagnostics.
1111
*/
1212

13-
14-
1513
// ========================================================================
1614
// PARAMETERS
1715
// ========================================================================

infra/core/containers/container-registry.bicep

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,43 +10,13 @@ targetScope = 'resourceGroup'
1010
** Creates an Azure Container Registry resource, including permission grants and diagnostics.
1111
*/
1212

13+
import { DiagnosticSettings } from '../../types/DiagnosticSettings.bicep'
14+
import { PrivateEndpointSettings } from '../../types/PrivateEndpointSettings.bicep'
1315

1416
// ========================================================================
1517
// USER-DEFINED TYPES
1618
// ========================================================================
1719

18-
// From: infra/types/DiagnosticSettings.bicep
19-
@description('The diagnostic settings for a resource')
20-
type DiagnosticSettings = {
21-
@description('The number of days to retain log data.')
22-
logRetentionInDays: int
23-
24-
@description('The number of days to retain metric data.')
25-
metricRetentionInDays: int
26-
27-
@description('If true, enable diagnostic logging.')
28-
enableLogs: bool
29-
30-
@description('If true, enable metrics logging.')
31-
enableMetrics: bool
32-
}
33-
34-
// From: infra/types/PrivateEndpointSettings.bicep
35-
@description('Type describing the private endpoint settings.')
36-
type PrivateEndpointSettings = {
37-
@description('The name of the resource group to hold the Private DNS Zone. By default, this uses the same resource group as the resource.')
38-
dnsResourceGroupName: string
39-
40-
@description('The name of the private endpoint resource.')
41-
name: string
42-
43-
@description('The name of the resource group to hold the private endpoint.')
44-
resourceGroupName: string
45-
46-
@description('The ID of the subnet to link the private endpoint to.')
47-
subnetId: string
48-
}
49-
5020
// From: https://github.com/Azure/bicep-registry-modules/blob/main/avm/res/container-registry/registry/main.bicep
5121
type roleAssignmentType = {
5222
@description('Required. The role to assign. You can provide either the display name of the role definition, the role definition GUID, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.')
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
targetScope = 'resourceGroup'
2+
3+
/*
4+
** A Container App running on a pre-existing Managed Environment (ACA Environment)
5+
** Copyright (C) 2024 Microsoft, Inc.
6+
** All Rights Reserved
7+
**
8+
***************************************************************************
9+
*/
10+
11+
// This simple ACA module is used until an updated Azure Verified Module
12+
// is available using the new Container Apps API (version 2024-02-02-preview or newer).
13+
14+
// ========================================================================
15+
// USER-DEFINED TYPES
16+
// ========================================================================
17+
18+
// https://learn.microsoft.com/rest/api/containerapps/container-apps/get?view=rest-containerapps-2024-03-01&tabs=HTTP#container
19+
type container = {
20+
@description('Container start command arguments.')
21+
args: string[]?
22+
23+
@description('Container start command.')
24+
command: string[]?
25+
26+
@description('Container environment variables.')
27+
env: environmentVar[]?
28+
29+
@description('Container image tag.')
30+
image: string
31+
32+
@description('Custom container name.')
33+
name: string?
34+
35+
@description('List of health probes for the container.')
36+
probes: object[]?
37+
38+
@description('Container resource requirements.')
39+
resources: object
40+
41+
@description('Container volume mounts.')
42+
volumeMounts: volumeMount[]?
43+
}
44+
45+
// https://learn.microsoft.com/rest/api/containerapps/container-apps/get?view=rest-containerapps-2024-03-01&tabs=HTTP#environmentvar
46+
type environmentVar = {
47+
@description('Environment variable name.')
48+
name: string
49+
50+
@description('Name of the Container App secret from which to pull the environment variable value.')
51+
secretRef: string?
52+
53+
@description('Non-secret environment variable value.')
54+
value: string?
55+
}
56+
57+
// https://learn.microsoft.com/rest/api/containerapps/container-apps/get?view=rest-containerapps-2024-03-01&tabs=HTTP#volumemount
58+
type volumeMount = {
59+
@description('Path within the container where the volume should be mounted. Must not contain \':\'.')
60+
mountPath: string
61+
62+
@description('Path within the volume from which the container\'s volume should be mounted. Defaults to "" (volume\'s root).')
63+
subPath: string?
64+
65+
@description('This must match the Name of a Volume.')
66+
volumeName: string
67+
}
68+
69+
// ========================================================================
70+
// PARAMETERS
71+
// ========================================================================
72+
73+
@description('The Azure region for the resource.')
74+
param location string
75+
76+
@description('The name of the primary resource')
77+
param name string
78+
79+
@description('The tags to associate with this resource.')
80+
param tags object = {}
81+
82+
/*
83+
** Dependencies
84+
*/
85+
@description('The resource ID of the hosting Azure Container managed environment.')
86+
param environmentId string
87+
88+
@description('The ID of a user-assigned managed identity to use as the identity for this resource. Use a blank string for a system-assigned identity.')
89+
param managedIdentityId string = ''
90+
91+
/*
92+
** Settings
93+
*/
94+
95+
@description('Container images included in the container app.')
96+
param containers container[]
97+
98+
@description('If true, allow HTTP connections to the container app endpoint. If false, HTTP connections are redirected to HTTPS.')
99+
param ingressAllowInsecure bool = false
100+
101+
@description('If true, allow external access to the container app endpoint.')
102+
param ingressExternal bool = false
103+
104+
@description('Container port for ingress traffic.')
105+
param ingressTargetPort int = 80
106+
107+
@description('Credentials for private container registries. Entries defined with secretref reference the secrets configuration object.')
108+
param registries array = []
109+
110+
@description('Scale rule maximum replica count.')
111+
param scaleMaxReplicas int = 5
112+
113+
@description('Scale rule minimum replica count.')
114+
param scaleMinReplicas int = 1
115+
116+
@description('Scale rules for the container app.')
117+
param scaleRules array = []
118+
119+
@description('Workload profile to use for app execution.')
120+
param workloadProfileName string = ''
121+
122+
// ========================================================================
123+
// VARIABLES
124+
// ========================================================================
125+
126+
var identity = !empty(managedIdentityId) ? {
127+
type: 'UserAssigned'
128+
userAssignedIdentities: {
129+
'${managedIdentityId}': {}
130+
}
131+
} : {
132+
type: 'SystemAssigned'
133+
}
134+
135+
// ========================================================================
136+
// AZURE RESOURCES
137+
// ========================================================================
138+
139+
resource containerApp 'Microsoft.App/containerApps@2024-02-02-preview' = {
140+
name: name
141+
location: location
142+
tags: tags
143+
identity: identity
144+
145+
properties: {
146+
environmentId: environmentId
147+
workloadProfileName: workloadProfileName
148+
configuration: {
149+
ingress: {
150+
external: ingressExternal
151+
targetPort: ingressTargetPort
152+
allowInsecure: ingressAllowInsecure
153+
}
154+
registries: !empty(registries) ? registries : null
155+
}
156+
template: {
157+
containers: containers
158+
scale: {
159+
minReplicas: scaleMinReplicas
160+
maxReplicas: scaleMaxReplicas
161+
rules: !empty(scaleRules) ? scaleRules : null
162+
}
163+
}
164+
}
165+
}
166+
167+
// ========================================================================
168+
// OUTPUTS
169+
// ========================================================================
170+
171+
output id string = containerApp.id
172+
output name string = containerApp.name

infra/core/identity/container-registry-role-assignments.bicep

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,7 @@ targetScope = 'resourceGroup'
1010
** Assigns roles to an Azure Container Registry for the specified identities.
1111
*/
1212

13-
// ========================================================================
14-
// USER-DEFINED TYPES
15-
// ========================================================================
16-
17-
// From: infra/types/ApplicationIdentity.bicep
18-
@description('Type describing an application identity.')
19-
type ApplicationIdentity = {
20-
@description('The ID of the identity')
21-
principalId: string
22-
23-
@description('The type of identity - either ServicePrincipal or User')
24-
principalType: 'ServicePrincipal' | 'User'
25-
}
13+
import { ApplicationIdentity } from '../../types/ApplicationIdentity.bicep'
2614

2715
// ========================================================================
2816
// PARAMETERS

infra/core/storage/storage-account.bicep

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ import { PrivateEndpointSettings } from '../../types/PrivateEndpointSettings.bic
1212
import { DiagnosticSettings } from '../../types/DiagnosticSettings.bicep'
1313
import { ApplicationIdentity } from '../../types/ApplicationIdentity.bicep'
1414

15-
type FirewallRules = {
16-
@description('The list of IP address CIDR blocks to allow access from.')
17-
allowedIpAddresses: string[]
18-
}
19-
2015
// ========================================================================
2116
// PARAMETERS
2217
// ========================================================================
@@ -73,9 +68,6 @@ param sku object = { name: 'Standard_LRS' }
7368
@description('Determines whether or not trusted azure services are allowed to connect to this account')
7469
param bypass string = 'AzureServices'
7570

76-
@description('The firewall rules to install on the sql-server.')
77-
param firewallRules FirewallRules?
78-
7971
// ========================================================================
8072
// VARIABLES
8173
// ========================================================================
@@ -91,11 +83,6 @@ var storageBlobDataContributorRoleId = 'ba92f5b4-2d11-453d-a403-e96b0029c9fe'
9183
var defaultToOAuthAuthentication = false
9284
var dnsEndpointType = 'Standard'
9385

94-
95-
var allowedCidrBlocks = firewallRules != null ? map(firewallRules!.allowedIpAddresses, ipaddr => {
96-
value: ipaddr
97-
}) : []
98-
9986
// ========================================================================
10087
// AZURE RESOURCES
10188
// ========================================================================
@@ -115,11 +102,7 @@ resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = {
115102
dnsEndpointType: dnsEndpointType
116103
minimumTlsVersion: minimumTlsVersion
117104
publicNetworkAccess: enablePublicNetworkAccess ? 'Enabled' : 'Disabled'
118-
networkAcls: enablePublicNetworkAccess ? {
119-
bypass: bypass
120-
defaultAction: 'Deny'
121-
ipRules: allowedCidrBlocks
122-
} : {
105+
networkAcls: enablePublicNetworkAccess ? null : {
123106
defaultAction:'Deny'
124107
bypass: bypass
125108
}

0 commit comments

Comments
 (0)