0

I'm building environment creation via bicep files and Azure Dev Ops pipelines. The main services that I'm using are:

  • 2 x App Services
  • SQL server
  • Storage
  • Azure Functions
  • Virtual Network

When I'm disabling connectivity to internat, decided to put everything in vnet. All parts are created via bicep files correctly. The problem starts when trying to deploy Azure functions. I'm having error:

Creation of storage file share failed with: 'The remote server returned an error: (403) Forbidden.'. Please check if the storage account is accessible.

After that error I was trying to figure out what can be wrong with my bicep files. I've decided to try create this manually with such important steps inside creator.

  1. Create Function App
  2. Attached App service plan created via bicep S1 - Standard
  3. Use existing storage account created from bicep
  4. Disable public access
  5. Enable Network injection
  6. Choose existing virtual network crated via bicep
  7. Choose outbound access to subnet dedicated to functions and created via bicep
  8. No private endpoints

With all that points the Function App was successfully created. Please help me figure out what I have missed in the bicep file that having this error while disabling public access to storage.

Below relevant bicep files: vnet.bicep:

param nameBase string
param location string

resource vnet 'Microsoft.Network/virtualNetworks@2022-09-01' = {
  name: '${nameBase}-vnet'
  location: location
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'deafult'        
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'api'        
        properties: {
          addressPrefix: '10.0.1.0/24'
          delegations: [
            {
              name: 'Microsoft.Web/serverFarms'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
      {
        name: 'ui'        
        properties: {
          addressPrefix: '10.0.2.0/24'
          delegations: [
            {
              name: 'Microsoft.Web/serverFarms'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
        }
      }
      {
        name: 'functions'        
        properties: {
          addressPrefix: '10.0.3.0/24'
          delegations: [
            {
              name: 'Microsoft.Web/serverFarms'
              properties: {
                serviceName: 'Microsoft.Web/serverFarms'
              }
            }
          ]
          serviceEndpoints: [
            {
              service: 'Microsoft.Storage'
            }
          ]
        }
      }
      {
        name: 'storage'        
        properties: {
          addressPrefix: '10.0.4.0/24'
          serviceEndpoints: [
            {
              service: 'Microsoft.Storage'
            }
          ]
        }
      }
    ]
  }
}

output subnetId string = vnet.properties.subnets[0].id
output subnetIdApi string = vnet.properties.subnets[1].id
output subnetIdUi string = vnet.properties.subnets[2].id
output subnetIdFunctions string = vnet.properties.subnets[3].id
output subnetIdStorage string = vnet.properties.subnets[4].id

functions.bicep:

param name string
param client string
param env string
param location string
param subnetIdFunctions string
param subnetIdStorage string

resource storage 'Microsoft.Storage/storageAccounts@2022-05-01' = {
  name: 'storage${client}${env}'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    accessTier: 'Hot'
    isHnsEnabled: true
    isSftpEnabled: true
    minimumTlsVersion: 'TLS1_2'
    publicNetworkAccess: 'Enabled'
    allowBlobPublicAccess: false
    supportsHttpsTrafficOnly: true
    allowSharedKeyAccess: true
    encryption: {
      keySource: 'Microsoft.Storage'
      requireInfrastructureEncryption: false
      services: {
        blob: {
          enabled: true
          keyType: 'Account'
        }
        file: {
          enabled: true
          keyType: 'Account'
        }
        queue: {
          enabled: true
          keyType: 'Service'
        }
        table: {
          enabled: true
          keyType: 'Service'
        }
      }
    }
    keyPolicy: {
      keyExpirationPeriodInDays: 7
    }
    networkAcls: {
      bypass: 'AzureServices'
      defaultAction: 'Deny'
      virtualNetworkRules: [
        {
          id: subnetIdStorage
          action: 'Allow'
        }
      ]
      }
  }
}

output storageAccountName string = storage.name

resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
  name: '${name}-functions-insights'
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
    Request_Source: 'rest'
  }
}

resource serviceplan 'Microsoft.Web/serverfarms@2021-03-01' = {
  name: '${name}-functions-serviceplan'
  location: location
  sku: {
    name: 'S1'
    tier: 'Standard'
  }
}

var functionAppName = '${name}-functions'
resource functionApp 'Microsoft.Web/sites@2021-03-01' = {
  name: functionAppName
  location: location
  kind: 'functionapp'
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    virtualNetworkSubnetId: subnetIdFunctions
    serverFarmId: serviceplan.id
    siteConfig: {
      appSettings: [
        {
          name: 'AzureWebJobsStorage'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storage.listKeys().keys[0].value}'
        }
        {
          name: 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'
          value: 'DefaultEndpointsProtocol=https;AccountName=${storage.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storage.listKeys().keys[0].value}'
        }
        {
          name: 'WEBSITE_CONTENTSHARE'
          value: toLower(functionAppName)
        }
        {
          name: 'FUNCTIONS_EXTENSION_VERSION'
          value: '~2'
        }
        {
          name: 'WEBSITE_NODE_DEFAULT_VERSION'
          value: '~10'
        }
        {
          name: 'APPINSIGHTS_INSTRUMENTATIONKEY'
          value: applicationInsights.properties.InstrumentationKey
        }
        {
          name: 'FUNCTIONS_WORKER_RUNTIME'
          value: 'dotnet'
        }
      ]
      ftpsState: 'FtpsOnly'
      minTlsVersion: '1.2'
    }
    httpsOnly: true
  }
}
kjubersson
  • 17
  • 7
  • Please refer the answer here for function app and private storage account -https://github.com/Azure/bicep/discussions/6426 Also check the answers in this SO post with similar error with logic app instead of function for more insights -https://stackoverflow.com/questions/69766994/cant-create-a-file-share-in-a-storage-account-while-deploying-logic-app-from-th – SiddheshDesai Apr 21 '23 at 07:49
  • Also, go through this sample MS document -https://learn.microsoft.com/en-us/samples/azure/azure-quickstart-templates/function-app-storage-private-endpoints/ – SiddheshDesai Apr 21 '23 at 07:52
  • But I'm deploying this in the same region in the same resource group – kjubersson Apr 21 '23 at 07:54

0 Answers0