azureazure-bicepinfrastructure-as-codeazure-front-door

Azure front door custom domain bicep


Here is my set up:

I have a bicep repository that has bicep templates which are called as modules in the applications which need them.

My front door (classic) template from bicep repo:

param frontDoorName string
param backEndAddress string
param frontEndEndPointName string
param backEndPoolName string

var loadBalancingSettingsName = ''
var healthProbeSettingsName = ''
var routingRuleName = ''

resource myFrontDoorResource 'Microsoft.Network/frontDoors@2021-06-01' = {
  name: frontDoorName
  location: 'global'
  properties: {
    enabledState: 'Enabled'

    frontendEndpoints: [
      {
        name: frontEndEndPointName
        properties: {
          hostName: '${frontDoorName}.azurefd.net'
          sessionAffinityEnabledState: 'Disabled'
        }
      }
    ]

    loadBalancingSettings: [
      {
        name: loadBalancingSettingsName
        properties: {
          sampleSize: 4
          successfulSamplesRequired: 2
        }
      }
    ]

    healthProbeSettings: [
      {
        name: healthProbeSettingsName
        properties: {
          path: '/'
          protocol: 'Http'
          intervalInSeconds: 120
        }
      }
    ]

    backendPools: [
      {
        name: backEndPoolName
        properties: {
          backends: [
            {
              address: backEndAddress
              backendHostHeader: backEndAddress
              httpPort: 80
              httpsPort: 443
              weight: 100
              priority: 1
              enabledState: 'Enabled'
            }
          ]
          loadBalancingSettings: {
            id: resourceId('Microsoft.Network/frontDoors/loadBalancingSettings', frontDoorName, loadBalancingSettingsName)
          }
          healthProbeSettings: {
            id: resourceId('Microsoft.Network/frontDoors/healthProbeSettings', frontDoorName, healthProbeSettingsName)
          }
        }
      }
    ]

    routingRules: [
      {
        name: routingRuleName
        properties: {
          frontendEndpoints: [
            {
              id: resourceId('Microsoft.Network/frontDoors/frontEndEndpoints', frontDoorName, frontEndEndPointName)
            }
          ]
          acceptedProtocols: [
            'Http'
            'Https'
          ]
          patternsToMatch: [
            '/*'
          ]
          routeConfiguration: {
            '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration'
            forwardingProtocol: 'MatchRequest'
            backendPool: {
              id: resourceId('Microsoft.Network/frontDoors/backEndPools', frontDoorName, backEndPoolName)
            }
          }
          enabledState: 'Enabled'
        }
      }
    ]
  }
}

Module called from application

module myFrontDoorModule 'azurefrontdoor.bicep' = {
 name: ''
 params: {
   frontDoorName: ''
   backEndAddress: ''
   frontEndEndpPintName: ''
   backEndPoolName: ''
 }
}

Now I have added one custom domain and my routing rule is updated to use the custom domain value in Frontends/domains field. Assuming I will have more custom domains, backend pools, routing rules I need help in improving it to accept array of such input params to make this dynamic in nature for other applications to use. Can someone please suggest/help me how to go about improving the above shared set up?

Updated bicep

param frontDoorName string

var loadBalancingSettingsName = 'loadBalancingSettings'
var healthProbeSettingsName = 'healthProbeSettings'

var endpoints = [
  {
    name: 'frontEndEndpoint'
    hostName: '${frontDoorName}.azurefd.net'
  }
  {
    name: 'abc'
    hostName: 'abc.com'
  }
  {
    name: 'xyz'
    hostName: 'xyz.com'
  }
]

var backendPoolArray = [
  {
    backendPoolName: 'firstbepool'
    backendAddress: 'abc.azurewebsites.net'
  }
  {
    backendPoolName: 'secondbepool'
    backendAddress: 'xyz.azurewebsites.net'
  }
]

var routingRules = [
  {
    routingRuleName: 'routingRuleOne'
    backendPoolName: 'firstbepool'
    endpointName: 'abc'
  }
  {
    routingRuleName: 'routingRuleTwo'
    backendPoolName: 'secondbepool'
    endpointName: 'xyz'
  }
]

