azureazure-logic-appsazure-bicepdataverse

Logic App Connector Policy throws "Property Immutable" error


There is one Logic App Standard which uses a connector to Dataverse. An Access Policy is needed so that Workflows from the Logic App can use the connector. Below are the Bicep files, except the Service Plan which I don't have access to. Using various quickstart templates from Azure repos do not seem to solve the issue.

The question is why is this error popping up and what can be done to be solved?

The error is thrown only when the Access Policy is added and it looks like:

"errorCode: PropertyImmutable. Message: The property 'ConnectionAceStorageEntity.PrincipalId' is immutable."

Bicep for Connector:

param DataverseConnectionClient string
param DataverseConnectionName string
param DataverseConnectionTenant string
param Location string

@secure()
param DataverseConnectionSecret string

resource DataverseConnection 'Microsoft.Web/connections@2016-06-01' = {
  // This property may give a warning but the it should work and passed further
  // https://github.com/Azure/bicep/issues/3512
  kind: 'V2'
  name: DataverseConnectionName
  location: Location
  properties: {
    displayName: DataverseConnectionName
    parameterValues: {
      'token:TenantId': DataverseConnectionTenant
      'token:clientId': DataverseConnectionClient
      'token:grantType': 'client_credentials'
      'token:clientSecret': DataverseConnectionSecret
    }
    api: {
      name: 'commondataservice'
      displayName: 'Microsoft Dataverse (legacy)'
      description: 'Provides access to the environment database in Microsoft Dataverse.'
      category: 'Standard'
      id: '/subscriptions/${subscription().subscriptionId}/providers/Microsoft.Web/locations/${Location}/managedApis/commondataservice'
      type: 'Microsoft.Web/locations/managedApis'
    }
  }
}

// This reference may give a warning but the top level property 'connectionRuntimeUrl' should be offered back
// https://github.com/Azure/bicep/issues/3494
output connectionRuntimeUrl string = DataverseConnection.properties.connectionRuntimeUrl

Bicep for Logic App:

    resource LogicAppSite 'Microsoft.Web/sites@2022-09-01' = {
  name: LogicAppSiteName
  location: LogicAppLocation
  tags: {
    'hidden-link: /app-insights-resource-id': '/subscriptions/${subscription().subscriptionId}/resourceGroups/${resourceGroup().name}/providers/Microsoft.Insights/components/${AppInsightsName}'
  }
  kind: 'functionapp,workflowapp'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    enabled: true
    serverFarmId: ServerFarmId
    reserved: false
    isXenon: false
    hyperV: false
    vnetRouteAllEnabled: false
    vnetImagePullEnabled: false
    vnetContentShareEnabled: false
    siteConfig: {
      numberOfWorkers: 1
      acrUseManagedIdentityCreds: false
      alwaysOn: false
      http20Enabled: false
      appSettings: [
        {
          name: 'APP_KIND'
          value: 'workflowApp'
        }
        {
          name: 'AzureFunctionsJobHost__extensionBundle__id'
          value: 'Microsoft.Azure.Functions.ExtensionBundle.Workflows'
        }
        {
          name: 'AzureFunctionsJobHost__extensionBundle__version'
          value: '[1.*, 2.0.0)'
        }
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${StorageAccountName};AccountKey=${listKeys('${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${StorageAccountName}', '2019-06-01').keys[0].value};EndpointSuffix=core.windows.net'
        }
        // {
        //   name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
        //   value: 'DefaultEndpointsProtocol=https;AccountName=${StorageAccountName};AccountKey=${listKeys('${resourceGroup().id}/providers/Microsoft.Storage/storageAccounts/${StorageAccountName}', '2019-06-01').keys[0].value};EndpointSuffix=core.windows.net'
        // }
        // {
        //   name: 'WEBSITE_CONTENTSHARE'
        //   value: LogicAppSiteName
        // }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~4'
        }
        {
          name: 'WEBSITE_CONTENTOVERVNET'
          value: '1'
        }
        {
          name: 'APPLICATIONINSIGHTS_CONNECTION_STRING'
          value: reference(resourceId('Microsoft.Insights/components', AppInsightsName), '2020-02-02').ConnectionString
        }
        {
          name: 'WORKFLOWS_SUBSCRIPTION_ID'
          value: subscription().subscriptionId
        }
        {
          name: 'WORKFLOWS_LOCATION_NAME'
          value: LogicAppLocation
        }
        {
          name: 'WORKFLOWS_RESOURCE_GROUP_NAME'
          value: resourceGroup().name
        }
        {
          name: 'WORKFLOWS_DATAVERSE_CONNECTION_NAME'
          value: DataverseConnectionName
        }
        {
          name: 'WORKFLOWS_DATAVERSE_CONN_ID'
          value: DataverseConnection.id
        }
        {
          name: 'WORKFLOWS_DATAVERSE_CONN_RUNTIMEURL'
          // This reference may give a warning but the top level property 'connectionRuntimeUrl' should be offered back
          // https://github.com/Azure/bicep/issues/3494
          value: DataverseConnection.properties.connectionRuntimeUrl
        }
        {
          name: 'WORKFLOWS_DATAVERSE_URL'
          value: DataverseUrl
        }
      ]
    }
    scmSiteAlsoStopped: false
    clientAffinityEnabled: false
    clientCertEnabled: false
    clientCertMode: 'Required'
    hostNamesDisabled: false
    customDomainVerificationId: '...'
    containerSize: 1536
    dailyMemoryTimeQuota: 0
    httpsOnly: true
    redundancyMode: 'None'
    publicNetworkAccess: 'Enabled'
    storageAccountRequired: false
    keyVaultReferenceIdentity: 'SystemAssigned'
    
  }
}

