教學課程:使用 Azure AD 應用程式建立 Azure AD 使用者

適用于:Azure SQL資料庫

此文章將逐步引導您使用 Azure 服務主體 (Azure AD 應用程式),在 Azure SQL Database 中建立 Azure AD 使用者的程序。 此功能已經存在於 Azure SQL 受控執行個體中,但現在即將在 Azure SQL Database 中推出。 為了支援此案例,必須產生 Azure AD 身分識別,並將其指派給 Azure SQL 邏輯伺服器。

如需針對 Azure SQL 進行 Azure AD 驗證的詳細資訊,請參閱使用 Azure Active Directory 驗證

在本教學課程中,您會了解如何:

  • 將身分識別指派給 Azure SQL 邏輯伺服器
  • 將目錄讀取者權限指派給 SQL 邏輯伺服器身分識別
  • 在 Azure AD 中建立服務主體 (Azure AD 應用程式)
  • 在 Azure SQL Database 中建立服務主體使用者
  • 使用 Azure AD 服務主體使用者,在 SQL Database 中建立不同的 Azure AD 使用者

必要條件

  • 現有的 Azure SQL Database 部署。 我們假設您在此教學課程中有一個可運作的 SQL Database。
  • 可存取已經存在的 Azure Active Directory。
  • 使用 PowerShell 以針對 Azure SQL 將個別 Azure AD 應用程式設定為 Azure AD 管理員時,需要 Az.Sql 2.9.0 \(英文\) 模組或更新版本。 確定您已升級到最新模組。

將身分識別指派給 Azure SQL 邏輯伺服器

  1. 連線到您的 Azure Active Directory。 您將需要尋找您的租用戶識別碼。 前往 Azure 入口網站,然後前往您的 Azure Active Directory 資源,即可找到此項。 在 [概觀] 窗格中,應該會看到您的租用戶識別碼。 執行下列 PowerShell 命令:

    • 使用您的租用戶識別碼取代 <TenantId>
    Connect-AzAccount -Tenant <TenantId>
    

    記錄 TenantId,以供未來在此教學課程中使用。

  2. 產生 Azure AD 身分識別並指派給 Azure SQL 邏輯伺服器。 執行下列 PowerShell 命令:

    • 使用您的資源取代 <resource group><server name>。 如果您的伺服器名稱是 myserver.database.windows.net,使用 myserver 取代 <server name>
    Set-AzSqlServer -ResourceGroupName <resource group> -ServerName <server name> -AssignIdentity
    

    如需詳細資訊,請參閱 Set-AzSqlServer \(英文\) 命令。

    重要

    如果已針對 Azure SQL 邏輯伺服器設定 Azure AD 身分識別,則必須將目錄讀取者權限授與身分識別。 我們將在下一節逐步解說此步驟。 請勿跳過此步驟,因為 Azure AD 驗證將停止運作。

    有了適用於 Azure SQL 的 Microsoft Graph 支援,您可以使用較低層級的權限取代「目錄讀取者」角色。 如需詳細資訊,請參閱適用於 Azure SQL 的 Azure AD 中的使用者指派受控識別

    如果系統指派或使用者指派的受控識別是用來作為伺服器或執行個體身分識別,則刪除身分識別將導致伺服器或執行個體無法存取 Microsoft Graph。 Azure AD 驗證和其他函數將會失敗。 若要還原 Azure AD 功能,必須將新的 SMI 或 UMI 指派給具有適當權限的伺服器。

    • 如果您過去已使用 New-AzSqlServer \(英文\) 命令搭配 AssignIdentity 參數來建立新的 SQL 伺服器,則您之後將需要以個別命令形式執行 Set-AzSqlServer \(英文\) 命令,在 Azure 網狀架構中啟用此屬性。
  3. 檢查是否已成功指派伺服器身分識別。 執行下列 PowerShell 命令:

    • 使用您的資源取代 <resource group><server name>。 如果您的伺服器名稱是 myserver.database.windows.net,使用 myserver 取代 <server name>
    $xyz = Get-AzSqlServer  -ResourceGroupName <resource group> -ServerName <server name>
    $xyz.identity
    

    您的輸出應該會顯示 PrincipalIdTypeTenantId。 指派的身分識別是 PrincipalId

  4. 您也可以前往 Azure 入口網站來檢查身分識別。

    • 在 [Azure Active Directory] 資源底下,前往 [企業應用程式]。 輸入您的 SQL 邏輯伺服器名稱。 您將會看到其具有一個已附加至資源的物件識別碼

    object-id

將目錄讀取者權限指派給 SQL 邏輯伺服器身分識別

若要讓 Azure AD 指派的身分識別能夠針對 Azure SQL 正常運作,就必須將 Azure AD Directory Readers 權限授與伺服器身分識別。

若要授與此必要權限,請執行下列指令碼。

注意

此指令碼必須由 Azure AD Global AdministratorPrivileged Roles Administrator 執行。

