Compartir a través de


Ejecución del script de implementación de Bicep de forma privada a través de un punto de conexión privado

Con la versión de la API de recursos de Microsoft.Resources/deploymentScripts 2023-08-01, puede ejecutar scripts de implementación de forma privada dentro de una instancia de Azure Container Instance (ACI).

Configuración del entorno

En esta configuración, la ACI creada por el script de implementación se ejecuta dentro de una red virtual y obtiene una dirección IP privada. A continuación, establece una conexión a una cuenta de almacenamiento nueva o preexistente a través de un punto de conexión privado. La propiedad containerSettings/subnetIds especifica la ACI que se debe implementar en una subred de la red virtual.

Captura de pantalla de la arquitectura de alto nivel que muestra cómo se conecta la infraestructura para ejecutar scripts de implementación de forma privada.

Para ejecutar scripts de implementación de forma privada, necesita la siguiente infraestructura como se muestra en el diagrama de arquitectura:

  • Cree una red virtual con dos subredes:
    • Una subred para el punto de conexión privado.
    • Una subred para la ACI, esta subred necesita una delegación Microsoft.ContainerInstance/containerGroups.
  • Cree una cuenta de almacenamiento sin acceso a la red pública.
  • Cree un punto de conexión privado dentro de la red virtual configurada con el subrecurso file en la cuenta de almacenamiento.
  • Cree una zona DNS privada privatelink.file.core.windows.net y registre la dirección IP del punto de conexión privado como un registro A. Vincule la zona DNS privada a la red virtual creada.
  • Cree una identidad administrada asignada por el usuario con permisos Storage File Data Privileged Contributor en la cuenta de almacenamiento y especifíquela en la propiedad identity en el recurso de script de implementación. Para asignar la identidad, consulte Identidad.
  • El recurso de script de implementación crea automáticamente el recurso de script de implementación.

El siguiente archivo de Bicep configura la infraestructura necesaria para ejecutar un script de implementación de forma privada:

@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@2023-01-31' = {
  name: userAssignedIdentityName
  location: location
}

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

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-11-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@2020-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@2023-11-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: '9.0'
    retentionInterval: 'P1D'
    scriptContent: 'Write-Host "Hello World!"'
  }
}

ACI descarga imágenes de contenedor de Microsoft Container Registry. Si usa un firewall, incluya en la lista de permitidos la dirección URL mcr.microsoft.com descargar la imagen. Si no se descarga la imagen de contenedor, la ACI entra en un estado de waiting, provoca un error de tiempo de espera.

Pasos siguientes

En este artículo, ha aprendido a ejecutar scripts de implementación a través de un punto de conexión privado. Para obtener más información: