PowerShell:為 Azure SQL 資料庫建立虛擬服務端點和 VNet 規則

適用於:Azure SQL Database

虛擬網路規則是一項防火牆安全性功能,用於控制適用於 Azure SQL Database 資料庫、彈性集區或 Azure Synapse 中的資料庫的邏輯 SQL Server 是否接受虛擬網路中特定子網路所傳送的通訊。

重要

本文適用於 Azure SQL 資料庫,包括 Azure Synapse (先前稱為 SQL DW)。 為了簡單起見,本文中的 Azure SQL 資料庫一詞適用於屬於 Azure SQL 資料庫 或 Azure Synapse 的資料庫。 本文適用於 Azure SQL 受控執行個體,因為它沒有與之相關聯的服務端點。

本文示範採用下列動作的 PowerShell 指令碼:

  1. 在您的子網路上建立 Microsoft Azure 虛擬服務端點
  2. 將端點新增至伺服器的防火牆,以建立虛擬網路規則

如需更多背景,請參閱適用於 Azure SQL 資料庫的虛擬服務端點

提示

如果您只需要評定或新增 Azure SQL 資料庫虛擬服務端點類型名稱至子網路,您可以直接跳至更多 Direct PowerShell 指令碼

注意

本文使用 Azure Az PowerShell 模組,這是與 Azure 互動時建議使用的 PowerShell 模組。 若要開始使用 Az PowerShell 模組,請參閱安裝 Azure PowerShell。 若要瞭解如何遷移至 Az PowerShell 模組,請參閱將 Azure PowerShell 從 AzureRM 遷移至 Az

重要

Azure SQL 資料庫仍然支援 PowerShell Azure Resource Manager 模組,但所有未來的開發都是針對 Az.Sql Cmdlets。 如需較舊的模組,請參閱 AzureRM.Sql。 Az 模組和 AzureRm 模組中命令的引數本質上完全相同。

主要 Cmdlet

本文強調 New-AzSqlServerVirtualNetworkRule Cmdlet,此 Cmdlet 會新增子網路端點至伺服器的存取控制清單 (ACL),藉此建立規則。

下列清單顯示您必須執行的其他主要 Cmdlet 序列,以準備對 New-AzSqlServerVirtualNetworkRule 的呼叫。 在本文中,這些呼叫會在指令碼 3「虛擬網路規則」中發生:

  1. New-AzVirtualNetworkSubnetConfig:建立子網路物件。
  2. New-AzVirtualNetwork:建立虛擬網路,為其提供子網路。
  3. Set-AzVirtualNetworkSubnetConfig:將虛擬服務端點指派給子網路。
  4. Set-AzVirtualNetwork:保存對虛擬網路所做的更新。
  5. New-AzSqlServerVirtualNetworkRule:在子網路成為端點之後,將子網路新增為虛擬網路規則,並新增至伺服器的 ACL。
    • 從 Azure RM PowerShell 模組 5.1.1 版開始,此 Cmdlet 提供參數 -IgnoreMissingVNetServiceEndpoint

執行 PowerShell 的必要條件

  • 您已經可以登入 Azure,例如透過 Azure 入口網站
  • 您已經可以執行 PowerShell 指令碼。

注意

請確定您要新增至伺服器的 VNet/子網路已開啟服務端點,否則建立 VNet 防火牆規則將會失敗。

一個指令碼分成四個區塊

我們的示範 PowerShell 指令碼分成一個較小指令碼序列。 分割可簡化學習,並提供彈性。 指令碼必須依指示的順序執行。 如果您現在沒有時間執行指令碼,我們的實際測試輸出會顯示在指令碼 4 之後。

指令碼 1:變數

第一個 PowerShell 指令碼會將值指派給變數。 後續指令碼相依於這些變數。

重要

執行此指令碼之前,可以視需要編輯值。 例如,如果您已經有資源群組,您可能想要將資源群組名稱編輯為指派的值。

您的訂用帳戶名稱應該編輯到指令碼中。

PowerShell 指令碼 1 原始程式碼

######### Script 1 ########################################
##   LOG into to your Azure account.                     ##
##   (Needed only one time per powershell.exe session.)  ##
###########################################################

$yesno = Read-Host 'Do you need to log into Azure (only one time per powershell.exe session)?  [yes/no]'
if ('yes' -eq $yesno) { Connect-AzAccount }

###########################################################
##  Assignments to variables used by the later scripts.  ##
###########################################################

