I have the following resource defined in a bicep module for the setting of function app config:
resource functionAppAppsettings 'Microsoft.Web/sites/config#2018-11-01' = {
name: '${functionAppName}/appsettings'
properties: {
AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccountId, '2019-06-01').keys[0].value}'
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccountId, '2019-06-01').keys[0].value}'
FUNCTIONS_EXTENSION_VERSION: '~3'
FUNCTIONS_WORKER_RUNTIME: 'dotnet'
APPINSIGHTS_INSTRUMENTATIONKEY: appInsightsKey
WEBSITE_CONTENTSHARE: toLower(functionAppName)
ipSecurityRestrictions: [
{
ipAddress: '${pcPublicIp}/32'
action: 'Allow'
tag: 'Default'
priority: 101
name: 'laptop ip'
description: 'Allow requests from test laptop'
}
]
}
}
If I comment out the ipSecurityRestrictions block then it works ok but with it in, I get the following error:
"Code": "BadRequest",
"Message": "The parameter properties has an invalid value.",
"Target": null,
"Details": [
{
"Message": "The parameter properties has an invalid value."
},
{
"Code": "BadRequest"
},
{
"ErrorEntity": {
"ExtendedCode": "51008",
"MessageTemplate": "The parameter {0} has an invalid value.",
"Parameters": [
"properties"
],
"Code": "BadRequest",
"Message": "The parameter properties has an invalid value."
}
}
The pcPublicIp variable is a string containing a ip v4 address.
Can you anyone see what I have wrong?
You would need to use a web config section to configure ipSecurityRestrictions (see documentation):
resource functionApp 'Microsoft.Web/sites#2018-11-01' existing = {
name: functionAppName
}
// Web
resource webConfig 'Microsoft.Web/sites/config#2018-11-01' = {
parent: functionApp
name: 'web'
properties: {
ipSecurityRestrictions: [
{
ipAddress: '${pcPublicIp}/32'
action: 'Allow'
tag: 'Default'
priority: 101
name: 'laptop ip'
description: 'Allow requests from test laptop'
}
]
}
}
// AppSettings
resource appSettings 'Microsoft.Web/sites/config#2018-11-01' = {
parent: functionApp
name: 'appsettings'
properties: {
AzureWebJobsStorage: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccountId, '2019-06-01').keys[0].value}'
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(storageAccountId, '2019-06-01').keys[0].value}'
FUNCTIONS_EXTENSION_VERSION: '~3'
FUNCTIONS_WORKER_RUNTIME: 'dotnet'
APPINSIGHTS_INSTRUMENTATIONKEY: appInsightsKey
WEBSITE_CONTENTSHARE: toLower(functionApp.name)
}
}
Related
We have a Azure DevOps pipeline that we are using to deploy infrastructure to Azure using bicep files. In Azure, We have create a App Registration Service Principle and added it as a contributor to our Subscription, which we use as a Service Connection within Azure DevOps to allow us to deploy the required infrastructure.
In the pipeline we are creating a Key Vault and adding the Service Principle to the Access Policies. Further in the Bicep I am trying to get a secret to use as the password for another infrastructure resource, but I keep getting the following error:
{
"status": "Failed",
"error": {
"code": "DeploymentFailed",
"message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.",
"details": [
{
"code": "Forbidden",
"message": "{\r\n \"error\": {\r\n \"code\": \"KeyVaultParameterReferenceSecretRetrieveFailed\",\r\n \"message\": \"The secret of KeyVault parameter 'password' cannot be retrieved. Http status code: 'Forbidden'. Error message: 'Access denied to first party service.\\r\\nCaller: name=ARM;tid=f8cdef31...;appid=797f4846...;oid=f248a218...;iss=https://sts.windows.net/f8cdef31.../\\r\\nVault: kv-kf-web-shared-fea-ne;location=northeurope'. Please see https://aka.ms/arm-keyvault for usage details.\"\r\n }\r\n}"
}
]
}
}
main.bicep:
// Module: Key Vault
module keyVaultModule '../../Bicep.Modules/keyVault.bicep' = {
name: 'keyVaultDeployment'
params: {
application: '${application}-shared'
environment: environment
location: location
tags: tags
}
scope: resourceGroup
}
resource keyVault 'Microsoft.KeyVault/vaults#2022-07-01' existing = {
name: keyVaultModule.outputs.name
scope: resourceGroup
}
// Module: SQL Server
module databaseServerModule '../../Bicep.Modules/databaseServer.bicep' = {
name: 'databaseServerDeployment'
params: {
application: '${application}-shared'
environment: environment
location: location
tags: tags
keyVaultName: keyVaultModule.outputs.name
password: keyVault.getSecret('password-databaseServer-sql-${application}-shared-${environment}-${shortlocation}')
}
scope: resourceGroup
}
/keyVault.bicep
// Resource - Function App
resource keyVault 'Microsoft.KeyVault/vaults#2022-07-01' = {
name: name
location: location
tags: tags
properties: {
accessPolicies: [
{
objectId: '{ AAD-GRP-Dev-DevOps Object Id }'
permissions: {
certificates: [
'all'
]
keys: [
'all'
]
secrets: [
'all'
]
storage: [
'all'
]
}
tenantId: subscription().tenantId
}
{
objectId: '{ Windows Azure Service Management API Object Id }'
permissions: {
certificates: [
'all'
]
keys: [
'all'
]
secrets: [
'all'
]
storage: [
'all'
]
}
tenantId: subscription().tenantId
}
{
objectId: '{ Windows Azure Service Management API Object Id }'
permissions: {
certificates: [
'all'
]
keys: [
'all'
]
secrets: [
'all'
]
storage: [
'all'
]
}
tenantId: subscription().tenantId
}
]
sku: {
family: 'A'
name: 'standard'
}
tenantId: subscription().tenantId
}
}
Key Vault Access Policies:
In the access configuration of Key Vault check the Azure Resource Manager for template deployment, and probably for VM if needed.
Enable Template deployment for Key Vault
I am trying to get a logic app to read messages from a service bus topic. I am getting the error with the connection in logic app designer as :
Could not retrieve values. Error code: 'Unauthorized', Message: 'The remote server returned an error: (401) Unauthorized. Manage,EntityRead claims required for this operation. TrackingId:, SystemTracker:, Timestamp: clientRequestId: '. More diagnostic information: x-ms-client-request-id is ''.
currently I have tried the following in my cicd pipeline:
Grant permission to the logic app standard to access the connection api
resource servicebusConnectorAccessPolicy 'Microsoft.Web/connections/accessPolicies#2018-07-01-preview' = {
name: '${servicebusConnector.name}/${logicAppName}'
location: location
properties: {
principal: {
type: 'ActiveDirectory'
identity: {
tenantId: subscription().tenantId
objectId: logicApp.identity.principalId
}
}
}
}
Get this error:
ERROR: {"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"BadRequest","message":"{\r\n "error": {\r\n "code": "InvalidTemplate",\r\n "message": "Unable to process template language expressions for resource '/subscriptions//resourceGroups//providers/Microsoft.Web/connections/servicebus/accessPolicies/' at line '124' and column '5'. 'The language expression property 'principalId' doesn't exist, available properties are 'type, userAssignedIdentities'.'",\r\n "additionalInfo": [\r\n {\r\n "type": "TemplateViolation",\r\n "info": {\r\n "lineNumber": 124,\r\n "linePosition": 5,\r\n "path": ""\r\n }\r\n }\r\n ]\r\n }\r\n}"}]}}
also:
resource logicAppServiceBusRoleAssignment 'Microsoft.Authorization/roleAssignments#2020-10-01-preview' = {
scope: serviceBusNamespace
name: guid('${serviceBusNamespaceName}-${roleDefinitionId}')
properties: {
principalType: 'ServicePrincipal'
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleDefinitionId)
principalId: logicApp.identity.principalId
}
}
which yields this error:
ERROR: {"code": "InvalidTemplateDeployment", "message": "The template deployment failed with error: 'Authorization failed for template resource '' of type 'Microsoft.Authorization/roleAssignments'. The client '' with object id '' does not have permission to perform action 'Microsoft.Authorization/roleAssignments/write' at scope '/subscriptions//resourceGroups//providers/Microsoft.ServiceBus/namespaces//providers/Microsoft.Authorization/roleAssignments/'.'."}
for the role, it lacks permissions to add the role.
my logic app bicep file is as follows:
param logicAppName string // The name of the logic app to create.
param location string //Location for all resources.
param workflowDefinition object // the workflow schema in json
param connectorName string
param serviceBusNamespaceName string
resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities#2022-01-31-preview' = {
name: <managedIDname>
location: location
}
resource servicebusConnector 'Microsoft.Web/connections#2016-06-01' = {
name: connectorName
location: location
kind: 'V2'
properties: {
api: {
id: concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', resourceGroup().location, '/managedApis/servicebus')
}
displayName: connectorName
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
namespaceEndpoint: {
value: '<endpoint>'
}
}
}
}
}
resource logicApp 'Microsoft.Logic/workflows#2019-05-01' = {
name: logicAppName
location: location
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${managedIdentity.id}': {}
}
}
tags: {
displayName: logicAppName
}
properties: {
state: 'Enabled'
definition: workflowDefinition.definition
parameters: workflowDefinition.parameters
}
}
and for the service bus I have the following code:
param serviceBusNamespaceName string //Name of the Service Bus namespace
param serviceBusQueueName string // Name of the Queue
param location string // Location for all resources.
param topicApprovalName string // name of the topic for approval
param topicApprovalSubscriptionName string // name of the topic subscription
param connectorName string // name of the connector
param logicAppName string
param roleDefinitionId string = '8e3af657-a8ff-443c-a75c-2fe8c4bcb635'
resource logicApp 'Microsoft.Logic/workflows#2019-05-01' existing = {
name: logicAppName
}
resource lamanagedidentity 'Microsoft.ManagedIdentity/userAssignedIdentities#2022-01-31-preview' existing = {
name: 'managedIdentity'
}
resource serviceBusNamespace 'Microsoft.ServiceBus/namespaces#2022-01-01-preview' = {
name: serviceBusNamespaceName
location: location
sku: {
name: 'Standard'
}
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${lamanagedidentity.id}': {}
}
}
properties: {}
}
resource serviceBusQueue 'Microsoft.ServiceBus/namespaces/queues#2022-01-01-preview' = {
parent: serviceBusNamespace
name: serviceBusQueueName
properties: {
lockDuration: 'PT5M'
maxSizeInMegabytes: 1024
requiresDuplicateDetection: false
requiresSession: false
defaultMessageTimeToLive: 'P10675199DT2H48M5.4775807S'
deadLetteringOnMessageExpiration: false
duplicateDetectionHistoryTimeWindow: 'PT10M'
maxDeliveryCount: 10
autoDeleteOnIdle: 'P10675199DT2H48M5.4775807S'
enablePartitioning: false
enableExpress: false
}
}
resource topic 'Microsoft.ServiceBus/namespaces/topics#2021-11-01' = {
name: topicApprovalName
parent: serviceBusNamespace
}
resource topicsubscription 'Microsoft.ServiceBus/namespaces/topics/subscriptions#2022-01-01-preview' = {
name: topicApprovalSubscriptionName
parent: topic
}
resource sbNamespaceAuthRules 'Microsoft.ServiceBus/namespaces/AuthorizationRules#2022-01-01-preview' = {
name: <auth name>
parent: serviceBusNamespace
properties: {
rights: [
'Listen'
'Manage'
'Send'
]
}
}
resource servicebusConnector 'Microsoft.Web/connections#2018-07-01-preview' = {
name: connectorName
location: location
kind: 'V2'
properties: {
api: {
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
displayName: connectorName
parameterValueSet: {
name: <name>
values: {
namespaceEndpoint: {
value: '<endpoint>'
}
}
}
}
}
// Grant permission to the logic app standard to access the connection api
resource servicebusConnectorAccessPolicy 'Microsoft.Web/connections/accessPolicies#2018-07-01-preview' = {
name: '${servicebusConnector.name}/${logicAppName}'
location: location
properties: {
principal: {
type: 'ActiveDirectory'
identity: {
tenantId: subscription().tenantId
objectId: logicApp.identity.principalId
}
}
}
}
//output connectionRuntimeUrl string = reference(servicebusConnector.id, servicebusConnector.apiVersion, 'full').properties.connectionRuntimeUrl
Not sure why this isn't working... the issue that I'm landing on is the object id of this:
resource servicebusConnectorAccessPolicy 'Microsoft.Web/connections/accessPolicies#2018-07-01-preview' = {
name: '${servicebusConnector.name}/${logicAppName}'
location: location
properties: {
principal: {
type: 'ActiveDirectory'
identity: {
tenantId: subscription().tenantId
objectId: logicApp.identity.principalId
}
}
}
}
any help or advice would be welcome, I've been bashing my head against this for three days, and it just won't work.
thank you very much
I tried using a keyvault and connecting with a primary connection string, this did not work.
I have tried managed identity and roles, but both are not working for me.
it can find the connection, but gives an access error as cited above.
I was expecting for the connection to be authorized and for there to not be an error with the access policy.
I encountered this error in the bicep file while creating function app with VNET integration. My Vnet is in another resource group named 'tst-vnet' separate from my function app. Is there a way to resolve this? Here is the code snippet:
resource functionApp 'Microsoft.Web/sites#2022-03-01' = {
name: functionAppName
location: location
tags: tags
kind: 'functionapp'
identity: {
type: 'SystemAssigned'
}
properties: {
httpsOnly: true
serverFarmId: functionAppHostingPlan.id
clientAffinityEnabled: true
publicNetworkAccess: 'Disabled'
siteConfig: {
appSettings: [
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${functionAppStorageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(functionAppStorageAccount.id, functionAppStorageAccount.apiVersion).keys[0].value}'
}
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: runtimeStackVersion
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: runtimeStack
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${functionAppStorageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${listKeys(functionAppStorageAccount.id, functionAppStorageAccount.apiVersion).keys[0].value}'
}
{
name: 'WEBSITE_CONTENTSHARE'
value: 'functionapp'
}
{
name: 'WEBSITE_VNET_ROUTE_ALL'
value: '1'
}
{
name: 'WEBSITE_DNS_SERVER'
value: '168.63.129.16'
}
{
name: 'WEBSITE_CONTENTOVERVNET'
value: '1'
}
]
minTlsVersion: '1.2'
linuxFxVersion: linuxFxVersion
ftpsState: 'FtpsOnly'
}
}
}
I created a module to in order to use a resource group scope in order to reference the 'tst-vnet'
module networkConfig 'modules/network-config.bicep' = {
name: '${deploymentPrefix}-fn-networkcfg'
dependsOn: [
functionApp
]
scope: resourceGroup(pvtResourceGroupName)
params: {
functionAppName: functionAppName
privateBackendSubnet: privateBackendSubnet
privateEndpointVNet: privateEndpointVNet
privateBackendSubnetCIDR: privateBackendSubnetCIDR
}
}
This is the content of network-config.bicep
resource networkConfig 'Microsoft.Web/sites/networkConfig#2022-03-01' = {
name: '${functionAppName}/virtualNetwork'
properties: {
subnetResourceId: resourceId('Microsoft.Network/virtualNetworks/subnets', privateEndpointVNet, privateBackendSubnet)
swiftSupported: true
}
}
Full error from resource group deployment
{
"status": "Failed",
"error": {
"code": "DeploymentFailed",
"message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
"details": [
{
"code": "NotFound",
"message": "{\r\n "error": {\r\n "code": "ParentResourceNotFound",\r\n "message": "Can not perform requested operation on nested resource. Parent resource 'ase-data-tst-edp-fn-001' not found."\r\n }\r\n}"
}
]
When declaring a module, you can set a scope for the module that is different than the scope for the containing Bicep file. In your scenario, as you have existing virtual network, which is different scope, the virtual network should be declared in separate module. For your reference, you can use below template to deploy the function app integrating with virtual network which is in another resource group.
main.bicep file
#description('Location for all resources except Application Insights.')
param location string = resourceGroup().location
#description('Location for Application Insights.')
param appInsightsLocation string
#description('The language worker runtime to load in the function app.')
#allowed([
'node'
'dotnet'
'java'
])
param runtime string = 'node'
#description('The name of the function app that you wish to create.')
param appName string = 'fnapp${uniqueString(resourceGroup().id)}'
#description('Storage Account type')
#allowed([
'Standard_LRS'
'Standard_GRS'
'Standard_RAGRS'
])
param storageAccountType string = 'Standard_LRS'
#description('The name of the virtual network to be linked.')
param vnetName string
#description('The name of the subnet to be created within the virtual network.')
param subnetName string
#description('The name of the resource group where existing virtual network exists.')
param vnresourceGroup string
var functionAppName = appName
var hostingPlanName = appName
var storageAccountName = '${uniqueString(resourceGroup().id)}azfunctions'
var functionWorkerRuntime = runtime
resource virtualNetwork 'Microsoft.Network/virtualNetworks#2020-06-01' existing = {
name: vnetName
scope: resourceGroup(vnresourceGroup)
}
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-04-01' = {
name: storageAccountName
location: location
sku: {
name: storageAccountType
}
kind: 'StorageV2'
}
resource appInsights 'Microsoft.Insights/components#2020-02-02' = {
name: functionAppName
location: appInsightsLocation
kind: 'web'
properties: {
Application_Type: 'web'
}
}
resource serverFarm 'Microsoft.Web/serverfarms#2020-06-01' = {
name: hostingPlanName
location: location
sku: {
name: 'EP1'
tier: 'ElasticPremium'
}
kind: 'elastic'
properties: {
maximumElasticWorkerCount: 20
}
}
resource function 'Microsoft.Web/sites#2020-06-01' = {
name: functionAppName
location: location
kind: 'functionapp'
properties: {
serverFarmId: serverFarm.id
siteConfig: {
appSettings: [
{
name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
value: appInsights.properties.InstrumentationKey
}
{
name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
value: 'InstrumentationKey=${appInsights.properties.InstrumentationKey}'
}
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccount.name};EndpointSuffix= ${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
}
{
name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value};'
}
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: '~3'
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: functionWorkerRuntime
}
{
name: 'WEBSITE_NODE_DEFAULT_VERSION'
value: '~12'
}
]
}
}
dependsOn: [
virtualNetwork
]
}
resource networkConfig 'Microsoft.Web/sites/networkConfig#2020-06-01' = {
parent: function
name: 'virtualNetwork'
properties: {
subnetResourceId: subnet.outputs.subnetId
swiftSupported: true
}
dependsOn: [
subnet
]
}
module subnet 'modules/subnet.bicep' = {
name: subnetName
scope: resourceGroup(vnresourceGroup)
params: {
subnetName: subnetName
subnetPrefix: '10.2.1.0/24'
vnetName: vnetName
}
}
subnet.bicep
#description('The name of the virtual network to be linked.')
param vnetName string
#description('The name of the subnet to be created within the virtual network.')
param subnetName string
#description('The address Prefix of subnet to be created within the virtual network.')
param subnetPrefix string
param deploySubnet bool = true
resource VNET 'Microsoft.Network/virtualNetworks#2021-02-01' existing = {
name: vnetName
}
resource Subnets 'Microsoft.Network/virtualNetworks/subnets#2020-11-01'= if (deploySubnet) {
name: subnetName
parent: VNET
properties: {
addressPrefix: subnetPrefix
privateEndpointNetworkPolicies: 'Disabled'
privateLinkServiceNetworkPolicies: 'Enabled'
delegations: [
{
name: 'Microsoft.Web.serverFarms'
properties: {
serviceName: 'Microsoft.Web/serverFarms'
}
}
]
}
}
output subnetId string = deploySubnet ? Subnets.id:''
For a project I want to deploy three related resources to Azure through Bicep templates: 1) App Service with System Assigned Managed Identity, 2) Key Vault and 3) Access policy for the App Service (step 1) to the Key Vault (step 2).
The AppService deployment outputs the principalId of the System Assigned Identity which is then later on used when deploying the KeyVaultAccessPolicy.
However, when I run the AZ CLI (az deployment sub create --location WestEurope --template-file ./main.bicep --parameters ./parameters/parameters-dev.json)
to deploy this to Azure I get the following error:
'The language expression property 'outputs' doesn't exist, available properties are 'templateHash, parameters, mode, provisioningState, timestamp, duration, correlationId, providers, dependencies, outputResources'.
Does anyone have an idea why referencing the principalId of the App Service does not work here? Many thanks for any help.
Modules and main.bicep:
main.bicep
module appService 'modules/appService.bicep' = {
name: 'deployAppService'
scope: resourceGroup(appServiceResourceGroup)
params: {
name: appServiceName
location: appServiceLocation
alwaysOn: appServiceAlwaysOn
apimIpAddress: appServiceApimIpAddress
appServicePlanResourceGroup: appServicePlanResourceGroup
appServicePlanName: appServicePlanName
}
}
module keyVault 'modules/keyVault.bicep' = {
name: 'deployKeyVault'
scope: resourceGroup(appServiceResourceGroup)
params: {
name: keyVaultName
dependsOn: [ appService ]
location: appServiceLocation
}
}
module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = {
name: 'deployKeyVaultAccessPolicy'
scope: resourceGroup(appServiceResourceGroup)
params: {
name: '${appServiceName}-ap'
dependsOn: [ keyVault ]
objectId: appService.outputs.appServiceManagedIdentity
}
}
appService.bicep
resource appService 'Microsoft.Web/sites#2020-12-01' = {
name: name
location: location
kind: 'app'
identity: {
type: 'SystemAssigned'
}
properties: {
serverFarmId: '${subscription().id}/resourceGroups/${appServicePlanResourceGroup}/providers/Microsoft.Web/serverfarms/${appServicePlanName}'
enabled: true
}
}
output appServiceManagedIdentity string = appService.identity.principalId
keyVault.bicep
resource keyVault 'Microsoft.KeyVault/vaults#2022-07-01' = {
name: name
location: location
dependsOn: dependsOn
properties: {
enabledForDeployment: true
enabledForTemplateDeployment: true
enabledForDiskEncryption: true
tenantId: subscription().tenantId
accessPolicies: []
sku: {
name: 'standard'
family: 'A'
}
}
}
keyVaultAccessPolicy.bicep
resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies#2022-07-01' = {
name: name
dependsOn: dependsOn
properties: {
accessPolicies: [
{
tenantId: subscription().tenantId
objectId: objectId
permissions: {
secrets: [
'get'
]
}
}
]
}
}
Already found the answer:
I missed that modules already contain an dependsOn property and so there is no need to pass the dependencies as param.
The KeyVaultAccessPolicy's name did not contain a reference to the parent resource (KeyVault), see name: '${keyVaultName}/add' below
See working modules and main.bicep below:
main.bicep
module appService 'modules/appService.bicep' = {
name: 'deployAppService'
scope: resourceGroup(appServiceResourceGroup)
params: {
name: appServiceName
location: appServiceLocation
alwaysOn: appServiceAlwaysOn
apimIpAddress: appServiceApimIpAddress
appServicePlanResourceGroup: appServicePlanResourceGroup
appServicePlanName: appServicePlanName
}
}
module keyVault 'modules/keyVault.bicep' = {
scope: resourceGroup(appServiceResourceGroup)
name: 'keyVaultDeploy'
params: {
location: appServiceLocation
name: keyVaultName
}
}
module keyVaultAccessPolicy 'modules/keyVaultAccessPolicy.bicep' = {
scope: resourceGroup(appServiceResourceGroup)
name: 'keyVaultAccessPolicyDeploy'
dependsOn: [
keyVault
]
params: {
keyVaultName: keyVaultName
objectId: appService.outputs.appServiceManagedIdentity
}
}
appService.bicep
resource appService 'Microsoft.Web/sites#2020-12-01' = {
name: name
location: location
kind: 'app'
identity: {
type: 'SystemAssigned'
}
properties: {
// left out
}
}
output appServiceManagedIdentity string = appService.identity.principalId
keyVault.bicep
resource keyVault 'Microsoft.KeyVault/vaults#2022-07-01' = {
name: name
location: location
properties: {
enabledForDeployment: true
enabledForTemplateDeployment: true
enabledForDiskEncryption: true
tenantId: subscription().tenantId
accessPolicies: []
sku: {
name: 'standard'
family: 'A'
}
}
}
keyVaultAccessPolicy.bicep
resource keyVaultAccessPolicy 'Microsoft.KeyVault/vaults/accessPolicies#2022-07-01' = {
name: '${keyVaultName}/add'
properties: {
accessPolicies: [
{
tenantId: subscription().tenantId
objectId: objectId
permissions: {
secrets: [
'get'
]
}
}
]
}
}
Just for a heads up you don't need to pass these stuffs with parameters.
Just use the existing tag with the scope it will be easier to get datafrom any resource.
https://learn.microsoft.com/en-us/azure/azure-resource-manager/bicep/existing-resource#different-scope
I am trying to create logicapp api connnection for service bus using Bicep, below is the bicep code.
resource ServicebusApiCon 'Microsoft.Web/connections#2016-06-01' = {
name: 'servicebus123'
location: Location
kind: 'V2'
properties: {
displayName: 'servicebus'
api: {
name: 'servicebus'
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${Location}/managedApis/servicebus'
type: 'Microsoft.Web/locations/managedApis'
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
namespaceEndpoint: {
value: 'https://servicebus.servicebus.windows.net:443/'
}
}
}
}
}
}
for storage account:
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
accountName: 'storageaccountname'
}
}
for keyvault:
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
vaultName: 'keyvaultname'
}
}
I am getting below error while deploying it. could you please someone help me if something is missing or wrong ?
**{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource
deployment operation failed. Please list deployment operations for details. Please see
https://aka.ms/DeployOperations for usage details.","details":
[{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\":
\"InvalidRequestContent\",\r\n \"message\": \"The request content is not valid and could
not be deserialized: 'Could not find member 'parameterValueSet' on object of type
'ManagedApiReference'. Path 'parameterValueSet', line 1, position 258.'.\"\r\n
}\r\n}"}]}}**
The api-version should be 2018-07-01-preview :
resource servicebusConnector 'Microsoft.Web/connections#2018-07-01-preview' = {
name: 'servicebus123'
location: location
kind: 'V2'
properties: {
api: {
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
displayName: 'servicebus'
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
namespaceEndpoint: {
value: 'sb://${servicebusName}.servicebus.windows.net/'
}
}
}
}
}