resource frontDoorResource 'Microsoft.Network/frontDoors@2021-06-01' = {
  name: frontDoorName
  location: 'global'
  properties: {
    enabledState: 'Enabled'

    frontendEndpoints: [for endpoint in endpoints: {
      name: endpoint.name
      properties: {
        hostName: endpoint.hostName
        sessionAffinityEnabledState: 'Disabled'
      }
    }]

    loadBalancingSettings: [
      {
        name: loadBalancingSettingsName
        properties: {
          sampleSize: 4
          successfulSamplesRequired: 2
        }
      }
    ]

    healthProbeSettings: [
      {
        name: healthProbeSettingsName
        properties: {
          path: '/'
          protocol: 'Http'
          intervalInSeconds: 120
        }
      }
    ]

    backendPools: [for backendPool in backendPoolArray: {
      name: backendPool.backendPoolName
      properties: {
        backends: [
          {
            address: backendPool.backendAddress
            backendHostHeader: backendPool.backendAddress
            httpPort: 80
            httpsPort: 443
            weight: 100
            priority: 1
            enabledState: 'Enabled'
          }
        ]
        loadBalancingSettings: {
          id: resourceId('Microsoft.Network/frontDoors/loadBalancingSettings', frontDoorName, loadBalancingSettingsName)
        }
        healthProbeSettings: {
          id: resourceId('Microsoft.Network/frontDoors/healthProbeSettings', frontDoorName, healthProbeSettingsName)
        }
      }
    }]

    routingRules: [for routingRule in routingRules: {
      name: routingRule.routingRuleName
      properties: {
        frontendEndpoints: [
          {
            id: resourceId('Microsoft.Network/frontDoors/frontEndEndpoints', frontDoorName, routingRule.endpointName)
          }
        ]
        acceptedProtocols: [
          'Http'
          'Https'
        ]
        patternsToMatch: [
          '/*'
        ]
        routeConfiguration: {
          '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration'
          forwardingProtocol: 'MatchRequest'
          backendPool: {
            id: resourceId('Microsoft.Network/frontDoors/backEndPools', frontDoorName, routingRule.backendPoolName)
          }
        }
        enabledState: 'Enabled'
      }
    }]
  }
}


Solution

  • To create two or more custom domains or routing rules or any resource properties, you need to initialize an array of objects, declare it in module bicep file, then traverse it using for loop in the bicep file.

    I modified your code as below.

    param frontdoorprefix string ='jah'
    param backEndAddress string = 'address1'
    param frontEndEndPointName string = 'endpointnew'
    param backEndPoolName string = 'backendpool1'
    param customDomain array
    param backendPools array
    param routingRules array
    var loadBalancingSettingsName = 'newlbj'
    var healthProbeSettingsName = 'probesj'
    var routingRuleName = 'newruleja'
    var frontDoorName = '${frontdoorprefix}${uniqueString(resourceGroup().id)}'
    
    resource myFrontDoorResource 'Microsoft.Network/frontDoors@2021-06-01' =  {
      name: frontDoorName
      location: 'global'
      properties: {
        enabledState: 'Enabled'
    
        frontendEndpoints: [
          for frontendEndpoint in customDomains : {
            name: '{frontEndEndPoint}1'
            properties: {
              hostName: '${frontendEndpoint}.azurefd.net'
              sessionAffinityEnabledState: 'Disabled'
            }
          }
        ]
    
        loadBalancingSettings: [
          {
            name: loadBalancingSettingsName
            properties: {
              sampleSize: 4
              successfulSamplesRequired: 2
            }
          }
        ]
    
        healthProbeSettings: [
          {
            name: healthProbeSettingsName
            properties: {
              path: '/'
              protocol: 'Http'
              intervalInSeconds: 120
            }
          }
        ]
    
        backendPools: [
          for backendPool in backendPools : {
            name: backendPool.name
            properties: {
              backends: [
                {
                  address: backEndAddress
                  backendHostHeader: backEndAddress
                  httpPort: 80
                  httpsPort: 443
                  weight: 100
                  priority: 1
                  enabledState: 'Enabled'
                }
              ]
              loadBalancingSettings: {
                id: resourceId('Microsoft.Network/frontDoors/loadBalancingSettings', frontDoorName, loadBalancingSettingsName)
              }
              healthProbeSettings: {
                id: resourceId('Microsoft.Network/frontDoors/healthProbeSettings', frontDoorName, healthProbeSettingsName)
              }
            }
          }
        ]
    
        routingRules: [
          {
            name: routingRuleName
            properties: {
              frontendEndpoints: [
                {
                  id: resourceId('Microsoft.Network/frontDoors/frontEndEndpoints', frontDoorName, frontEndEndPointName)
                }
              ]
              acceptedProtocols: [
                'Http'
                'Https'
              ]
              patternsToMatch: [
                '/*'
              ]
              routeConfiguration: {
                '@odata.type': '#Microsoft.Azure.FrontDoor.Models.FrontdoorForwardingConfiguration'
                forwardingProtocol: 'MatchRequest'
                backendPool: {
                  id: resourceId('Microsoft.Network/frontDoors/backEndPools', frontDoorName, backEndPoolName)
                }
              }
              enabledState: 'Enabled'
            }
          }
        ]
      }
    }
    

    module.bicep:

    module myFrontDoorModule 'azurefrontdoor.bicep' = {
     name: 'xxxxx'
    params: {
        customDomain: [
          {
            name: 'Domain1'
            hostName: 'xxxx.com'
          },
          {
            name: 'Domain2'
            hostName: 'xxxx.com'
          }
        ]
      }
    }
            //Add other required array's same as above format.
    

    Output:

    enter image description here