# You can edit these values, if necessary.
$SubscriptionName = 'yourSubscriptionName'
Select-AzSubscription -SubscriptionName $SubscriptionName

$ResourceGroupName = 'RG-YourNameHere'
$Region = 'westcentralus'

$VNetName = 'myVNet'
$SubnetName = 'mySubnet'
$VNetAddressPrefix = '10.1.0.0/16'
$SubnetAddressPrefix = '10.1.1.0/24'
$VNetRuleName = 'myFirstVNetRule-ForAcl'

$SqlDbServerName = 'mysqldbserver-forvnet'
$SqlDbAdminLoginName = 'ServerAdmin'
$SqlDbAdminLoginPassword = 'ChangeYourAdminPassword1'

$ServiceEndpointTypeName_SqlDb = 'Microsoft.Sql'  # Official type name.

Write-Host 'Completed script 1, the "Variables".'

指令碼 2:必要條件

此指令碼為端點動作所在的下一個指令碼做準備。 此指令碼會為您建立下列清單項目,但前提是這些項目尚未存在。 如果您確定這些項目已經存在,則可以略過指令碼 2:

  • Azure 資源群組
  • 邏輯 SQL 伺服器

PowerShell 指令碼 2 原始程式碼

######### Script 2 ########################################
##   Ensure your Resource Group already exists.          ##
###########################################################

Write-Host "Check whether your Resource Group already exists."

$gottenResourceGroup = $null
$gottenResourceGroup = Get-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue

if ($null -eq $gottenResourceGroup) {
    Write-Host "Creating your missing Resource Group - $ResourceGroupName."
    New-AzResourceGroup -Name $ResourceGroupName -Location $Region
} else {
    Write-Host "Good, your Resource Group already exists - $ResourceGroupName."
}

$gottenResourceGroup = $null

###########################################################
## Ensure your server already exists. ##
###########################################################

Write-Host "Check whether your server already exists."

$sqlDbServer = $null
$azSqlParams = @{
    ResourceGroupName = $ResourceGroupName
    ServerName        = $SqlDbServerName
    ErrorAction       = 'SilentlyContinue'
}
$sqlDbServer = Get-AzSqlServer @azSqlParams

if ($null -eq $sqlDbServer) {
    Write-Host "Creating the missing server - $SqlDbServerName."
    Write-Host "Gather the credentials necessary to next create a server."

    $sqlAdministratorCredentials = [pscredential]::new($SqlDbAdminLoginName,(ConvertTo-SecureString -String $SqlDbAdminLoginPassword -AsPlainText -Force))

    if ($null -eq $sqlAdministratorCredentials) {
        Write-Host "ERROR, unable to create SQL administrator credentials.  Now ending."
        return
    }

    Write-Host "Create your server."

    $sqlSrvParams = @{
        ResourceGroupName           = $ResourceGroupName
        ServerName                  = $SqlDbServerName
        Location                    = $Region
        SqlAdministratorCredentials = $sqlAdministratorCredentials
    }
    New-AzSqlServer @sqlSrvParams
} else {
    Write-Host "Good, your server already exists - $SqlDbServerName."
}

$sqlAdministratorCredentials = $null
$sqlDbServer = $null

Write-Host 'Completed script 2, the "Prerequisites".'

指令碼 3:建立端點和規則

此指令碼會建立具有子網路的虛擬網路。 然後指令碼會將 Microsoft.Sql 端點類型指派給您的子網路。 最後,指令碼會將子網新增至訪問控制清單 (ACL) ,藉此建立規則。

PowerShell 指令碼 3 原始程式碼

######### Script 3 ########################################
##   Create your virtual network, and give it a subnet.  ##
###########################################################

Write-Host "Define a subnet '$SubnetName', to be given soon to a virtual network."

$subnetParams = @{
    Name            = $SubnetName
    AddressPrefix   = $SubnetAddressPrefix
    ServiceEndpoint = $ServiceEndpointTypeName_SqlDb
}
$subnet = New-AzVirtualNetworkSubnetConfig @subnetParams

Write-Host "Create a virtual network '$VNetName'.`nGive the subnet to the virtual network that we created."

$vnetParams = @{
    Name              = $VNetName
    AddressPrefix     = $VNetAddressPrefix
    Subnet            = $subnet
    ResourceGroupName = $ResourceGroupName
    Location          = $Region
}
$vnet = New-AzVirtualNetwork @vnetParams

