Deploy dotnet Azure function alongside Python Azure function (#1733)

Co-authored-by: stas <statis@microsoft.com>
This commit is contained in:
Stas
2022-04-01 09:42:06 -07:00
committed by GitHub
parent e2d554da13
commit 20d3df0a11
4 changed files with 269 additions and 145 deletions

View File

@ -26,7 +26,6 @@ var tenantId = subscription().tenantId
var scaleset_identity = '${name}-scalesetid' var scaleset_identity = '${name}-scalesetid'
var telemetry = 'd7a73cf4-5a1a-4030-85e1-e5b25867e45a'
var StorageBlobDataReader = '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1' var StorageBlobDataReader = '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1'
var roleAssignmentsParams = [ var roleAssignmentsParams = [
@ -68,13 +67,49 @@ module serverFarms 'bicep-templates/server-farms.bicep' = {
location: location location: location
} }
} }
var keyVaultName = 'of-kv-${uniqueString(resourceGroup().id)}'
module keyVaults 'bicep-templates/keyvaults.bicep' = { resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' = {
name: 'keyvaults' name: keyVaultName
params: {
location: location location: location
principal_id: reference(pythonFunction.id, pythonFunction.apiVersion, 'Full').identity.principalId properties: {
tenant_id: tenantId enabledForDiskEncryption: false
enabledForTemplateDeployment: true
sku: {
family: 'A'
name: 'standard'
}
networkAcls: {
defaultAction: 'Allow'
bypass: 'AzureServices'
}
accessPolicies: [
{
objectId: pythonFunction.outputs.principalId
tenantId: tenantId
permissions: {
secrets: [
'get'
'list'
'set'
'delete'
]
}
}
{
objectId: netFunction.outputs.principalId
tenantId: tenantId
permissions: {
secrets: [
'get'
'list'
'set'
'delete'
]
}
}
]
tenantId: tenantId
} }
} }
@ -128,19 +163,34 @@ module eventGrid 'bicep-templates/event-grid.bicep' = {
} }
// try to make role assignments to deploy as late as possible in order to has principalId ready // try to make role assignments to deploy as late as possible in order to has principalId ready
resource roleAssigments 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = [for r in roleAssignmentsParams: { resource roleAssigmentsPy 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = [for r in roleAssignmentsParams: {
name: guid('${resourceGroup().id}${r.suffix}') name: guid('${resourceGroup().id}${r.suffix}')
properties: { properties: {
roleDefinitionId: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/${r.role}' roleDefinitionId: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/${r.role}'
principalId: reference(pythonFunction.id, pythonFunction.apiVersion, 'Full').identity.principalId principalId: pythonFunction.outputs.principalId
} }
dependsOn: [ dependsOn: [
eventGrid eventGrid
keyVaults keyVault
serverFarms serverFarms
] ]
}] }]
// try to make role assignments to deploy as late as possible in order to has principalId ready
resource roleAssigmentsNet 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = [for r in roleAssignmentsParams: {
name: guid('${resourceGroup().id}${r.suffix}-net')
properties: {
roleDefinitionId: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Authorization/roleDefinitions/${r.role}'
principalId: netFunction.outputs.principalId
}
dependsOn: [
eventGrid
keyVault
serverFarms
]
}]
// try to make role assignments to deploy as late as possible in order to has principalId ready // try to make role assignments to deploy as late as possible in order to has principalId ready
resource readBlobUserAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = { resource readBlobUserAssignment 'Microsoft.Authorization/roleAssignments@2020-10-01-preview' = {
name: guid('${resourceGroup().id}-user_managed_idenity_read_blob') name: guid('${resourceGroup().id}-user_managed_idenity_read_blob')
@ -150,111 +200,72 @@ resource readBlobUserAssignment 'Microsoft.Authorization/roleAssignments@2020-10
} }
dependsOn: [ dependsOn: [
eventGrid eventGrid
keyVaults keyVault
serverFarms serverFarms
] ]
} }
resource pythonFunction 'Microsoft.Web/sites@2021-03-01' = {
module pythonFunction 'bicep-templates/function.bicep' = {
name: 'pythonFunction'
params: {
functions_worker_runtime: 'python'
linux_fx_version: 'Python|3.8'
functions_extension_version: '~3'
name: name name: name
app_logs_sas_url: storage.outputs.FuncSasUrlBlobAppLogs
app_func_audiences: app_func_audiences
app_func_issuer: app_func_issuer
app_insights_app_id: operationalInsights.outputs.appInsightsAppId
app_insights_key: operationalInsights.outputs.appInsightsInstrumentationKey
client_id: clientId
client_secret: clientSecret
diagnostics_log_level: diagnosticsLogLevel
func_sas_url: storage.outputs.FuncSasUrl
func_storage_resource_id: storage.outputs.FuncId
fuzz_storage_resource_id: storage.outputs.FuzzId
keyvault_name: keyVaultName
location: location location: location
kind: 'functionapp,linux' log_retention: log_retention
tags: { monitor_account_name: operationalInsights.outputs.monitorAccountName
'OWNER': owner multi_tenant_domain: multi_tenant_domain
} owner: owner
identity: { server_farm_id: serverFarms.outputs.id
type: 'SystemAssigned' signal_r_connection_string: signalR.outputs.connectionString
}
properties: {
siteConfig: {
linuxFxVersion: 'Python|3.8'
alwaysOn: true
defaultDocuments: []
httpLoggingEnabled: true
logsDirectorySizeLimit: 100
detailedErrorLoggingEnabled: true
http20Enabled: true
ftpsState: 'Disabled'
}
httpsOnly: true
serverFarmId: serverFarms.outputs.id
clientAffinityEnabled: true
} }
} }
resource funcAuthSettings 'Microsoft.Web/sites/config@2021-03-01' = { module netFunction 'bicep-templates/function.bicep' = {
name: 'authsettingsV2' name: 'netFunction'
properties: { params: {
login:{ functions_worker_runtime: 'dotnet-isolated'
tokenStore: { linux_fx_version: 'DOTNET-ISOLATED|6.0'
enabled: true functions_extension_version: '~4'
name: '${name}-net'
app_logs_sas_url: storage.outputs.FuncSasUrlBlobAppLogs
app_func_audiences: app_func_audiences
app_func_issuer: app_func_issuer
app_insights_app_id: operationalInsights.outputs.appInsightsAppId
app_insights_key: operationalInsights.outputs.appInsightsInstrumentationKey
client_id: clientId
client_secret: clientSecret
diagnostics_log_level: diagnosticsLogLevel
func_sas_url: storage.outputs.FuncSasUrl
func_storage_resource_id: storage.outputs.FuncId
fuzz_storage_resource_id: storage.outputs.FuzzId
keyvault_name: keyVaultName
location: location
log_retention: log_retention
monitor_account_name: operationalInsights.outputs.monitorAccountName
multi_tenant_domain: multi_tenant_domain
owner: owner
server_farm_id: serverFarms.outputs.id
signal_r_connection_string: signalR.outputs.connectionString
} }
} }
globalValidation: {
unauthenticatedClientAction: 'RedirectToLoginPage'
requireAuthentication: true
}
httpSettings: {
requireHttps: true
}
identityProviders: {
azureActiveDirectory: {
enabled: true
isAutoProvisioned: false
registration: {
clientId: clientId
openIdIssuer: app_func_issuer
clientSecretSettingName: 'ONEFUZZ_CLIENT_SECRET'
}
validation: {
allowedAudiences: app_func_audiences
}
}
}
}
parent: pythonFunction
}
resource funcLogs 'Microsoft.Web/sites/config@2021-03-01' = {
name: 'logs'
properties: {
applicationLogs: {
azureBlobStorage: {
level: diagnosticsLogLevel
retentionInDays: log_retention
sasUrl: storage.outputs.FuncSasUrlBlobAppLogs
}
}
}
parent: pythonFunction
}
resource pythonFunctionSettings 'Microsoft.Web/sites/config@2021-03-01' = {
name: 'appsettings'
parent: pythonFunction
properties: {
'FUNCTIONS_EXTENSION_VERSION': '~3'
'FUNCTIONS_WORKER_RUNTIME': 'python'
'FUNCTIONS_WORKER_PROCESS_COUNT': '1'
'APPINSIGHTS_INSTRUMENTATIONKEY': operationalInsights.outputs.appInsightsInstrumentationKey
'APPINSIGHTS_APPID': operationalInsights.outputs.appInsightsAppId
'ONEFUZZ_TELEMETRY': telemetry
'AzureWebJobsStorage': storage.outputs.FuncSasUrl
'MULTI_TENANT_DOMAIN': multi_tenant_domain
'AzureWebJobsDisableHomepage': 'true'
'AzureSignalRConnectionString': signalR.outputs.connectionString
'AzureSignalRServiceTransportType': 'Transient'
'ONEFUZZ_INSTANCE_NAME': name
'ONEFUZZ_INSTANCE': 'https://${name}.azurewebsites.net'
'ONEFUZZ_RESOURCE_GROUP': resourceGroup().id
'ONEFUZZ_DATA_STORAGE': storage.outputs.FuzzId
'ONEFUZZ_FUNC_STORAGE': storage.outputs.FuncId
'ONEFUZZ_MONITOR': operationalInsights.outputs.monitorAccountName
'ONEFUZZ_KEYVAULT': keyVaults.outputs.name
'ONEFUZZ_OWNER': owner
'ONEFUZZ_CLIENT_SECRET': clientSecret
}
}
output fuzz_storage string = storage.outputs.FuzzId output fuzz_storage string = storage.outputs.FuzzId
output fuzz_name string = storage.outputs.FuzzName output fuzz_name string = storage.outputs.FuzzName

