SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

Bicep でマネージドプライベートエンドポイントを承認する

leave a comment

Azure の Data Factory / Synapse / Data Explorer といったリソースでは、マネージド仮想ネットワーク内にプライベートエンドポイントを作成することができる、「マネージドプライベートエンドポイント」というリソースを作成することができます。

通常のプライベートエンドポイントは、仮想ネットワーク内に展開を行います。

しかし、上述のリソースは仮想ネットワーク内に展開することができないのですが、このようなリソースで、使用できるプライベートエンドポイントを作成する方法として、マネージドプライベートエンドポイントという機能が提供されています。

マネージドプライベートエンドポイントを作成することで、セキュリティで保護されている特定のリソースへのアクセスポイントを、仮想ネットワーク内に展開することができないリソースでも作成することができます。

Synapse についてはドキュメントが見つからなかったのですが、ADF と ADX については、マネージドプライベートエンドポイントをBicep で作成することが可能となっています。

マネージドプライベートエンドポイントを作成する場合は、上述のキュメントの内容で Bicep を作成すればよいのですが、作成したエンドポイントの承認まで Bicep で実施しようとすると少し手間がかかったので、本投稿で承認をした際の内容をまとめておこうと思います。

今回はストレージアカウントの BLOB に対してプライベートエンドポイントを作成することを想定しています。

作成したサンプルについては https://github.com/MasayukiOzawa/bicep-sample/tree/main/managed-private-endpoint に置いてあります。

通常のプライベートエンドポイントを Bicep で作成する場合

マネージドプライベートエンドポイントではなく、通常のプライベートエンドポイント (仮想ネットワーク内に NIC を作成してプライベートエンドポイントを作成) を使用する場合は次のような Bicep で承認まで実施することができます。

param location string
param vnetId string
param subnetId string
param storageAccountId string

param privateEndpointName string = 'pep-myPrivateEndpoint'

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-11-01' = {
  name: privateEndpointName
  location: location
  properties: {
    subnet: {
      id: subnetId
    }
    privateLinkServiceConnections: [
      {
        name: 'linkConnection-${privateEndpointName}'
        properties: {
          privateLinkServiceId: storageAccountId
          groupIds: [
            'blob'
          ]
        }
      }
    ]
    customNetworkInterfaceName: 'nic-${privateEndpointName}'
  }
}

resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: 'privatelink.blob.${environment().suffixes.storage}'
  location: 'global'
}

resource virtualNetworkLink 'Microsoft.Network/privateDnsZones/virtualNetworkLinks@2020-06-01' = {
  name: 'link-${privateEndpointName}'
  parent: privateDnsZone
  location: 'global'
  properties: {
    registrationEnabled: true
    virtualNetwork: {
      id: vnetId
    }
  }
}

resource privateDnsZoneGroup 'Microsoft.Network/privateEndpoints/privateDnsZoneGroups@2023-11-01' = {
  name: 'zoneGroup-${privateEndpointName}'
  parent: privateEndpoint
  properties: {
    privateDnsZoneConfigs: [
      {
        name: 'zoneConfig-${privateEndpointName}'
        properties: {
          privateDnsZoneId: privateDnsZone.id
        }
      }
    ]
  }
}

 

通常のプライベートエンドポイントを作成する際には、次のようなリソースを作成することで対応することができます。

  • privateEndpoint
  • privateDnsZones
  • virtualNetworkLinks
  • privateDnsZoneGroups

プライベートエンドポイントは、Microsoft.Network privateEndpoints で作成することができますが、上記のような Bicep でプライベートエンドポイントを作成した場合、自動承認が行われ、明示的な承認をすることなく、プライベートエンドポイントが作成されていました。

 

マネージドプライベートエンドポイント を Bicep で作成する

今回は、Azure Data Factory でマネージドプライベートエンドポイントを作成してみます。

Azure Data Factory とマネージドプライベートエンドポイントの作成

マネージドプライベートエンドポイントを使用するためには、Data Factory を作成する際にマネージド仮想ネットワークを使用して展開する必要があります。

マネージド仮想ネットワークを使用して展開した Data Factory であればマネージドプライベートエンドポイントを作成することが可能です。

次のような Bicep を使用することで、Data Factory の展開と、指定したストレージアカウントに対してのマネージドプライベートエンドポイントの作成を行うことができます。

param location string
param adfResourceName string = 'adf-${uniqueString(resourceGroup().id)}'
param storageAccountId string

resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' = {
  name: adfResourceName
  location: location
  properties: {
    publicNetworkAccess: 'Enabled'
  }
  identity: {
    type: 'SystemAssigned'
  }
}

resource managedVirtualNetwork 'Microsoft.DataFactory/factories/managedVirtualNetworks@2018-06-01' = {
  parent: dataFactory
  name: 'default'
  properties: {
    virtualNetworkType: 'Managed'
  }
}