###########################################################
##   Create a Virtual Service endpoint on the subnet.    ##
###########################################################

Write-Host "Assign a Virtual Service endpoint 'Microsoft.Sql' to the subnet."

$vnetSubParams = @{
    Name            = $SubnetName
    AddressPrefix   = $SubnetAddressPrefix
    VirtualNetwork  = $vnet
    ServiceEndpoint = $ServiceEndpointTypeName_SqlDb
}
$vnet = Set-AzVirtualNetworkSubnetConfig @vnetSubParams

Write-Host "Persist the updates made to the virtual network > subnet."

$vnet = Set-AzVirtualNetwork -VirtualNetwork $vnet

$vnet.Subnets[0].ServiceEndpoints  # Display the first endpoint.

###########################################################
##   Add the Virtual Service endpoint Id as a rule,      ##
##   into SQL Database ACLs.                             ##
###########################################################

Write-Host "Get the subnet object."

$vnet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VNetName

$subnet = Get-AzVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $vnet

Write-Host "Add the subnet .Id as a rule, into the ACLs for your server."

$ruleParams = @{
    ResourceGroupName      = $ResourceGroupName
    ServerName             = $SqlDbServerName
    VirtualNetworkRuleName = $VNetRuleName
    VirtualNetworkSubnetId = $subnet.Id
}
New-AzSqlServerVirtualNetworkRule @ruleParams 

Write-Host "Verify that the rule is in the SQL Database ACL."

$rule2Params = @{
    ResourceGroupName      = $ResourceGroupName
    ServerName             = $SqlDbServerName
    VirtualNetworkRuleName = $VNetRuleName
}
Get-AzSqlServerVirtualNetworkRule @rule2Params

Write-Host 'Completed script 3, the "Virtual-Network-Rule".'

指令碼 4:清理

此最終指令碼會刪除先前指令碼為示範所建立的資源。 不過,指令碼會在刪除下列資源之前要求確認:

  • 邏輯 SQL 伺服器
  • Azure 資源群組

您可以在指令碼 1 完成之後隨時執行指令碼 4。

PowerShell 指令碼 4 原始程式碼

######### Script 4 ########################################
##   Clean-up phase A:  Unconditional deletes.           ##
##                                                       ##
##   1. The test rule is deleted from SQL Database ACL.        ##
##   2. The test endpoint is deleted from the subnet.    ##
##   3. The test virtual network is deleted.             ##
###########################################################

Write-Host "Delete the rule from the SQL Database ACL."

$removeParams = @{
    ResourceGroupName      = $ResourceGroupName
    ServerName             = $SqlDbServerName
    VirtualNetworkRuleName = $VNetRuleName
    ErrorAction            = 'SilentlyContinue'
}
Remove-AzSqlServerVirtualNetworkRule @removeParams

Write-Host "Delete the endpoint from the subnet."

$vnet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VNetName

Remove-AzVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $vnet

Write-Host "Delete the virtual network (thus also deletes the subnet)."

$removeParams = @{
    Name              = $VNetName
    ResourceGroupName = $ResourceGroupName
    ErrorAction       = 'SilentlyContinue'
}
Remove-AzVirtualNetwork @removeParams

###########################################################
##   Clean-up phase B:  Conditional deletes.             ##
##                                                       ##
##   These might have already existed, so user might     ##
##   want to keep.                                       ##
##                                                       ##
##   1. Logical SQL server                        ##
##   2. Azure resource group                             ##
###########################################################

$yesno = Read-Host 'CAUTION !: Do you want to DELETE your server AND your resource group?  [yes/no]'
if ('yes' -eq $yesno) {
    Write-Host "Remove the server."

    $removeParams = @{
        ServerName        = $SqlDbServerName
        ResourceGroupName = $ResourceGroupName
        ErrorAction       = 'SilentlyContinue'
    }
    Remove-AzSqlServer @removeParams

    Write-Host "Remove the Azure Resource Group."
    
    Remove-AzResourceGroup -Name $ResourceGroupName -ErrorAction SilentlyContinue
} else {
    Write-Host "Skipped over the DELETE of SQL Database and resource group."
}

Write-Host 'Completed script 4, the "Clean-Up".'

確認子網路是端點

您可能有已指派 Microsoft.Sql 類型名稱的子網路,這表示它已經是虛擬服務端點。 您可以使用 Azure 入口網站從端點建立虛擬網路規則。