View File

@ -0,0 +1,152 @@
param name string
param location string
param owner string
param server_farm_id string
param client_id string
param app_func_issuer string
param app_func_audiences array
@secure()
param app_logs_sas_url string
param app_insights_app_id string
@secure()
param app_insights_key string
@secure()
param func_sas_url string
param multi_tenant_domain string
@secure()
param signal_r_connection_string string
@description('The degree of severity for diagnostics logs.')
@allowed([
'Verbose'
'Information'
'Warning'
'Error'
])
param diagnostics_log_level string
param log_retention int
param func_storage_resource_id string
param fuzz_storage_resource_id string
param keyvault_name string
@secure()
param client_secret string
param monitor_account_name string
param linux_fx_version string
param functions_worker_runtime string
param functions_extension_version string
var telemetry = 'd7a73cf4-5a1a-4030-85e1-e5b25867e45a'
resource function 'Microsoft.Web/sites@2021-03-01' = {
name: name
location: location
kind: 'functionapp,linux'
tags: {
'OWNER': owner
}
identity: {
type: 'SystemAssigned'
}
properties: {
siteConfig: {
linuxFxVersion: linux_fx_version
alwaysOn: true
defaultDocuments: []
httpLoggingEnabled: true
logsDirectorySizeLimit: 100
detailedErrorLoggingEnabled: true
http20Enabled: true
ftpsState: 'Disabled'
}
httpsOnly: true
serverFarmId: server_farm_id
clientAffinityEnabled: true
}
}
resource funcAuthSettings 'Microsoft.Web/sites/config@2021-03-01' = {
name: 'authsettingsV2'
properties: {
login:{
tokenStore: {
enabled: true
}
}
globalValidation: {
unauthenticatedClientAction: 'RedirectToLoginPage'
requireAuthentication: true
}
httpSettings: {
requireHttps: true
}
identityProviders: {
azureActiveDirectory: {
enabled: true
isAutoProvisioned: false
registration: {
clientId: client_id
openIdIssuer: app_func_issuer
clientSecretSettingName: 'ONEFUZZ_CLIENT_SECRET'
}
validation: {
allowedAudiences: app_func_audiences
}
}
}
}
parent: function
}
resource funcLogs 'Microsoft.Web/sites/config@2021-03-01' = {
name: 'logs'
properties: {
applicationLogs: {
azureBlobStorage: {
level: diagnostics_log_level
retentionInDays: log_retention
sasUrl: app_logs_sas_url
}
}
}
parent: function
}
resource pythonFunctionSettings 'Microsoft.Web/sites/config@2021-03-01' = {
name: 'appsettings'
parent: function
properties: {
'FUNCTIONS_EXTENSION_VERSION': functions_extension_version
'FUNCTIONS_WORKER_RUNTIME': functions_worker_runtime
'FUNCTIONS_WORKER_PROCESS_COUNT': '1'
'APPINSIGHTS_INSTRUMENTATIONKEY': app_insights_key
'APPINSIGHTS_APPID': app_insights_app_id
'ONEFUZZ_TELEMETRY': telemetry
'AzureWebJobsStorage': func_sas_url
'MULTI_TENANT_DOMAIN': multi_tenant_domain
'AzureWebJobsDisableHomepage': 'true'
'AzureSignalRConnectionString': signal_r_connection_string
'AzureSignalRServiceTransportType': 'Transient'
'ONEFUZZ_INSTANCE_NAME': name
'ONEFUZZ_INSTANCE': 'https://${name}.azurewebsites.net'
'ONEFUZZ_RESOURCE_GROUP': resourceGroup().id
'ONEFUZZ_DATA_STORAGE': fuzz_storage_resource_id
'ONEFUZZ_FUNC_STORAGE': func_storage_resource_id
'ONEFUZZ_MONITOR': monitor_account_name
'ONEFUZZ_KEYVAULT': keyvault_name
'ONEFUZZ_OWNER': owner
'ONEFUZZ_CLIENT_SECRET': client_secret
}
}
output principalId string = reference(function.id, function.apiVersion, 'Full').identity.principalId

View File

@ -1,39 +0,0 @@
param tenant_id string
param principal_id string
param location string
var keyVaultName = 'of-kv-${uniqueString(resourceGroup().id)}'
resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' = {
name: keyVaultName
location: location
properties: {
enabledForDiskEncryption: false
enabledForTemplateDeployment: true
sku: {
family: 'A'
name: 'standard'
}
networkAcls: {
defaultAction: 'Allow'
bypass: 'AzureServices'
}
tenantId: tenant_id
accessPolicies: [
{
objectId: principal_id
tenantId: tenant_id
permissions: {
secrets: [
'get'
'list'
'set'
'delete'
]
}
}
]
}
}
output name string = keyVaultName

View File

@ -24,7 +24,7 @@ var storageAccountFuncContainersParams = [
] ]
var storageAccountFuncQueuesParams = [ var storageAccountFuncQueuesParams = [
'file-chages' 'file-changes'
'task-heartbeat' 'task-heartbeat'
'node-heartbeat' 'node-heartbeat'
'proxy' 'proxy'