Skip to content

Commit 9ac595f

Browse files
committed
Updates to function auth
1 parent 12d71d5 commit 9ac595f

File tree

7 files changed

+151
-211
lines changed

7 files changed

+151
-211
lines changed

app/functions/figure_processor/function_app.py

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

119119

120120
@app.function_name(name="process_figure")
121-
@app.route(route="process", methods=["POST"], auth_level=func.AuthLevel.ANONYMOUS)
121+
@app.route(route="process", methods=["POST"])
122122
async def process_figure_request(req: func.HttpRequest) -> func.HttpResponse:
123123
"""Entrypoint for Azure Search custom skill calls."""
124124

infra/app/functions-app.bicep

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@ param instanceMemoryMB int = 2048
1414
param maximumInstanceCount int = 10
1515
param identityId string
1616
param identityClientId string
17-
// App Registration client ID (applicationId) used to secure Function App endpoints (Easy Auth)
18-
param skillAppClientId string = ''
19-
// Audience / identifier URI to validate tokens (e.g. api://<subscriptionId>/<env>-skill)
20-
param skillAppAudience string = ''
17+
18+
// Authorization parameters
19+
@description('The Entra ID application (client) ID for App Service Authentication')
20+
param authClientId string
21+
22+
@description('The Entra ID identifier URI for App Service Authentication')
23+
param authIdentifierUri string
24+
25+
@description('The Azure AD tenant ID for App Service Authentication')
26+
param authTenantId string
2127

2228
// AVM expects authentication.type values: SystemAssignedIdentity | UserAssignedIdentity | StorageAccountConnectionString
2329
// Use UserAssignedIdentity for per-function user-assigned managed identity deployment storage access.
@@ -51,14 +57,12 @@ var appInsightsSettings = !empty(applicationInsightsName) ? {
5157
APPLICATIONINSIGHTS_CONNECTION_STRING: applicationInsights.?properties.ConnectionString ?? ''
5258
} : {}
5359

54-
// Surface skill application identifiers for downstream logging/diagnostics (not used for manual validation now that Easy Auth is enabled)
55-
var skillAudienceSettings = (!empty(skillAppClientId) && !empty(skillAppAudience)) ? {
56-
SKILL_APP_ID: skillAppClientId
57-
SKILL_APP_AUDIENCE: skillAppAudience
58-
} : {}
60+
var easyAuthSettings = {
61+
OVERRIDE_USE_MI_FIC_ASSERTION_CLIENTID: identityClientId
62+
}
5963

6064
// Merge all app settings
61-
var allAppSettings = union(appSettings, baseAppSettings, appInsightsSettings, skillAudienceSettings)
65+
var allAppSettings = union(appSettings, baseAppSettings, appInsightsSettings, easyAuthSettings)
6266