或者,您可能不確定您的子網路是否有 Microsoft.Sql 類型名稱。 您可以執行下列 PowerShell 指令碼來進行下列動作:

  1. 確定您的子網路是否具有 Microsoft.Sql 類型名稱。
  2. 或者,如果不存在,請指派該類型名稱。
    • 指令碼會要求您確認,然後才會套用不存在的類型名稱。

指令碼的階段

以下是 PowerShell 指令碼的階段:

  1. 登入您的 Azure 帳戶,每個 PS 工作階段只需要登入一次。 指派變數。
  2. 搜尋您的虛擬網路,然後搜尋您的子網路。
  3. 您的子網路是否標記為 Microsoft.Sql 端點伺服器類型?
  4. 在您的子網路上新增類型名稱為 Microsoft.Sql 的虛擬服務端點。

重要

執行此指令碼之前,您必須在靠近指令碼頂端的位置,編輯指派給 $-variables 的值。

Direct PowerShell 原始程式碼

此 PowerShell 指令碼不會更新任何內容,除非您在系統要求確認時回應是。 指令碼可以將類型名稱 Microsoft.Sql 新增至您的子網路。 但是,指令碼僅在子網路缺少類型名稱時才會嘗試此新增動作。

### 1. LOG into to your Azure account, needed only once per PS session.  Assign variables.
$yesno = Read-Host 'Do you need to log into Azure (only one time per powershell.exe session)?  [yes/no]'
if ('yes' -eq $yesno) { Connect-AzAccount }

# Assignments to variables used by the later scripts.
# You can EDIT these values, if necessary.

$SubscriptionName = 'yourSubscriptionName'
Select-AzSubscription -SubscriptionName "$SubscriptionName"

$ResourceGroupName = 'yourRGName'
$VNetName = 'yourVNetName'
$SubnetName = 'yourSubnetName'
$SubnetAddressPrefix = 'Obtain this value from the Azure portal.' # Looks roughly like: '10.0.0.0/24'

$ServiceEndpointTypeName_SqlDb = 'Microsoft.Sql'  # Do NOT edit. Is official value.

### 2. Search for your virtual network, and then for your subnet.
# Search for the virtual network.
$vnet = $null
$vnet = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VNetName

if ($vnet -eq $null) {
    Write-Host "Caution: No virtual network found by the name '$VNetName'."
    return
}

$subnet = $null
for ($nn = 0; $nn -lt $vnet.Subnets.Count; $nn++) {
    $subnet = $vnet.Subnets[$nn]
    if ($subnet.Name -eq $SubnetName) { break }
    $subnet = $null
}

if ($null -eq $subnet) {
    Write-Host "Caution: No subnet found by the name '$SubnetName'"
    Return
}

### 3. Is your subnet tagged as 'Microsoft.Sql' endpoint server type?
$endpointMsSql = $null
for ($nn = 0; $nn -lt $subnet.ServiceEndpoints.Count; $nn++) {
    $endpointMsSql = $subnet.ServiceEndpoints[$nn]
    if ($endpointMsSql.Service -eq $ServiceEndpointTypeName_SqlDb) {
        $endpointMsSql
        break
    }
    $endpointMsSql = $null
}

if ($null -eq $endpointMsSql) {
    Write-Host "Good: Subnet found, and is already tagged as an endpoint of type '$ServiceEndpointTypeName_SqlDb'."
    return
} else {
    Write-Host "Caution: Subnet found, but not yet tagged as an endpoint of type '$ServiceEndpointTypeName_SqlDb'."

    # Ask the user for confirmation.
    $yesno = Read-Host 'Do you want the PS script to apply the endpoint type name to your subnet?  [yes/no]'
    if ('no' -eq $yesno) { return }
}

### 4. Add a Virtual Service endpoint of type name 'Microsoft.Sql', on your subnet.
$setParams = @{
    Name            = $SubnetName
    AddressPrefix   = $SubnetAddressPrefix
    VirtualNetwork  = $vnet
    ServiceEndpoint = $ServiceEndpointTypeName_SqlDb
}
$vnet = Set-AzVirtualNetworkSubnetConfig @setParams

# Persist the subnet update.
$vnet = Set-AzVirtualNetwork -VirtualNetwork $vnet

for ($nn = 0; $nn -lt $vnet.Subnets.Count; $nn++) {
    $vnet.Subnets[0].ServiceEndpoints # Display.
}