我正在为Azure数据工厂开发一个ARM模板,该模板具有到SQL Server和Azure Datalake的托管专用端点。然而,当ARM模板完成执行时,被管理的私有端点处于";挂起";状态我如何配置被管理的专用端点,以便将其配置为";批准";一旦使用ARM模板完全供应ADF。以下是我的template.json文件:
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"environment": {
"type": "string",
"metadata": {
"description": "name of environment for deployment"
}
},
"project": {
"type": "string",
"metadata": {
"description": "name of the project for building the name of resources"
}
},
"location": {
"defaultValue": "eastus",
"type": "string"
},
"adfFactoryName": {
"type": "string"
},
"adfVersion": {
"type": "string"
},
"tags": {
"type": "object",
"metadata": {
"description": "tags to add to resources"
}
},
"adfVNetEnabled": {
"type": "bool"
},
"adfPublicNetworkAccess": {
"type": "bool"
},
"adfAzureDatabricksDomain": {
"type": "string",
"metadata": "Azure Databricks existing cluster Id"
},
"adfAzureDatabricksExistingClusterId": {
"type": "string",
"metadata": "Azure Databricks existing cluster Id"
},
"adfDataLakeConnectionString": {
"type": "string",
"metadata": "Azure Data Lake connection string"
},
"adfDataFactoryIdentity": {
"type": "string",
"metadata": "Identity type for data factory"
},
"adfLSASDBConnectionString": {
"type": "string",
"metadata": "SQL DB connection string"
},
"adfKVBaseURL": {
"type": "string",
"metadata": "Keyvault connection string"
},
"adfDataLakeStorageName": {
"type": "string",
"metadata": "Azure Data lake Storage Name"
},
"adfDataLakeStorageGroupId": {
"type": "string",
"metadata": "Azure Data lake Storage Group ID"
},
"adfSqlServerName": {
"type": "string",
"metadata": "Azure SQL Server name"
},
"adfSqlServerGroupId": {
"type": "string",
"metadata": "Azure SQL Server Group ID"
}
},
"variables": {
"factoryId": "[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'))]",
"managedVirtualNetworkName": "[concat(parameters('adfFactoryName'), '/default')]"
},
"resources": [
{
"condition": "[equals(parameters('adfVersion'), 'V2')]",
"type": "Microsoft.DataFactory/factories",
"apiVersion": "2018-06-01",
"name": "[parameters('adfFactoryName')]",
"location": "[parameters('location')]",
"identity": {
"type": "[parameters('adfDataFactoryIdentity')]"
},
"properties": {
"publicNetworkAccess": "[if(bool(parameters('adfPublicNetworkAccess')), 'Enabled', 'Disabled')]"
},
"tags": "[parameters('tags')]",
"resources": [
{
"condition": "[and(equals(parameters('adfVersion'), 'V2'), parameters('adfVNetEnabled'))]",
"name": "[concat(parameters('adfFactoryName'), '/default')]",
"type": "Microsoft.DataFactory/factories/managedVirtualNetworks",
"apiVersion": "2018-06-01",
"properties": {},
"dependsOn": [
"[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'))]"
]
},
{
"condition": "[and(equals(parameters('adfVersion'), 'V2'), parameters('adfVNetEnabled'))]",
"name": "[concat(parameters('adfFactoryName'), '/DDIR')]",
"type": "Microsoft.DataFactory/factories/integrationRuntimes",
"apiVersion": "2018-06-01",
"properties": {
"type": "Managed",
"managedVirtualNetwork": {
"referenceName": "default",
"type": "ManagedVirtualNetworkReference"
},
"typeProperties": {
"computeProperties": {
"location": "[parameters('location')]"
}
}
},
"dependsOn": [
"[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'))]",
"[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'), '/managedVirtualNetworks/default')]"
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/AzureKeyVault')]",
"type": "Microsoft.DataFactory/factories/linkedServices",
"apiVersion": "2018-06-01",
"properties": {
"annotations": [],
"type": "AzureKeyVault",
"typeProperties": {
"baseUrl": "[parameters('adfKVBaseURL')]"
}
},
"dependsOn": [
"[parameters('adfFactoryName')]"
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/AzureDatabricks_LinkedService')]",
"type": "Microsoft.DataFactory/factories/linkedServices",
"apiVersion": "2018-06-01",
"properties": {
"annotations": [],
"type": "AzureDatabricks",
"typeProperties": {
"domain": "[parameters('adfAzureDatabricksDomain')]",
"accessToken": {
"type": "AzureKeyVaultSecret",
"store": {
"referenceName": "AzureKeyVault",
"type": "LinkedServiceReference"
},
"secretName": "[concat('kvs-databricks-',parameters('environment'), 'aue', parameters('project'))]"
},
"existingClusterId": "[parameters('adfAzureDatabricksExistingClusterId')]"
},
"connectVia": {
"referenceName": "DDIR",
"type": "IntegrationRuntimeReference"
}
},
"dependsOn": [
"[parameters('adfFactoryName')]",
"[concat(variables('factoryId'), '/integrationRuntimes/DDIR')]",
"[concat(variables('factoryId'), '/linkedServices/AzureKeyVault')]"
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/AzureDatalake_DDIR')]",
"type": "Microsoft.DataFactory/factories/linkedServices",
"apiVersion": "2018-06-01",
"properties": {
"annotations": [],
"type": "AzureBlobFS",
"typeProperties": {
"url": "[parameters('adfDataLakeConnectionString')]"
},
"connectVia": {
"referenceName": "DDIR",
"type": "IntegrationRuntimeReference"
}
},
"dependsOn": [
"[parameters('adfFactoryName')]",
"[concat(variables('factoryId'), '/integrationRuntimes/DDIR')]"
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/LS_ASDB')]",
"type": "Microsoft.DataFactory/factories/linkedServices",
"apiVersion": "2018-06-01",
"properties": {
"annotations": [],
"type": "AzureSqlDatabase",
"typeProperties": {
"connectionString": "[parameters('adfLSASDBConnectionString')]",
"password": {
"type": "AzureKeyVaultSecret",
"store": {
"referenceName": "AzureKeyVault",
"type": "LinkedServiceReference"
},
"secretName": "kvs-synapsepwd-devauegteng"
}
},
"connectVia": {
"referenceName": "DDIR",
"type": "IntegrationRuntimeReference"
}
},
"dependsOn": [
"[parameters('adfFactoryName')]",
"[concat(variables('factoryId'), '/integrationRuntimes/DDIR')]",
"[concat(variables('factoryId'), '/linkedServices/AzureKeyVault')]"
]
}
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/default/',parameters('adfDataLakeStorageName'))]",
"type": "Microsoft.DataFactory/factories/managedVirtualNetworks/managedPrivateEndpoints",
"apiVersion": "2018-06-01",
"properties": {
"privateLinkResourceId": "[resourceId('Microsoft.Storage/storageAccounts', parameters('adfDataLakeStorageName'))]",
"groupId": "[parameters('adfDataLakeStorageGroupId')]"
},
"dependsOn": [
"[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'), '/managedVirtualNetworks/default')]"
]
},
{
"name": "[concat(parameters('adfFactoryName'), '/default/',parameters('adfSqlServerName'))]",
"type": "Microsoft.DataFactory/factories/managedVirtualNetworks/managedPrivateEndpoints",
"apiVersion": "2018-06-01",
"properties": {
"privateLinkResourceId": "[resourceId('Microsoft.Sql/servers', parameters('adfSqlServerName'))]",
"groupId": "[parameters('adfSqlServerGroupId')]"
},
"dependsOn": [
"[concat('Microsoft.DataFactory/factories/', parameters('adfFactoryName'), '/managedVirtualNetworks/default')]"
]
}
]
}
我遇到了同样的问题,并创建了一个Az Powershell脚本函数来帮助我。
function ApprovePrivateEndpointConnections {
param (
[string] $ResourceGroupName,
[string] $ResourceName
)
$Resource = Get-AzResource -Name $ResourceName -ResourceGroupName $ResourceGroup
if ($Resource) {
$ResourcePendingConnection = Get-AzPrivateEndpointConnection -PrivatelinkResourceId $Resource.ResourceId | Where-Object -FilterScript {$_.PrivateLinkServiceConnectionState.Status -EQ 'Pending'}
if ($ResourcePendingConnection) {
foreach ($Connection in $ResourcePendingConnection)
{
Approve-AzPrivateEndpointConnection -ResourceId $Connection.Id
}
}
else
{
Write-Output 'No pending connections for Resource: ' $ResourceName
}
}
else
{
Write-Output 'No resource found with name: ' $ResourceName
}
}
使用Azure门户或使用带有以下JSON模板的ARM模板创建专用端点资源,并在ConnectionState中注明状态为Approved。
示例:
{
"name": "string",
"type": "Microsoft.Network/privateEndpoints",
"apiVersion": "2020-07-01",
"location": "string",
"tags": {},
"properties": {
"subnet": {
"id": "string",
"name": "string"
},
"privateLinkServiceConnections": [
{
"id": "string",
"properties": {
"privateLinkServiceId": "string",
"groupIds": [
"string"
],
"requestMessage": "string",
"privateLinkServiceConnectionState": {
"status": "string",
"description": "string",
"actionsRequired": "string"
}
},
"name": "string"
}
],
"manualPrivateLinkServiceConnections": [
{
"id": "string",
"properties": {
"privateLinkServiceId": "string",
"groupIds": [
"string"
],
"requestMessage": "string",
"privateLinkServiceConnectionState": {
"status": "string",
"description": "string",
"actionsRequired": "string"
}
},
"name": "string"
}
],
"customDnsConfigs": [
{
"fqdn": "string",
"ipAddresses": [
"string"
]
}
]
},
"resources": []
}
有关字符串属性值,请参阅-privateendpoint。
审批需要通过脚本实现自动化,官方模板中有一个很好的例子。
我发现Toofle的脚本在这里是一个很好的开始,但对简单地批准所有未决请求的安全风险有点担心。
因此,我修改了脚本,以获取与我期望的私有端点相关的附加参数,并忽略任何不匹配的端点。
param(
[Parameter(Mandatory)]
[string] $DataFactoryName,
[Parameter(Mandatory)]
[string] $PrivateEndpointName,
[Parameter(Mandatory)]
[string] $TargetResourceId
)
$Resource = Get-AzResource -ResourceId $TargetResourceId
if ($Resource) {
$ResourcePendingConnection = Get-AzPrivateEndpointConnection -PrivatelinkResourceId $Resource.ResourceId `
| Where-Object -FilterScript {$_.PrivateLinkServiceConnectionState.Status -EQ 'Pending'} `
| Where-Object -FilterScript {$_.PrivateEndpoint.Id -like "*/providers/Microsoft.Network/privateEndpoints/$DataFactoryName.$PrivateEndpointName"}
if ($ResourcePendingConnection) {
foreach ($Connection in $ResourcePendingConnection)
{
Approve-AzPrivateEndpointConnection -ResourceId $Connection.Id
}
}
else
{
Write-Output 'No pending connections for Resource: ' $TargetResourceId
}
}
else
{
Write-Output 'No resource found with ID: ' $TargetResourceId
}
我找不到在ARM中完成它的方法。我的感觉是,如果可以这样做,你必须站在链接(存储帐户、数据库等(的接收端,无论是ARM、Bicep还是CLI。
我们现在正在做的是:
az network private-endpoint-connection list -g <RESOURCE_GROUP> -n <SA_NAME> --type Microsoft.Storage/storageAccounts --query "[?properties.privateLinkServiceConnectionState.status == 'Pending'].name" > output.json
jq -c '.[]' output.json | xargs -r -L 1 az network private-endpoint-connection approve -g <RESOURCE_GROUP> --resource-name <SA_NAME> --type Microsoft.Storage/storageAccounts --description "Approved" -n
您可以将其放在发布管道的Azure CLI步骤中。