Getting error while creating logic app connection through Bicep - azure

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/'
}
}
}
}
}

Related

Give access to Azure Logic App in a CICD pipeline to connect to a service bus topic with managed identity

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.

Bicep -Can not perform requested operation on nested resource

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:''

How to reference System Assigned Identity in Bicep when deploying Key Vault Access Policy

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

logic app connection to storage account failing

I have created logic app storage connection using below code but unfortunately it is throwing error.
resource blobConnector 'Microsoft.Web/connections#2018-07-01-preview' = {
name: 'apic-d365-azureblob12345'
location: Location
kind: 'V2'
properties: {
alternativeParameterValues: {}
api: {
id: 'subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${Location}/managedApis/azureblob'
}
customParameterValues: {}
displayName: 'azureblob'
parameterValueSet: {
name: 'managedIdentityAuth'
values: {}
}
}
}
Role assignment:
resource blobcontributorroleassignment 'Microsoft.Authorization/roleAssignments#2020-10-01-preview' = {
name: guid(resourceGroup().id, logicappsite.id, blobcontributorroledefination.id)
properties: {
roleDefinitionId: blobcontributorroledefination.id
principalType: 'ServicePrincipal'
principalId: logicappsite.identity.principalId
}
}
below is the error it is throwing while making connection
"error": "'Operation not supported with AAD authentication, use Azure Storage Account name/key connection instead
Could someone help me if I am missing something or doing wrong.
Thanks in advance.
You also need to create an access policy to allow the logic app to access the connection api:
// Grant permission to the logic app standard to access the connection api
resource blobConnectorAccessPolicy 'Microsoft.Web/connections/accessPolicies#2018-07-01-preview' = {
name: '${blobConnector.name}/${logicappsite.name}'
location: location
properties: {
principal: {
type: 'ActiveDirectory'
identity: {
tenantId: subscription().tenantId
objectId: logicappsite.identity.principalId
}
}
}
}

Api connections(keyvault, servicebus and blob ) using managed identity through bicep

Hi I am trying to create API connections for Key Vault, service bus and storage account using bicep. unfortunately do not see clear documentation from Microsoft side.
created API connections(Azure Key Vault, Service Bus and storage account) using below code, deployment going successfully but connection gets into error state.
resource ServicebusApiCon 'Microsoft.Web/connections#2016-06-01' = {
name: 'servicebus'
location: Location
kind: 'V2'
properties: {
displayName: 'servicebus'
api: {
name: 'servicebus'
description: 'Connect to Azure Serice Bus to send and receive messages'
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/
locations/${Location}/managedApis/servicebus'
type: 'Microsoft.Web/locations/managedApis'
}
}
}
resource keyvaultApiCon 'Microsoft.Web/connections#2016-06-01' = {
name: 'keyvault'
location: Location
kind: 'V2'
properties: {
displayName: 'keyvault'
api:{
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/
locations/${Location}/managedApis/keyvault'
displayName: ' Azure key vault'
type: 'Microsoft.Web/locations/managedApis'
}
}
}
resource blobApiConnection 'Microsoft.Web/connections#2016-06-01' = {
name: 'azureblob'
location: Location
kind: 'V2'
properties: {
displayName: 'azureblob'
api: {
name: 'azureblob'
displayName: 'Azure Blob storage'
id: '/subscriptions/${subscription().subscriptionId}/providers
/Microsoft.Web/locations/${Location}/managedApis/azureblob'
}
}
}
could you please suggest me if i am doing something wrong or missing something
To be honest these connection apis are not documented at all...
Your best shot is to create them from Azure portal with the networking tab open so you can see what are the requests sent:
From there I was able to create connection for
key vault:
param logicAppName string
param location string = resourceGroup().location
param keyVaultName string
param name string = 'keyvault'
// Get a reference to the existing logic app
resource logicApp 'Microsoft.Web/sites#2021-03-01' existing = {
name: logicAppName
}
resource keyvaultConnector 'Microsoft.Web/connections#2018-07-01-preview' = {
name: name
location: location
kind: 'V2'
properties: {
displayName: name
parameterValueType: 'Alternative'
alternativeParameterValues: {
vaultName: keyVaultName
}
api: {
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${location}/managedApis/keyvault'
type: 'Microsoft.Web/locations/managedApis'
}
}
}
// Grant permission to the logic app standard to access the connection api
resource keyvaultConnectorAccessPolicy 'Microsoft.Web/connections/accessPolicies#2018-07-01-preview' = {
name: '${keyvaultConnector.name}/${logicAppName}'
location: location
properties: {
principal: {
type: 'ActiveDirectory'
identity: {
tenantId: subscription().tenantId
objectId: logicApp.identity.principalId
}
}
}
}
output connectionRuntimeUrl string = reference(keyvaultConnector.id, keyvaultConnector.apiVersion, 'full').properties.connectionRuntimeUrl
service bus:
param logicAppName string
param location string = resourceGroup().location
param servicebusName string
param name string = 'servicebus'
// Get a reference to the existing logic app
resource logicApp 'Microsoft.Web/sites#2021-03-01' existing = {
name: logicAppName
}
resource servicebusConnector 'Microsoft.Web/connections#2018-07-01-preview' = {
name: name
location: location
kind: 'V2'
properties: {
api: {
id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${location}/managedApis/servicebus'
}
displayName: name
parameterValueSet: {
name: 'managedIdentityAuth'
values: {
namespaceEndpoint: {
value: 'sb://${servicebusName}.servicebus.windows.net/'
}
}
}
}
}
// 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
You still need to grant permissions to the managed identity to access key vault or servicebus.
You also will need to update the connectionRuntimeUrl so probably create an app setting for that so it s easier to update:

Resources