resource autoResolveIntegrationRuntime 'Microsoft.DataFactory/factories/integrationRuntimes@2018-06-01' = {
  parent: dataFactory
  name: 'AutoResolveIntegrationRuntime'
  properties: {
    type: 'Managed'
    managedVirtualNetwork: {
      type: 'ManagedVirtualNetworkReference'
      referenceName: managedVirtualNetwork.name
    }
    typeProperties: {
      computeProperties: {
        location: 'AutoResolve'
      }
    }
  }
}

resource managedPrivateEndpoint 'Microsoft.DataFactory/factories/managedVirtualNetworks/managedPrivateEndpoints@2018-06-01' = {
  parent: managedVirtualNetwork
  name: 'AzureBlobStorageEndpoint'
  properties: {
    privateLinkResourceId: storageAccountId
    groupId: 'blob'
  }
}

 

プライベートエンドポイントでは、作成した接続は自動承認が行われていたのですが、上記の Bicep で作成したマネージドプライベートエンドポイントに対しては、「保留中」の状態となり、明示的に承認を行う必要がありました。

image

マネージドプライベートエンドポイントの承認を Bicep で行う

マネージドプライベートエンドポイントの承認を Bicep で実施することは可能なのですが、少し手間がかかりました。

今回は次のようなモジュールの構成としています。


module dataFactory 'dataFactory.bicep' = {
  name: 'dataFactory'
  params: {
    location: location
    storageAccountId: storage.outputs.storageAccountId
  }
}

module approvePrivateEndpointPreTask 'approvePrivateEndpointPreTask.bicep' = {
  name : 'approvePrivateEndpointPreTask'
  dependsOn: [
    dataFactory
  ]
  params : {
    storageAccountName: storage.outputs.storageAccountName
  }
}

module approvePrivateEndpoint 'approvePrivateEndpoint.bicep' = {
  name : 'approvePrivateEndpoint'
  params : {
    storageAccountName: storage.outputs.storageAccountName
    storagePrivateEndpointConnections: approvePrivateEndpointPreTask.outputs.storagePrivateEndpointConnections
  }
}

 

最初に Data Factory を作成し、Data Factory の作成が完了したら「approvePrivateEndpointPreTask」を実行しています。このモジュールの内容は次のようになっています。

param storageAccountName string

resource storage 'Microsoft.Storage/storageAccounts@2023-04-01' existing = {
  name: storageAccountName
}

output storagePrivateEndpointConnections array = filter(storage.properties.privateEndpointConnections, (item, index) => item.properties.privateLinkServiceConnectionState.status == 'Pending')

 

プライベートエンドポイントを作成すると、該当のストレージアカウントのプロパティには、プライベートエンドポイントの接続情報が追加されます。

これは、Data Factory でプライベートエンドポイントを作成後に追加されるプロパティとなりますので、「dependsOn」で Data Factory の設定が一通り完了した後に情報の取得を行っています。

承認対象となるものは「Pending」状態の接続のみとなりますので、フィルターですでに承認済みの接続はスキップしています。 (承認済みの接続を再承認しようとするとエラーとなったはずです)

これで、プライベートエンドポイントの接続情報が追加された状態のストレージの情報を取得することができましたので、保留中の接続の承認を「approvePrivateEndpoint」で実施します。

param storageAccountName string 
param storagePrivateEndpointConnections array

resource storage 'Microsoft.Storage/storageAccounts@2023-04-01' existing = {
  name: storageAccountName
}

resource privateEndpointConnection 'Microsoft.Storage/storageAccounts/privateEndpointConnections@2023-04-01' = [for (resource,index) in storagePrivateEndpointConnections : {
  name: resource.name
  parent: storage
  properties: {
    privateLinkServiceConnectionState: {
      status: 'Approved'
    }
  }
}]

 

これで保留中の接続を承認することができ、マネージドプライベートエンドポイントが使用できる状態となりました。

image

 

まとめ

今回は、マネージドプライベートエンドポイントの作成時に自動承認が行われていなかったので手動で承認をしました。

マネージドプライベートエンドポイント以外にも、自動承認が行われないケースがあった場合は、次のようなフローを作成することで対応できるのではないでしょうか。

  1. プライベートエンドポイントを作成
  2. プライベートエンドポイントの作成後、リソースの最新の情報を取得し、プライベートエンドポイントの接続名を取得
    • プライベートエンドポイントの作成後に、対象のリソースの最新の情報を取得するとプライベートエンドポイントの情報が追加されている
    • 「existing」によるリソース情報の取得は「dependsOn」を指定できないため、モジュール呼び出し時に指定して、プライベートエンドポイント作成後に情報取得が行われるように依存関係を制御
  3. 取得した接続名を承認
    • 承認対象は「Pending」になっている状態の接続を対象としておくことで、複数回実行してもエラーが発生すること無く実行できるように制御をすることができる
Share

Written by Masayuki.Ozawa

7月 14th, 2024 at 8:40 pm

Posted in Bicep

Tagged with

Leave a Reply