您可以在 Azure AD 中將 Directory Readers 角色指派給群組。 然後,群組擁有者可以將受控識別新增為此群組的成員,這將會略過 Global AdministratorPrivileged Roles Administrator 授與 Directory Readers 角色的需求。 如需這項功能的詳細資訊,請參閱 Azure Active Directory 中適用於 Azure SQL 的 Directory 讀者角色

  • 使用稍早蒐集的 TenantId 取代 <TenantId>
  • 使用您自己的 SQL 邏輯伺服器名稱取代 <server name>。 如果您的伺服器名稱是 myserver.database.windows.net,使用 myserver 取代 <server name>
# This script grants Azure "Directory Readers" permission to a Service Principal representing the Azure SQL logical server
# It can be executed only by a "Global Administrator" or "Privileged Roles Administrator" type of user.
# To check if the "Directory Readers" permission was granted, execute this script again

Import-Module AzureAD
Connect-AzureAD -TenantId "<TenantId>"    #Enter your actual TenantId
$AssignIdentityName = "<server name>"     #Enter Azure SQL logical server name
 
# Get Azure AD role "Directory Users" and create if it doesn't exist
$roleName = "Directory Readers"
$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq $roleName}
if ($role -eq $null) {
    # Instantiate an instance of the role template
    $roleTemplate = Get-AzureADDirectoryRoleTemplate | Where-Object {$_.displayName -eq $roleName}
    Enable-AzureADDirectoryRole -RoleTemplateId $roleTemplate.ObjectId
    $role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq $roleName}
}
 
# Get service principal for server
$roleMember = Get-AzureADServicePrincipal -SearchString $AssignIdentityName
$roleMember.Count
if ($roleMember -eq $null) {
    Write-Output "Error: No Service Principals with name '$($AssignIdentityName)', make sure that AssignIdentityName parameter was entered correctly."
    exit
}

if (-not ($roleMember.Count -eq 1)) {
    Write-Output "Error: More than one service principal with name pattern '$($AssignIdentityName)'"
    Write-Output "Dumping selected service principals...."
    $roleMember
    exit
}
 
# Check if service principal is already member of readers role
$allDirReaders = Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId
$selDirReader = $allDirReaders | where{$_.ObjectId -match $roleMember.ObjectId}
 
if ($selDirReader -eq $null) {
    # Add principal to readers role
    Write-Output "Adding service principal '$($AssignIdentityName)' to 'Directory Readers' role'..."
    Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $roleMember.ObjectId
    Write-Output "'$($AssignIdentityName)' service principal added to 'Directory Readers' role'..."
 
    #Write-Output "Dumping service principal '$($AssignIdentityName)':"
    #$allDirReaders = Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId
    #$allDirReaders | where{$_.ObjectId -match $roleMember.ObjectId}
} else {
    Write-Output "Service principal '$($AssignIdentityName)' is already member of 'Directory Readers' role'."
}

注意

上述這個指令碼的輸出將指出是否已將目錄讀取者權限授與該身分識別。 如果您不確定是否已授與權限,則可重新執行指令碼。

如需如何針對 SQL 受控執行個體設定目錄讀取者權限的類似方法,請參閱佈建 Azure AD 管理員 (SQL 受控執行個體)

在 Azure AD 中建立服務主體 (Azure AD 應用程式)

若您尚未這麼做,請註冊您的應用程式。 若要註冊應用程式,您必須是 Azure AD 管理員或獲指派 Azure AD「應用程式開發人員」角色的使用者。 如需指派角色的詳細資訊,請參閱使用 Azure Active Directory 將系統管理員和非系統管理員角色指派給使用者

應用程式註冊完成後,會產生與顯示應用程式識別碼

若要註冊應用程式:

  1. 請在 Azure 入口網站中,選取 [Azure Active Directory]>[應用程式註冊]>[新增註冊]。

    應用程式註冊

    應用程式註冊建立之後,會產生及顯示應用程式識別碼值。

    顯示的應用程式識別碼

  2. 您也必須建立用於登入的用戶端密碼。 依照此處的指南上傳憑證或建立秘密以進行登入

  3. 從您的應用程式註冊記錄下列各項。 您可以從 [概觀] 窗格中取得:

    • 應用程式識別碼
    • 租用戶識別碼:這應該會與之前的相同

在此教學課程中,我們將使用 AppSP 作為主要服務主體,並使用 myapp 作為第二個服務主體使用者 (將在 Azure SQL 中由 AppSP 所建立)。 您將需要建立兩個應用程式:AppSPmyapp

如需如何建立 Azure AD 應用程式的詳細資訊,請參閱下文:操作說明:使用入口網站來建立可存取資源的 Azure AD 應用程式和服務主體

在 Azure SQL Database 中建立服務主體使用者

在 Azure AD 中建立服務主體之後,在 SQL Database 中建立使用者。 您將必須使用具有權限的有效登入來連線到您的 SQL Database,以在資料庫中建立使用者。

重要

只有 Azure AD 使用者可以在 Azure SQL 資料庫中建立其他 Azure AD 使用者。 任何具有 SQL 驗證的 SQL 使用者,包括伺服器管理員都無法建立 Azure AD 使用者。 Azure AD 系統管理員是一開始可以在 SQL Database 中建立 Azure AD 使用者的唯一使用者。 在 Azure AD 系統管理員建立其他使用者之後,任何具有適當許可權的 Azure AD 使用者都可以建立其他 Azure AD 使用者。

  1. 使用下列 T-SQL 命令,在 SQL Database 中建立使用者 AppSP

    CREATE USER [AppSP] FROM EXTERNAL PROVIDER
    GO
    
  2. db_owner 權限授與 AppSP,讓使用者能夠在資料庫中建立其他 Azure AD 使用者。

    EXEC sp_addrolemember 'db_owner', [AppSP]
    GO
    

    如需詳細資訊,請參閱 sp_addrolemember \(部分機器翻譯\)。

    或者,可以授與 ALTER ANY USER 權限,而不是提供 db_owner 角色。 這將可讓服務主體新增其他 Azure AD 使用者。

    GRANT ALTER ANY USER TO [AppSp]
    GO
    

    注意

    已針對伺服器將 AppSP 設定為 Azure AD 管理員時,就不需要上述設定。 若要針對 SQL 邏輯伺服器將服務主體設定為 AD 管理員,您可以使用 Azure 入口網站、PowerShell 或 Azure CLI 命令。 如需詳細資訊,請參閱佈建 Azure AD 管理員 (SQL Database)

使用 Azure AD 服務主體,在 SQL Database 中建立 Azure AD 使用者

重要

用來登入 SQL Database 的服務主體必須具有用戶端密碼。 如果沒有,請遵循在 Azure AD 中建立服務主體 (Azure AD 應用程式) 的步驟 2。 在下列指令碼中,必須將此用戶端密碼新增為輸入參數。

  1. 使用下列指令碼,使用服務主體 AppSP 來建立 Azure AD 服務主體使用者 myapp

    • 使用稍早蒐集的 TenantId 取代 <TenantId>
    • 使用稍早蒐集的 ClientId 取代 <ClientId>
    • 使用稍早建立的用戶端密碼取代 <ClientSecret>
    • 使用您自己的 SQL 邏輯伺服器名稱取代 <server name>。 如果您的伺服器名稱是 myserver.database.windows.net,使用 myserver 取代 <server name>
    • 使用您的 SQL Database 名稱取代 <database name>
    # PowerShell script for creating a new SQL user called myapp using application AppSP with secret
    # AppSP is part of an Azure AD admin for the Azure SQL server below
    
    # Download latest  MSAL  - https://www.powershellgallery.com/packages/MSAL.PS
    Import-Module MSAL.PS
    
    $tenantId = "<TenantId>"   # tenantID (Azure Directory ID) were AppSP resides
    $clientId = "<ClientId>"   # AppID also ClientID for AppSP     
    $clientSecret = "<ClientSecret>"   # Client secret for AppSP 
    $scopes = "https://database.windows.net/.default" # The end-point
    
    $result = Get-MsalToken -RedirectUri $uri -ClientId $clientId -ClientSecret (ConvertTo-SecureString $clientSecret -AsPlainText -Force) -TenantId $tenantId -Scopes $scopes
    
    $Tok = $result.AccessToken
    #Write-host "token"
    $Tok
    
    $SQLServerName = "<server name>"    # Azure SQL logical server name 
    $DatabaseName = "<database name>"     # Azure SQL database name
    
    Write-Host "Create SQL connection string"
    $conn = New-Object System.Data.SqlClient.SQLConnection 
    $conn.ConnectionString = "Data Source=$SQLServerName.database.windows.net;Initial Catalog=$DatabaseName;Connect Timeout=30"
    $conn.AccessToken = $Tok
    
    Write-host "Connect to database and execute SQL script"
    $conn.Open() 
    $ddlstmt = 'CREATE USER [myapp] FROM EXTERNAL PROVIDER;'
    Write-host " "
    Write-host "SQL DDL command"
    $ddlstmt
    $command = New-Object -TypeName System.Data.SqlClient.SqlCommand($ddlstmt, $conn)       
    
    Write-host "results"
    $command.ExecuteNonQuery()
    $conn.Close()
    

    或者,您可以使用 Azure AD 服務主體驗證至 SQL DB - 程式碼範例 \(英文\) 部落格中的程式碼範例。 修改指令碼,以執行 DDL 陳述式 CREATE USER [myapp] FROM EXTERNAL PROVIDER。 您可以使用相同的指令碼,在 SQL Database 中建立一般的 Azure AD 使用者或群組。

  2. 執行下列命令,以檢查使用者 myapp 是否存在於資料庫中:

    SELECT name, type, type_desc, CAST(CAST(sid as varbinary(16)) as uniqueidentifier) as appId from sys.database_principals WHERE name = 'myapp'
    GO
    

    您應該會看到如下的輸出:

    name	type	type_desc	appId
    myapp	E	EXTERNAL_USER	6d228f48-xxxx-xxxx-xxxx-xxxxxxxxxxxx
    

後續步驟