6367
// Create Flex Consumption Function App using AVM
6468
module functionApp 'br/public:avm/res/web/site:0.15.1' = {
@@ -70,7 +74,9 @@ module functionApp 'br/public:avm/res/web/site:0.15.1' = {
7074
tags: tags
7175
serverFarmResourceId: appServicePlanId
7276
managedIdentities: {
73-
userAssignedResourceIds: [identityId]
77+
userAssignedResourceIds: [
78+
'${identityId}'
79+
]
7480
}
7581
functionAppConfig: {
7682
deployment: {
@@ -107,31 +113,43 @@ module functionApp 'br/public:avm/res/web/site:0.15.1' = {
107113

108114
// Enable Easy Auth (App Service authentication) for Azure Search custom skill access when a skillAppId is provided.
109115
// Based on Microsoft guidance: require authentication, return 401 on unauthenticated, allowed audience api://{applicationId}.
110-
resource auth 'Microsoft.Web/sites/config@2022-03-01' = if (!empty(skillAppClientId) && !empty(skillAppAudience)) {
116+
resource auth 'Microsoft.Web/sites/config@2022-03-01' = {
111117
name: '${name}/authsettingsV2'
118+
dependsOn: [
119+
functionApp // Ensure the Function App module completes before configuring authentication
120+
]
112121
properties: {
113122
globalValidation: {
114123
requireAuthentication: true
115124
unauthenticatedClientAction: 'Return401'
125+
redirectToProvider: 'azureactivedirectory'
116126
}
117127
identityProviders: {
118128
azureActiveDirectory: {
119129
enabled: true
120130
registration: {
121-
clientId: skillAppClientId
131+
openIdIssuer: '${environment().authentication.loginEndpoint}${authTenantId}/v2.0'
132+
clientId: authClientId
133+
clientSecretSettingName: 'OVERRIDE_USE_MI_FIC_ASSERTION_CLIENTID'
122134
}
123135
validation: {
124-
allowedAudiences: [ skillAppAudience ]
136+
jwtClaimChecks: {}
137+
allowedAudiences: [
138+
authIdentifierUri
139+
]
140+
defaultAuthorizationPolicy: {
141+
allowedPrincipals: {}
142+
allowedApplications: [authClientId]
143+
}
125144
}
126145
}
127146
}
128147
}
129-
dependsOn: [ functionApp ]
130148
}
131149

132150
// Outputs
133151
output name string = functionApp.outputs.name
134152
output defaultHostname string = functionApp.outputs.defaultHostname
135153
// Expose resourceId for downstream skill auth configuration
136154
output resourceId string = functionApp.outputs.resourceId
137-
output authEnabled bool = !empty(skillAppClientId) && !empty(skillAppAudience)
155+
output authEnabled bool = !empty(authClientId) && !empty(authIdentifierUri)

infra/app/functions-rbac.bicep

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ var monitoringMetricsPublisherRoleId = '3913510d-42f4-4e42-8a64-420c390055eb' //
2323
// Storage: Blob Data Reader (read content container)
2424
module storageBlobReaderRole '../core/security/role.bicep' = {
2525
scope: resourceGroup(storageResourceGroupName)
26-
name: 'storage-blob-reader-${uniqueString(principalId)}'
26+
name: 'function-storage-blob-reader-${uniqueString(principalId)}'
2727
params: {
2828
principalId: principalId
2929
roleDefinitionId: storageBlobDataReaderRoleId
@@ -34,7 +34,7 @@ module storageBlobReaderRole '../core/security/role.bicep' = {
3434
// Storage: Blob Data Contributor (write images container, deployment container)
3535
module storageBlobContributorRole '../core/security/role.bicep' = {
3636
scope: resourceGroup(storageResourceGroupName)
37-
name: 'storage-blob-contributor-${uniqueString(principalId)}'
37+
name: 'function-storage-blob-contributor-${uniqueString(principalId)}'
3838
params: {
3939
principalId: principalId
4040
roleDefinitionId: storageBlobDataContributorRoleId
@@ -45,7 +45,7 @@ module storageBlobContributorRole '../core/security/role.bicep' = {
4545
// Storage: Queue Data Contributor (for AzureWebJobsStorage)
4646
module storageQueueContributorRole '../core/security/role.bicep' = {
4747
scope: resourceGroup(storageResourceGroupName)
48-
name: 'storage-queue-contributor-${uniqueString(principalId)}'
48+
name: 'function-storage-queue-contributor-${uniqueString(principalId)}'
4949
params: {
5050
principalId: principalId
5151
roleDefinitionId: storageQueueDataContributorRoleId
@@ -56,7 +56,7 @@ module storageQueueContributorRole '../core/security/role.bicep' = {
5656
// Storage: Table Data Contributor (for AzureWebJobsStorage)
5757
module storageTableContributorRole '../core/security/role.bicep' = {
5858
scope: resourceGroup(storageResourceGroupName)
59-
name: 'storage-table-contributor-${uniqueString(principalId)}'
59+
name: 'function-storage-table-contributor-${uniqueString(principalId)}'
6060
params: {
6161
principalId: principalId
6262
roleDefinitionId: storageTableDataContributorRoleId
@@ -67,7 +67,7 @@ module storageTableContributorRole '../core/security/role.bicep' = {
6767
// Search: Index Data Contributor (write chunks to index)
6868
module searchIndexContributorRole '../core/security/role.bicep' = {
6969
scope: resourceGroup(searchServiceResourceGroupName)
70-
name: 'search-index-contributor-${uniqueString(principalId)}'
70+
name: 'function-search-index-contributor-${uniqueString(principalId)}'
7171
params: {
7272
principalId: principalId
7373
roleDefinitionId: searchIndexDataContributorRoleId
@@ -78,7 +78,7 @@ module searchIndexContributorRole '../core/security/role.bicep' = {
7878
// OpenAI: Cognitive Services OpenAI User
7979
module openAiUserRole '../core/security/role.bicep' = {
8080
scope: resourceGroup(openAiResourceGroupName)
81-
name: 'openai-user-${uniqueString(principalId)}'
81+
name: 'function-openai-user-${uniqueString(principalId)}'
8282
params: {
8383
principalId: principalId
8484
roleDefinitionId: cognitiveServicesOpenAIUserRoleId
@@ -89,7 +89,7 @@ module openAiUserRole '../core/security/role.bicep' = {
8989
// Document Intelligence: Cognitive Services User
9090
module documentIntelligenceUserRole '../core/security/role.bicep' = {
9191
scope: resourceGroup(documentIntelligenceResourceGroupName)
92-
name: 'doc-intelligence-user-${uniqueString(principalId)}'
92+
name: 'function-doc-intelligence-user-${uniqueString(principalId)}'
9393
params: {
9494
principalId: principalId
9595
roleDefinitionId: cognitiveServicesUserRoleId
@@ -100,7 +100,7 @@ module documentIntelligenceUserRole '../core/security/role.bicep' = {
100100
// Vision: Cognitive Services User (if multimodal)
101101
module visionUserRole '../core/security/role.bicep' = if (useMultimodal && !empty(visionServiceName)) {
102102
scope: resourceGroup(visionResourceGroupName)
103-
name: 'vision-user-${uniqueString(principalId)}'
103+
name: 'function-vision-user-${uniqueString(principalId)}'
104104
params: {
105105
principalId: principalId
106106
roleDefinitionId: cognitiveServicesUserRoleId
@@ -111,7 +111,7 @@ module visionUserRole '../core/security/role.bicep' = if (useMultimodal && !empt
111111
// Content Understanding: Cognitive Services User (if multimodal)
112112
module contentUnderstandingUserRole '../core/security/role.bicep' = if (useMultimodal && !empty(contentUnderstandingServiceName)) {
113113
scope: resourceGroup(contentUnderstandingResourceGroupName)
114-
name: 'content-understanding-user-${uniqueString(principalId)}'
114+
name: 'function-content-understanding-user-${uniqueString(principalId)}'
115115
params: {
116116
principalId: principalId
117117
roleDefinitionId: cognitiveServicesUserRoleId
@@ -121,7 +121,7 @@ module contentUnderstandingUserRole '../core/security/role.bicep' = if (useMulti
121121

122122
// Application Insights: Monitoring Metrics Publisher
123123
module appInsightsMetricsPublisherRole '../core/security/role.bicep' = {
124-
name: 'appinsights-metrics-${uniqueString(principalId)}'
124+
name: 'function-appinsights-metrics-${uniqueString(principalId)}'
125125
params: {
126126
principalId: principalId
127127
roleDefinitionId: monitoringMetricsPublisherRoleId

0 commit comments

Comments
 (0)