resource LogicAppSiteName_web 'Microsoft.Web/sites/config@2022-09-01' = {
  parent: LogicAppSite
  name: 'web'
  properties: {
    numberOfWorkers: 1
    defaultDocuments: [
      'Default.htm'
      'Default.html'
      'Default.asp'
      'index.htm'
      'index.html'
      'iisstart.htm'
      'default.aspx'
      'index.php'
    ]
    netFrameworkVersion: 'v6.0'
    requestTracingEnabled: false
    remoteDebuggingEnabled: false
    httpLoggingEnabled: false
    acrUseManagedIdentityCreds: false
    logsDirectorySizeLimit: 35
    detailedErrorLoggingEnabled: false
    publishingUsername: LogicAppSiteName
    scmType: 'None'
    use32BitWorkerProcess: false
    webSocketsEnabled: false
    alwaysOn: false
    managedPipelineMode: 'Integrated'
    preWarmedInstanceCount: 0
    elasticWebAppScaleLimit: 0
    functionsRuntimeScaleMonitoringEnabled: true
    functionAppScaleLimit: 0
    virtualApplications: [
      {
        virtualPath: '/'
        physicalPath: 'site\\wwwroot'
        preloadEnabled: false
      }
    ]
    loadBalancing: 'LeastRequests'
    experiments: {
      rampUpRules: []
    }
    autoHealEnabled: false
    vnetRouteAllEnabled: true
    vnetPrivatePortsCount: 0
    publicNetworkAccess: 'Enabled'
    cors: {
      supportCredentials: false
    }
    localMySqlEnabled: false
    managedServiceIdentityId: 37494
    ipSecurityRestrictions: [
      {
        ipAddress: 'Any'
        action: 'Allow'
        priority: 2147483647
        name: 'Allow all'
        description: 'Allow all access'
      }
    ]
    http20Enabled: false
    minTlsVersion: '1.2'
    scmMinTlsVersion: '1.2'
    azureStorageAccounts: {}
  }
}

resource LogicAppSiteName_LogicAppSiteName_azurewebsites_net 'Microsoft.Web/sites/hostNameBindings@2022-09-01' = {
  parent: LogicAppSite
  name: '${LogicAppSiteName}.azurewebsites.net'
  properties: {
    siteName: LogicAppSiteName
    hostNameType: 'Verified'
  }
}

And finally the Bicep for Access Policy:

resource connections_dataverse_logicAppSystemAssignedIdentityObjectId 'Microsoft.Web/connections/accessPolicies@2016-06-01' = {
  name: DataversePolicyName
  parent: DataverseConnection
  location: LogicAppLocation
  properties: {
    principal: {
      type: 'ActiveDirectory'
      identity: {
        tenantId: subscription().tenantId
        objectId: LogicAppSite.identity.principalId
      }
    }
  }
}

Solution

  • Found the culprit: if the same connection is created manually, in the portal, with the same name but different PrincipalID, the ARM/Bicep deployment is not able to override it.

    Just make sure that your experiments in portal.azure.com are not overlapping the deployments from pipelines.