Home > Net >  Azure Bicep - Timing of Dependent Module
Azure Bicep - Timing of Dependent Module

Time:09-21

I'd like a module that could add a fixed set of ip restriction rules to an existing app service (function app in this case).

I have added a call to a "ipSecurityRestrictions" module from my main.bicep as follows:

module ipRestrictions 'common.appSvc.ipSecurityRestrictions.bicep' = {
  scope: resourceGroup(utrnRg)
  name: 'ipRestrictionsDeploy'
  params: {
    appSvcName: functionAppName
    existingIpSecurityRestrictions: reference(resourceId('Microsoft.Web/sites/config', functionAppName, 'web'), '2021-02-01').ipSecurityRestrictions
  }
  dependsOn: [
    functionAppDeploy
  ]
}

The code for the "ipSecurityRetrictions" module is:

param appSvcName string
param existingIpSecurityRestrictions array = []

resource appSvc 'Microsoft.Web/sites@2021-02-01' existing = {
  name: appSvcName
}

var proxyIpAddresses = ['xxx.xxx.xxx.250/32','xxx.xxx.xxx.245/32','xxx.xxx.xxx.251/32']

var proxyIpRestrictions = [for (ip,i) in proxyIpAddresses: {
  ipAddress: ip
  action: 'Allow'
  tag: 'Default'
  priority: 900   i
  name: 'ProxyIp_${i}'
  description: 'Allow request from proxy ${i}'
}]

resource sitesConfig 'Microsoft.Web/sites/config@2021-02-01' = {
  name: 'web'
  parent: appSvc
  properties: {
    ipSecurityRestrictions: concat(existingIpSecurityRestrictions, proxyIpRestrictions)
  }
}

The call to the function app module is as follows:

module functionAppDeploy 'utrngen.functionApp.bicep' = {
name: 'functionAppDeploy'
scope: resourceGroup(utrnRg)
params: {
  pcPublicIp: pcPublicIp
  functionAppName: functionAppName
}
dependsOn: [
  appPlanDeploy
  storageAccountDeploy
]
}

The function app moddule has a sites/config resource to create ipSecurityRestrictions as follows:

resource sitesConfig 'Microsoft.Web/sites/config@2021-02-01' = {
    name: 'web'
    parent: functionApp
    properties: {
      ipSecurityRestrictions: [
        {
          ipAddress: '${pcPublicIp}/32'
          action: 'Allow'
          tag: 'Default'
          priority: 101
          name: 'laptop ip'
          description: 'Allow requests from test laptop'
        }
      ]
    }

The problem is, when main.bicep is run, it only adds the new set of rules to those that already existed; any rules specified in the function app module (in this case the one for pcPublicIp) are not added.

I guess this is because at the time the call to the ipRestrictions module is made from main.bicep, the ipSecurityRestrictions from the function app module have not yet been created; and so the following function call only returns what's present before the main.bicep is run:

existingIpSecurityRestrictions: reference(resourceId('Microsoft.Web/sites/config', functionAppName, 'web'), '2021-02-01').ipSecurityRestrictions 

So I think bicep is working as expected but curious if there's a solution this this problem? I could simply pass in the dedicated ip restriction rules for the function app as a parameter to the shared ipSecurityRestrictions module but that has a bad smell, since it breaks single responsibility for the ipSecurityRestrictions module. It would no longer be responsible for just adding the ip restrictions that are common to all our app services.

CodePudding user response:

You could move the call to the common module inside the functionapp module:

// utrngen.functionApp.bicep
... 
module ipRestrictions 'common.appSvc.ipSecurityRestrictions.bicep' = {
  name: 'ipRestrictionsDeploy-${functionAppName}'
  params: {
    appSvcName: functionApp.name
    existingIpSecurityRestrictions: reference(resourceId('Microsoft.Web/sites/config', functionApp.name, 'web'), '2021-02-01').ipSecurityRestrictions
  }
}

Or you could return the ipSecurityRestrictions from your function app module and use it in your main:

// utrngen.functionApp.bicep
...

output ipSecurityRestrictions array = sitesConfig.properties.ipSecurityRestrictions

// main.bicep
...

module ipRestrictions 'common.appSvc.ipSecurityRestrictions.bicep' = {
  name: 'ipRestrictionsDeploy-${functionAppName}'
  params: {
    appSvcName: functionAppName
    existingIpSecurityRestrictions: functionAppDeploy.outputs.ipSecurityRestrictions
  }
}

Or you could wrap the call to the ip restriction module inside another module

// common.appSvc.ipSecurityRestrictions-wrapper.bicep

param appSvcName string

module ipRestrictions 'common.appSvc.ipSecurityRestrictions.bicep' = {
  name: 'ipRestrictionsDeploy-${appSvcName}'
  params: {
    appSvcName: appSvcName
    existingIpSecurityRestrictions: reference(resourceId('Microsoft.Web/sites/config', appSvcName, 'web'), '2021-02-01').ipSecurityRestrictions 
  }
}

// main.bicep
...

module ipRestrictions 'common.appSvc.ipSecurityRestrictions-wrapper.bicep' = {
  name: 'ipRestrictionsDeploy-${functionAppName}'
  params: {
    appSvcName: functionAppName
  }
  dependsOn: [ functionAppDeploy ]
}
  • Related