Bicep-implementatiescript privé uitvoeren via een privé-eindpunt

Met de Microsoft.Resources/deploymentScripts resource-API-versie 2023-08-01kunt u implementatiescripts privé uitvoeren binnen een Azure Container Instance (ACI).

De omgeving configureren

In deze configuratie wordt de ACI die door het implementatiescript is gemaakt, uitgevoerd binnen een virtueel netwerk en krijgt deze een privé-IP-adres. Vervolgens wordt een verbinding tot stand gebracht met een nieuw of bestaand opslagaccount via een privé-eindpunt. De containerSettings/subnetIds eigenschap geeft de ACI op die moet worden geïmplementeerd in een subnet van het virtuele netwerk.

Schermopname van architectuur op hoog niveau die laat zien hoe de infrastructuur is verbonden om implementatiescripts privé uit te voeren.

Als u implementatiescripts privé wilt uitvoeren, hebt u de volgende infrastructuur nodig, zoals te zien is in het architectuurdiagram:

  • Maak een virtueel netwerk met twee subnetten:
    • Een subnet voor het privé-eindpunt.
    • Een subnet voor de ACI; dit subnet vereist een Microsoft.ContainerInstance/containerGroups-delegatie.
  • Maak een opslagaccount zonder openbare netwerktoegang.
  • Maak een privé-eindpunt in het virtuele netwerk dat is geconfigureerd met de file subresource in het opslagaccount.
  • Maak een privé-DNS-zone privatelink.file.core.windows.net en registreer het IP-adres van het privé-eindpunt als een A-record. Koppel de privé-DNS-zone aan het gemaakte virtuele netwerk.
  • Maak een door de gebruiker toegewezen beheerde identiteit met Storage File Data Privileged Contributor machtigingen voor het opslagaccount en geef deze op in de identity eigenschap in de implementatiescriptresource. Zie Identiteit om de identiteit toe te wijzen.
  • De ACI-resource wordt automatisch gemaakt door de resource voor het implementatiescript.

Important

Als je een beheerde identiteit toewijst met rechten die de operationele eisen van het script overstijgen, is de scriptmaker verantwoordelijk voor het waarborgen dat het opslagaccount beschermd is tegen onbedoelde toegang. Waar mogelijk, volg het principe van het minste privilege.

Met het volgende Bicep-bestand configureert u de infrastructuur die nodig is voor het uitvoeren van een implementatiescript privé:

@maxLength(10) // Required maximum length, because the storage account has a maximum of 26 characters
param namePrefix string
param location string = resourceGroup().location
param userAssignedIdentityName string = '${namePrefix}Identity'
param storageAccountName string = '${namePrefix}stg${uniqueString(resourceGroup().id)}'
param vnetName string = '${namePrefix}Vnet'
param deploymentScriptName string = '${namePrefix}ds'

var roleNameStorageFileDataPrivilegedContributor = '69566ab7-960f-475b-8e7c-b3118f30c6bd'
var vnetAddressPrefix = '192.168.4.0/23'
var subnetEndpointAddressPrefix = '192.168.4.0/24'
var subnetACIAddressPrefix = '192.168.5.0/24'

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2025-01-31-preview' = {
  name: userAssignedIdentityName
  location: location
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
  name: storageAccountName
  kind: 'StorageV2'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    publicNetworkAccess: 'Disabled'
    networkAcls: {
      defaultAction: 'Deny'
      bypass: 'AzureServices'
    }
  }
}

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2025-01-01' = {
   name: storageAccount.name
   location: location
   properties: {
    privateLinkServiceConnections: [
      {
        name: storageAccount.name
        properties: {
          privateLinkServiceId: storageAccount.id
          groupIds: [
            'file'
          ]
        }
      }
    ]
    customNetworkInterfaceName: '${storageAccount.name}-nic'
    subnet: {
      id: virtualNetwork::privateEndpointSubnet.id
    }
   }
}

resource storageFileDataPrivilegedContributorReference 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
  name: roleNameStorageFileDataPrivilegedContributor
  scope: tenant()
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storageFileDataPrivilegedContributorReference.id, managedIdentity.id, storageAccount.id)
  scope: storageAccount
  properties: {
    principalId: managedIdentity.properties.principalId
    roleDefinitionId: storageFileDataPrivilegedContributorReference.id
    principalType: 'ServicePrincipal'
  }
}

resource privateDnsZone 'Microsoft.Network/privateDnsZones@2024-06-01' = {
  name: 'privatelink.file.core.windows.net'
  location: 'global'

  resource virtualNetworkLink 'virtualNetworkLinks' = {
    name: uniqueString(virtualNetwork.name)
    location: 'global'
    properties: {
      registrationEnabled: false
      virtualNetwork: {
        id: virtualNetwork.id
      }
    }
  }

  resource resRecord 'A' = {
    name: storageAccount.name
    properties: {
      ttl: 10
      aRecords: [
        {
          ipv4Address: first(first(privateEndpoint.properties.customDnsConfigs)!.ipAddresses)
        }
      ]
    }
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2025-01-01' = {
  name: vnetName
  location: location
  properties:{
    addressSpace: {
      addressPrefixes: [
        vnetAddressPrefix
      ]
    }
  }

  resource privateEndpointSubnet 'subnets' = {
    name: 'PrivateEndpointSubnet'
    properties: {
      addressPrefixes: [
        subnetEndpointAddressPrefix
      ]
    }
  }

  resource containerInstanceSubnet 'subnets' = {
    name: 'ContainerInstanceSubnet'
    properties: {
      addressPrefix: subnetACIAddressPrefix
      delegations: [
        {
          name: 'containerDelegation'
          properties: {
            serviceName: 'Microsoft.ContainerInstance/containerGroups'
          }
        }
      ]
    }
  }
}

resource privateDeploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: deploymentScriptName
  dependsOn: [
    privateEndpoint
    privateDnsZone::virtualNetworkLink
  ]
  location: location
  kind: 'AzurePowerShell'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${managedIdentity.id}' : {}
    }
  }
  properties: {
    storageAccountSettings: {
      storageAccountName: storageAccount.name
    }
    containerSettings: {
      subnetIds: [
        {
          id: virtualNetwork::containerInstanceSubnet.id
        }
      ]
    }
    azPowerShellVersion: '14.0'
    retentionInterval: 'P1D'
    scriptContent: 'Write-Host "Hello World!"'
  }
}

De ACI downloadt containerinstallatiekopieën uit het Microsoft Container Registry. Als u een firewall gebruikt, voeg dan de URL mcr.microsoft.com toe aan de allowlist om de image te downloaden. Als het downloaden van de containerimage mislukt, komt ACI in de status waiting terecht, wat uiteindelijk leidt tot een time-outfout.

Volgende stappen

In dit artikel hebt u geleerd hoe u implementatiescripts uitvoert via een privé-eindpunt. Zie voor meer informatie: