Руководство по настройке администратора Microsoft Entra для SQL Server с помощью автоматизации
Статья
Область применения: SQL Server 2022 (16.x)
Примечание.
Эта функция доступна в SQL Server 2022 (16.x) или более поздних версиях и поддерживается только для локальных версий SQL Server для узлов Windows и Linux и SQL Server 2022 на виртуальных машинах Windows Azure.
В этой статье мы рассмотрим, как настроить администратора Microsoft Entra, чтобы разрешить проверку подлинности с помощью идентификатора Microsoft Entra (ранее Azure Active Directory) для SQL Server с помощью портал Azure и API, таких как:
Хотя идентификатор Microsoft Entra — это новое имя Azure Active Directory (Azure AD), чтобы предотвратить нарушение существующих сред, Azure AD по-прежнему остается в некоторых жестко закодированных элементах, таких как поля пользовательского интерфейса, поставщики подключений, коды ошибок и командлеты. В этой статье два имени являются взаимозаменяемыми.
Необходимые компоненты
УСТАНАВЛИВАЕТСЯ SQL Server 2022 (16.x) или более поздней версии.
Подготовка перед настройкой администратора Microsoft Entra
Для настройки администратора Microsoft Entra в SQL Server — ресурсов Azure Arc и хранилища ключей необходимы следующие разрешения.
Настройка разрешений для Azure Arc
Следуйте инструкциям, чтобы убедиться, что SQL Server подключен к Azure Arc. Пользователь, настроив администратора Microsoft Entra для SQL Server — ресурс Azure Arc , должен иметь роль участника для сервера.
Выберите SQL Server — Azure Arc и выберите экземпляр для узла SQL Server.
Выберите Управление доступом (IAM).
Нажмите кнопку Добавить>назначение ролей, чтобы добавить роль участника в настройку администратора Microsoft Entra.
Настройка разрешений для Azure Key Vault
Создайте Azure Key Vault, если у вас его еще нет. Пользователь, настроив администратор Microsoft Entra, должен иметь роль участника для Azure Key Vault. Чтобы добавить роль пользователю в Azure Key Vault, выполните приведенные действия.
Нажмите кнопку Добавить>назначение ролей, чтобы добавить роль участника в настройку администратора Microsoft Entra.
Настройка политик доступа для узла SQL Server
В портал Azure перейдите к экземпляру Azure Key Vault и выберите политики доступа.
Выберите Добавить политику доступа.
Для разрешений ключа используйте знак.
Для разрешений "Секрет" выберите " Получить " и "Список".
Для разрешений сертификата выберите "Получить" и "Список".
Выберите Далее.
На главной странице найдите имя экземпляра Azure Arc, который является именем узла узла SQL Server.
Пропустить страницу приложения (необязательно), нажав кнопку "Далее" дважды или выбрав "Просмотр и создание".
Убедитесь, что идентификатор объекта субъекта соответствует идентификатору субъекта управляемого удостоверения, назначенному экземпляру.
Чтобы подтвердить, перейдите на страницу ресурсов и выберите представление JSON в правом верхнем углу поля "Основные сведения" на странице "Обзор". В разделе удостоверений вы найдете субъект-идентификатор.
Нажмите кнопку создания.
Чтобы убедиться, что применены разрешения, необходимо выбрать "Создать ". Чтобы убедиться, что разрешения сохранены, обновите окно браузера и убедитесь, что строка для экземпляра Azure Arc по-прежнему присутствует.
Настройка политик доступа для пользователей Microsoft Entra
В портал Azure перейдите к экземпляру Azure Key Vault и выберите политики доступа.
Выберите Добавить политику доступа.
Для разрешений "Ключи" выберите " Получить", "Список" и "Создать".
Для разрешений "Секрет" выберите " Получить", "Список" и "Задать".
Для разрешений сертификата выберите "Получить", "Список" и "Создать".
Для выбора субъекта добавьте пользователя Microsoft Entra, который вы хотите использовать для подключения к SQL Server.
Нажмите кнопку Добавить, а затем выберите Сохранить.
Настройка администратора Microsoft Entra для SQL Server
Новые api и функции портала позволяют пользователям настраивать администратора Microsoft Entra для SQL Server без необходимости отдельно создавать сертификат Azure и приложение Microsoft Entra. Выберите вкладку, чтобы узнать, как настроить администратора Microsoft Entra для SQL Server, подключенного к Azure Arc, с автоматическим сертификатом и созданием приложений.
Примечание.
Шаблон ARM по-прежнему требует создания сертификата Azure Key Vault и приложения Microsoft Entra перед настройкой администратора Microsoft Entra. Дополнительные сведения об этом процессе см. в руководстве по настройке проверки подлинности Microsoft Entra для SQL Server.
Используйте портал Azure для настройки администратора Microsoft Entra, создайте сертификат Azure Key Vault и приложение Microsoft Entra в том же процессе. Это необходимо для использования проверки подлинности Microsoft Entra с SQL Server.
Примечание.
Ранее перед настройкой администратора Microsoft Entra требуется сертификат Azure Key Vault и регистрация приложения Microsoft Entra. Это больше не требуется, но пользователи по-прежнему могут предоставить свой собственный сертификат и приложение для настройки администратора Microsoft Entra.
Настройка администратора Microsoft Entra с помощью портал Azure
Проверьте состояние ресурса SQL Server — Azure Arc и убедитесь в том, что он подключен, перейдя в меню Свойства. Дополнительные сведения см. в статье "Проверка ресурсов SQL Server с поддержкой Arc".
Выберите идентификатор Microsoft Entra и Purview в разделе "Параметры " в меню ресурсов.
Выберите " Задать администратора" , чтобы открыть область идентификатора Microsoft Entra, и выберите учетную запись, которая будет добавлена в качестве имени администратора в SQL Server.
Выберите Сохранить. Это отправляет запрос агенту сервера Arc, который настраивает проверку подлинности Microsoft Entra для этого экземпляра SQL Server. Операция может занять несколько минут; Дождитесь подтверждения процесса Saved successfully сохранения перед попыткой входа Microsoft Entra.
Регистрация приложения, управляемого службой, выполняет следующие действия.
Создает сертификат в хранилище ключей с именем в форме <hostname>-<instanceName><uniqueNumber>.
Создает приложение Microsoft Entra с таким именем, как <hostname>-<instanceName><uniqueNumber>и назначает необходимые разрешения для этого приложения. Дополнительные сведения см. в разделе "Предоставление разрешений приложения"
Назначает новый сертификат в Azure Key Vault приложению.
Сохраняет эти параметры в Azure Arc.
Примечание.
Сертификаты, созданные для Microsoft Entra, не поворачиваются автоматически. Клиенты могут предоставить собственный сертификат и приложение для настройки администратора Microsoft Entra. Дополнительные сведения см. в руководстве по настройке проверки подлинности Microsoft Entra для SQL Server.
Требуется Az.ConnectedMachine 0.5.1 или более поздней версии
Чтобы установить Az.ConnectedMachine модуль, используйте az extension add --name ConnectedMachine. Чтобы проверить, какая версия Azure CLI установлена, используйте az version.
Для скрипта Azure CLI используются следующие входные параметры:
<applicationName> — Имя приложения, которое будет создано
<certSubjectName> — имя сертификата, которое будет создано
<keyVaultName> — Имя хранилища ключей. Перед выполнением скрипта необходимо создать это хранилище ключей.
<machineName> — имя компьютера узла SQL Server
<resourceGroupName>— Имя группы ресурсов, содержащее экземпляр SQL Server — Экземпляр Azure Arc
<adminAccountName> — учетная запись администратора Microsoft Entra, которую вы хотите задать для SQL Server
<instanceName> — необязательный параметр для именованных экземпляров SQL Server. Используйте этот параметр при наличии именованного экземпляра. Если опущено, используется имя MSSQLSERVER по умолчанию
<tenantId> — необязательный параметр для идентификатора клиента. Идентификатор клиента можно найти, перейдя в портал Azure и перейдя к ресурсу идентификатора Microsoft Entra ID. В области Обзор отобразится идентификатор клиента. Если опущено, идентификатор клиента по умолчанию используется в качестве параметра.
<subscriptionId> — необязательный параметр для идентификатора подписки. Идентификатор подписки можно найти в портал Azure. Если опущено, используется идентификатор подписки по умолчанию
Чтобы использовать приведенный ниже скрипт Azure CLI, сохраните скрипт в виде .ps1 файла и выполните следующую команду:
Для SQL Server на Linux хост-компьютеров замените WindowsAgent.SqlServerLinuxAgent.SqlServer его в скрипте.
# AZ CLI and AZ CLI's connected machine extension must be installed before running this script
param (
[Parameter(mandatory=$true)] $applicationName,
[Parameter(mandatory=$true)] $certSubjectName,
[Parameter(mandatory=$true)] $keyVaultName,
[Parameter(mandatory=$true)] $machineName,
[Parameter(mandatory=$true)] $resourceGroupName,
[Parameter(mandatory=$true)] $adminAccountName,
$instanceName,
$tenantId,
$subscriptionId
)
# Constants
#
$NUMRETRIES = 60
# Helper functions
#
function ConvertFrom-StringArray {
param (
[string[]] $stringArray
)
if (!$stringArray)
{
return $null
}
else
{
return ConvertFrom-JSON ($stringArray -join "`n")
}
}
# Check parameters
#
if ([string]::IsNullOrEmpty($instanceName))
{
Write-Host "Warning: SQL Instance name (-instanceName) not provided. Default of MSSQLSERVER will be used"
$instanceName = "MSSQLSERVER"
}
$tenantIdArgument = ""
if ([string]::IsNullOrEmpty($tenantId))
{
Write-Host "Warning: Tenant ID (-tenantId) not supplied to the script, so default tenant is being used"
}
else
{
$tenantIdArgument = "-TenantId '" + $tenantId + "'"
}
$subscriptionIdArgument = ""
if ([string]::IsNullOrEmpty($subscriptionId))
{
Write-Host "Warning: Subscription ID (-subscriptionId) not supplied to the script, so default subscription is being used"
}
else
{
$subscriptionIdArgument = "-SubscriptionId '" + $subscriptionId + "'"
}
# Login and select subscription
#
$login = az login --tenant $tenantId --use-device-code
if (!$login)
{
Write-Error "Login to Azure AD failed. Exiting."
exit 1
}
if ($subscriptionId)
{
az account set -s $subscriptionId
}
$accountInfo = ConvertFrom-StringArray (az account show)
if (!$accountInfo)
{
Write-Error "Cannot query logged in Azure AD account. Check that 'az login' and 'az account set' succeeded"
exit 1
}
if ($subscriptionId)
{
if ($subscriptionId.ToLower() -ne $accountInfo.id.ToLower())
{
Write-Error "Could not select the desired subscription"
exit 1
}
}
else
{
$subscriptionId = $accountInfo.id
}
# Check AKV path exists
#
$keyVault = ConvertFrom-StringArray (az keyvault show --name $keyVaultName)
if (!$keyVault)
{
Write-Error "Azure key vault '$keyVaultName' does not exist"
exit 1
}
# Check certificate doesn't exist
#
$cert = ConvertFrom-StringArray (az keyvault certificate show --name $certSubjectName --vault-name $keyVaultName 2>$null)
if ($cert)
{
Write-Error "Certificate '$certSubjectName' already exists in key vault '$keyVaultName'"
exit 1
}
# Check app registration doesn't exist
#
$applications = ConvertFrom-StringArray (az ad app list --display-name $applicationName --only-show-errors)
if ($applications.length -gt 0)
{
Write-Error "App registration with name '$applicationName' already exists"
exit 1
}
# Check Arc SQL instance is valid
#
$extension = ConvertFrom-StringArray (az connectedmachine extension show --machine-name $machineName --name "WindowsAgent.SqlServer" --resource-group $resourceGroupName)
if (!$extension)
{
Write-Error "SQL Server Arc Server not found for machine '$machineName' in resource group '$resourceGroupName'"
exit 1
}
$arcServicePrincipals = ConvertFrom-StringArray(az ad sp list --display-name $machineName --only-show-errors)
if (!$arcServicePrincipals -or $arcServicePrincipals.length -eq 0)
{
Write-Error "Could not find a service principal account with the name '$machineName'"
exit 1
}
else
{
$principalFound = $false
for ($i = 0; $i -lt $arcServicePrincipals.length; $i++)
{
if ($arcServicePrincipals[$i].displayName.toLower() -eq $machineName.toLower()) {
if ($principalFound) {
Write-Error "Could not find exactly one service principal account with the name '$machineName'"
exit 1
}
$arcServicePrincipal = $arcServicePrincipals[$i]
$principalFound = $true
}
}
if (!$principalFound) {
Write-Error "Could not find a service principal account with the name '$machineName'"
exit 1
}
}
# Check if admin account exists
#
$adminAccount = ConvertFrom-StringArray (az ad user show --id $adminAccountName --only-show-errors 2>$null)
$adminAccountType = 0
if (!$adminAccount)
{
$adminAccounts = ConvertFrom-StringArray (az ad user list --filter "mail eq '$adminAccountName'" --only-show-errors 2>$null)
if ($adminAccounts -and $adminAccounts.length -gt 0)
{
if ($adminAccounts.length -eq 1)
{
$adminAccount = $adminAccounts[0]
}
else
{
Write-Error "Multiple Azure AD accounts found with identifier '$adminAccountName'"
exit 1
}
}
else
{
$adminAccount = ConvertFrom-StringArray (az ad group show --group $adminAccountName --only-show-errors 2>$null)
if (!$adminAccount)
{
$adminAccounts = ConvertFrom-StringArray (az ad app list --display-name $adminAccountName --only-show-errors 2>$null)
if ($adminAccounts -and $adminAccounts.length -gt 0)
{
if ($adminAccounts.length -eq 1)
{
$adminAccount = $adminAccounts[0]
}
else
{
Write-Error "Multiple Azure AD applications found with identifier '$adminAccountName'"
exit 1
}
}
else
{
Write-Error "Admin account not found"
exit 1
}
}
else
{
$adminAccountType = 1
}
}
}
if ($adminAccount)
{
$adminAccountSid = $adminAccount.id
}
else
{
Write-Error "Admin account not found"
exit 1
}
# Create certificate in AKV
#
$keyVaultPolicy = ConvertFrom-StringArray (az keyvault certificate get-default-policy)
if (!$keyVaultPolicy)
{
Write-Error "Could not get default key vault policy"
exit 1
}
$keyVaultPolicy.x509CertificateProperties.subject = "CN=" + $certSubjectName
$policyString = (ConvertTo-JSON -Depth 8 $keyVaultPolicy).replace("`r`n", "")
$escapedPolicyString = $policyString.replace("`"", "\`"")
$cert = ConvertFrom-StringArray (az keyvault certificate create --vault-name $keyVaultName --name $certSubjectName --policy $escapedPolicyString)
if (!$cert)
{
Write-Error "Failed to create certificate '$certSubjectName'"
exit 1
}
# Wait until cert is created?
#
$cert = ConvertFrom-StringArray (az keyvault certificate show --vault-name $keyVaultName --name $certSubjectName)
for (($i = 0); $i -lt $NUMRETRIES -and (!$cert -or !$cert.attributes.enabled); $i++)
{
$cert = ConvertFrom-StringArray (az keyvault certificate show --vault-name $keyVaultName --name $certSubjectName)
if (!$cert -or !$cert.attributes.enabled)
{
Start-Sleep -Seconds 5
}
}
# Allow Arc to access AKV
#
$newPerms = ConvertFrom-StringArray (az keyvault set-policy --name $keyVaultName --secret-permissions get list --certificate-permissions get list --object-id $arcServicePrincipal.id)
if (!$newPerms)
{
Write-Host "Warning: Unable to add permissions to key vault '$keyVaultName' for Arc's service principal's identity '$($arcServicePrincipal.id)'. Arc may not be able to configure Azure AD authentication"
}
# Create an Azure AD application
#
$application = ConvertFrom-StringArray (az ad app create --display-name $applicationName --only-show-errors)
if (!$application)
{
Write-Error "Unable to create the app registration '$applicationName'"
exit 1
}
# Set perms on app registration
#
az ad app permission add --id $application.id --api 00000003-0000-0000-c000-000000000000 --api-permissions c79f8feb-a9db-4090-85f9-90d820caa0eb=Scope --only-show-errors # Delegated Application.Read.All
az ad app permission add --id $application.id --api 00000003-0000-0000-c000-000000000000 --api-permissions 0e263e50-5827-48a4-b97c-d940288653c7=Scope --only-show-errors # Delegated Directory.AccessAsUser.All
az ad app permission add --id $application.id --api 00000003-0000-0000-c000-000000000000 --api-permissions 7ab1d382-f21e-4acd-a863-ba3e13f7da61=Role --only-show-errors # Application Directory.Read.All
az ad app permission add --id $application.id --api 00000003-0000-0000-c000-000000000000 --api-permissions 5f8c59db-677d-491f-a6b8-5f174b11ec1d=Scope --only-show-errors # Delegated Group.Read.All
az ad app permission add --id $application.id --api 00000003-0000-0000-c000-000000000000 --api-permissions a154be20-db9c-4678-8ab7-66f6cc099a59=Scope --only-show-errors # Delegated User.Read.All
# Upload cert to Azure AD
#
$certUploadRes = ConvertFrom-StringArray (az ad app credential reset --id $application.id --cert $certSubjectName --keyvault $keyVaultName --append --only-show-errors)
if (!$certUploadRes)
{
Write-Error "Failed to set certificate '$certSubjectName' as a credential for app registration '$applicationName'"
exit 1
}
# Remove the version from the secret ID if present
#
$secretId = $cert.sid
if ($secretId -Match "(https:\/\/[^\/]+\/secrets\/[^\/]+)(\/.*){0,1}$") {
if ($Matches[1]) {
$secretId = $Matches[1]
}
}
# Create the settings object to write to the Azure extension for SQL Server
#
$instanceSettings = @{
instanceName = $instanceName
adminLoginName = $adminAccountName
adminLoginSid = $adminAccountSid
azureCertSecretId = $secretId
azureCertUri = $cert.id
azureKeyVaultResourceUID = $keyVault.id
managedCertSetting = "CUSTOMER MANAGED CERT"
managedAppSetting = "CUSTOMER MANAGED APP"
appRegistrationName = $application.displayName
appRegistrationSid = $application.appId
tenantId = $tenantId
aadCertSubjectName = $certSubjectName
adminLoginType = $adminAccountType
}
$extension = ConvertFrom-StringArray (az connectedmachine extension show --machine-name $machineName --name "WindowsAgent.SqlServer" --resource-group $resourceGroupName)
if ($extension.properties.Settings.AzureAD)
{
$aadSettings = $extension.properties.Settings.AzureAD
$instanceFound = $false
$instanceNameLower = $instanceName.ToLower()
$instanceIndex = 0
for (($i = 0); $i -lt $aadSettings.Length; $i++)
{
if ($aadSettings[$i].instanceName.ToLower() -eq $instanceNameLower)
{
$instanceIndex = $i
$instanceFound = $true
break
}
}
if ($instanceFound)
{
$aadSettings[$instanceIndex] = $instanceSettings
}
else
{
$aadSettings += $instanceSettings
}
$extension.properties.Settings.AzureAD = $aadSettings
}
else
{
$aadSettings = , $instanceSettings
$extension.properties.Settings | Add-Member -Name 'AzureAD' -Value $aadSettings -MemberType NoteProperty
}
$settingsString = (ConvertTo-Json $extension.properties.Settings).replace("`"", "\`"").replace("`r`n", "")
# Push settings to Arc
#
Write-Host "Writing Azure AD setting to Azure extension for SQL Server. This may take several minutes..."
$updateRes = az connectedmachine extension update --machine-name $machineName --name "WindowsAgent.SqlServer" --resource-group $resourceGroupName --settings $settingsString
if (!$updateRes)
{
Write-Error "Failed to update Azure extension for SQL Server with Azure AD settings"
exit 1
}
Write-Output "Success"
Выполнение скрипта может занять несколько минут. После завершения процесса появится сообщение, аналогичное следующему:
Name Location ProvisioningState
---- -------- -----------------
WindowsAgent.SqlServer westus2 Succeeded
Success
Настройка администратора Microsoft Entra с существующим сертификатом и приложением с помощью Azure CLI
Если у вас уже есть сертификат Azure Key Vault и приложение Azure, которое вы хотите использовать для настройки администратора Microsoft Entra, можно использовать следующий скрипт CLI:
# Set up Microsoft Entra admin for user's existing key vault, certificate, and application
# Requires input parameters indicated below
# Connect statement
AZ Login
#Input parameters
$subscriptionId="<subscriptionId>"
$tenantId="<tenantId>"
$machineName="<machineName>" # hostname
$instanceName="<instanceName>" # SQL Server is define as `machine_name\instance_name`
$resourceGroupName="<resourceGroupName>"
$keyVaultName="<keyVaultName>"
$certSubjectName="<certSubjectName>" # Your existing certificate name
$applicationName="<applicationName>" # Your existing application name
$adminAccountName="<adminAccountName>"
$adminAccountSid="<adminID>" # Use object ID for the Azure AD user and group, or client ID for the Azure AD application
$adminAccountType= 0 # 0 – for Azure AD user and application, 1 for Azure AD group
# Helper function
#
function ConvertFrom-StringArray {
param (
[string[]] $stringArray
)
if (!$stringArray)
{
return $null
}
else
{
return ConvertFrom-JSON ($stringArray -join "`n")
}
}
$keyVault = ConvertFrom-StringArray (az keyvault show --name $keyVaultName)
if (!$keyVault)
{
Write-Error "Azure key vault '$keyVaultName' does not exist"
exit 1
}
$cert = ConvertFrom-StringArray (az keyvault certificate show --name $certSubjectName --vault-name $keyVaultName 2>$null)
if (!$cert)
{
Write-Error "Supplied certificate $certSubjectName was not found for this key vault. Please specify an existing certificate"
exit 1
}
$secretId = $cert.sid
if ($secretId -Match "(https:\/\/[^\/]+\/secrets\/[^\/]+)(\/.*){0,1}$") {
if ($Matches[1]) {
$secretId = $Matches[1]
}
}
$application = ConvertFrom-StringArray (az ad app list --display-name $applicationName --only-show-errors)
if (!$application)
{
Write-Error "Supplied application was not found in the subscription. Please specify an existing application"
exit 1
}
# Create the settings object to write to the Arc extension
#
$instanceSettings = @{
instanceName = $instanceName
adminLoginName = $adminAccountName
adminLoginSid = $adminAccountSid
azureCertSecretId = $secretId
azureCertUri = $cert.id
azureKeyVaultResourceUID = $keyVault.id
managedCertSetting = "CUSTOMER MANAGED CERT"
managedAppSetting = "CUSTOMER MANAGED APP"
appRegistrationName = $application.displayName
appRegistrationSid = $application.appId
tenantId = $tenantId
aadCertSubjectName = $certSubjectName
adminLoginType = $adminAccountType
}
$extension = ConvertFrom-StringArray (az connectedmachine extension show --machine-name $machineName --name "WindowsAgent.SqlServer" --resource-group $resourceGroupName)
if ($extension.properties.Settings.AzureAD)
{
$aadSettings = $extension.properties.Settings.AzureAD
$instanceFound = $false
$instanceNameLower = $instanceName.ToLower()
$instanceIndex = 0
for (($i = 0); $i -lt $aadSettings.Length; $i++)
{
if ($aadSettings[$i].instanceName.ToLower() -eq $instanceNameLower)
{
$instanceIndex = $i
$instanceFound = $true
break
}
}
if ($instanceFound)
{
$aadSettings[$instanceIndex] = $instanceSettings
}
else
{
$aadSettings += $instanceSettings
}
$extension.properties.Settings.AzureAD = $aadSettings
}
else
{
$aadSettings = , $instanceSettings
$extension.properties.Settings | Add-Member -Name 'AzureAD' -Value $aadSettings -MemberType NoteProperty
}
$settingsString = (ConvertTo-Json $extension.properties.Settings).replace("`"", "\`"").replace("`r`n", "")
# Push settings to Arc
#
Write-Host "Writing Azure AD setting to SQL Server Arc Extension. This may take several minutes..."
$updateRes = az connectedmachine extension update --machine-name $machineName --name "WindowsAgent.SqlServer" --resource-group $resourceGroupName --settings $settingsString
if (!$updateRes)
{
Write-Error "Failed to update SQL Arc Extension with Azure AD settings"
exit 1
}
Write-Output "Success"
Сертификаты, созданные для установки Microsoft Entra, не поворачиваются автоматически.
Для работы с этим руководством требуются следующие модули. Установите последние версии модулей или выше указанной ниже версии:
Az.Accounts 3.37.0
Az.ConnectedMachine 0.5.0
Az.KeyVault 4.5.0
Az.Resources 6.0.0
Для скрипта PowerShell используются следующие входные параметры:
<applicationName> — Имя приложения, которое будет создано
<certSubjectName> — имя сертификата, которое будет создано
<keyVaultName> — Имя хранилища ключей. Перед выполнением скрипта необходимо создать это хранилище ключей.
<machineName> — имя компьютера узла SQL Server
<resourceGroupName>— Имя группы ресурсов, содержащее экземпляр SQL Server — Экземпляр Azure Arc
<adminAccountName> — учетная запись администратора Microsoft Entra, которую вы хотите задать для SQL Server
<instanceName> — необязательный параметр для именованных экземпляров SQL Server. Используйте этот параметр при наличии именованного экземпляра. Если опущено, используется имя MSSQLSERVER по умолчанию
<tenantId> — необязательный параметр для идентификатора клиента. Идентификатор клиента можно найти, перейдя в портал Azure и перейдя к ресурсу идентификатора Microsoft Entra ID. В области Обзор отобразится идентификатор клиента. Если опущено, идентификатор клиента по умолчанию используется в качестве параметра.
<subscriptionId> — необязательный параметр для идентификатора подписки. Идентификатор подписки можно найти в портал Azure. Если опущено, используется идентификатор подписки по умолчанию
Чтобы использовать приведенный ниже сценарий PowerShell, сохраните скрипт в виде .ps1 файла и выполните следующую команду:
Для SQL Server на Linux хост-компьютеров замените WindowsAgent.SqlServerLinuxAgent.SqlServer его в скрипте.
param (
[Parameter(mandatory=$true)] $applicationName,
[Parameter(mandatory=$true)] $certSubjectName,
[Parameter(mandatory=$true)] $keyVaultName,
[Parameter(mandatory=$true)] $machineName,
[Parameter(mandatory=$true)] $resourceGroupName,
[Parameter(mandatory=$true)] $adminAccountName,
$instanceName,
$tenantId,
$subscriptionId
)
Import-Module Az.Accounts
Import-Module Az.ConnectedMachine
Import-Module Az.KeyVault
Import-Module Az.Resources
# Constants
#
$NUMRETRIES = 60
# Check parameters
#
if ([string]::IsNullOrEmpty($instanceName))
{
Write-Host "Warning: SQL Instance name (-instanceName) not provided. Default of MSSQLSERVER will be used"
$instanceName = "MSSQLSERVER"
}
$tenantIdArgument = ""
if ([string]::IsNullOrEmpty($tenantId))
{
Write-Host "Warning: Tenant ID (-tenantId) not supplied to the script, so default tenant is being used"
}
else
{
$tenantIdArgument = "-TenantId '" + $tenantId + "'"
}
$subscriptionIdArgument = ""
if ([string]::IsNullOrEmpty($subscriptionId))
{
Write-Host "Warning: Subscription ID (-subscriptionId) not supplied to the script, so default subscription is being used"
}
else
{
$subscriptionIdArgument = "-SubscriptionId '" + $subscriptionId + "'"
}
# Login
#
try
{
$loginRes = Invoke-Expression -Command ("Connect-AzAccount " + $tenantIdArgument + " " + $subscriptionIdArgument + " -ErrorAction stop -UseDeviceAuthentication")
}
catch
{
Write-Error $_
Write-Error "Failed to login to Azure. Script can not continue"
exit 1
}
# Get subscription ID
#
if ([string]::IsNullOrEmpty($subscriptionId))
{
$context = Get-AzContext
if ($context)
{
if ($context.Name -Match "[^(]+\(([^)]{36})\)")
{
if ($Matches[1])
{
$subscriptionId = $Matches[1]
}
}
}
}
if ([string]::IsNullOrEmpty($subscriptionId))
{
Write-Error "Failed to find default subscription"
exit 1
}
# Check AKV path exists
#
$keyVault = Get-AzKeyVault -VaultName $keyVaultName
if (!$keyVault)
{
Write-Error "Supplied key vault was not found in the subscription. Please specify an existing key vault"
exit 1
}
# Check certificate doesn't exist
#
$cert = Get-AzKeyVaultCertificate -VaultName $keyVaultName -Name $certSubjectName
if ($cert)
{
Write-Error "Certificate $certSubjectName already exists"
exit 1
}
# Check app registration doesn't exist
#
$application = Get-AzADApplication -DisplayName $applicationName
if ($application)
{
Write-Error "Application $applicationName already exists"
exit 1
}
# Check Arc SQL instance is valid
#
$arcInstance = Get-AzConnectedMachineExtension -SubscriptionId $subscriptionId -MachineName $machineName -ResourceGroupName $resourceGroupName -Name "WindowsAgent.SqlServer"
if (!$arcInstance)
{
Write-Error "Could not find a SQL Server Arc instance in subscription '$subscriptionId' and resource group '$resourceGroupName' with name '$machineName'"
exit 1
}
# Check if admin account exists
#
$adminAccount = Get-AzADUser -UserPrincipalName $adminAccountName
$adminAccountType = 0
if (!$adminAccount)
{
# Check for guest user
#
$adminAccount = Get-AzADUser -Mail $adminAccountName
if (!$adminAccount)
{
$adminAccount = Get-AzADGroup -DisplayName $adminAccountName
if (!$adminAccount)
{
$adminAccount = Get-AzADServicePrincipal -DisplayName $adminAccountName
}
else
{
$adminAccountType = 1
}
}
}
if ($adminAccount)
{
if ($adminAccount.Length -gt 1)
{
Write-Error "Multiple accounts with found with name $adminAccountName"
exit 1
}
$adminAccountSid = $adminAccount.Id
}
else
{
Write-Error "Could not find an account with name $adminAccountName"
exit 1
}
# Create certificate in AKV
#
$Policy = New-AzKeyVaultCertificatePolicy -SecretContentType "application/x-pkcs12" -SubjectName "CN=$certSubjectName" -IssuerName "Self" -ValidityInMonths 12 -ReuseKeyOnRenewal
try
{
$addCertRes = Add-AzKeyVaultCertificate -VaultName $keyVaultName -Name $certSubjectName -CertificatePolicy $Policy -ErrorAction stop
}
catch
{
Write-Error $_
Write-Error "Certificate $certSubjectName could not be created"
exit 1
}
for (($i = 0); $i -lt $NUMRETRIES -and (!$cert -or !$cert.enabled); $i++)
{
$cert = Get-AzKeyVaultCertificate -VaultName $keyVaultName -Name $certSubjectName
if (!$cert -or !$cert.enabled)
{
Start-Sleep -Seconds 5
}
}
if (!$cert)
{
Write-Error "Certificate $certSubjectName could not be created"
exit 1
}
# Allow Arc to access AKV
#
$arcServicePrincipal = Get-AzADServicePrincipal -DisplayName $machineName
if ($arcServicePrincipal -and ![string]::IsNullOrEmpty($arcServicePrincipal.Id))
{
try
{
Set-AzKeyVaultAccessPolicy -VaultName $keyVaultName -ObjectId $arcServicePrincipal.Id -PermissionsToSecrets Get,List -PermissionsToCertificates Get,List
}
catch
{
Write-Error $_
Write-Host "Warning: Could not find the identity of the Azure extension for SQL Server and thus, could not add permissions for the Arc process to read from AKV. Ensure the Arc identity has the required permissions to read from AKV."
}
}
else
{
Write-Host "Warning: Could not find the identity of the Azure extension for SQL Server and thus, could not add permissions for the Arc process to read from AKV. Ensure the Arc identity has the required permissions to read from AKV."
}
# Create an Azure AD application
#
$application = New-AzADApplication -DisplayName $applicationName
if (!$application)
{
Write-Error "Application could not be created"
exit 1
}
# Set perms on app registration
#
Add-AzADAppPermission -ObjectId $application.Id -ApiId 00000003-0000-0000-c000-000000000000 -PermissionId c79f8feb-a9db-4090-85f9-90d820caa0eb # Delegated Application.Read.All
Add-AzADAppPermission -ObjectId $application.Id -ApiId 00000003-0000-0000-c000-000000000000 -PermissionId 0e263e50-5827-48a4-b97c-d940288653c7 # Delegated Directory.AccessAsUser.All
Add-AzADAppPermission -ObjectId $application.Id -ApiId 00000003-0000-0000-c000-000000000000 -PermissionId 7ab1d382-f21e-4acd-a863-ba3e13f7da61 -Type Role # Application Directory.Read.All
Add-AzADAppPermission -ObjectId $application.Id -ApiId 00000003-0000-0000-c000-000000000000 -PermissionId 5f8c59db-677d-491f-a6b8-5f174b11ec1d # Delegated Group.Read.All
Add-AzADAppPermission -ObjectId $application.Id -ApiId 00000003-0000-0000-c000-000000000000 -PermissionId a154be20-db9c-4678-8ab7-66f6cc099a59 # Delegated User.Read.All
# Upload cert to Azure AD
#
try
{
$base64Cert = [System.Convert]::ToBase64String($cert.Certificate.GetRawCertData())
New-AzADAppCredential -ApplicationObject $application -CertValue $base64Cert -EndDate $cert.Certificate.NotAfter -StartDate $cert.Certificate.NotBefore -ErrorAction stop
}
catch
{
Write-Error $_
Write-Error "Failed to add certificate to app registration"
exit 1
}
# Remove the version from the secret ID if present
#
$secretId = $cert.SecretId
if ($secretId -Match "(https:\/\/[^\/]+\/secrets\/[^\/]+)(\/.*){0,1}$") {
if ($Matches[1]) {
$secretId = $Matches[1]
}
}
# Create the settings object to write to the Azure extension for SQL Server
#
$instanceSettings = @{
instanceName = $instanceName
adminLoginName = $adminAccountName
adminLoginSid = $adminAccountSid
azureCertSecretId = $secretId.replace(":443", "")
azureCertUri = $cert.Id.replace(":443", "")
azureKeyVaultResourceUID = $keyVault.ResourceId
managedCertSetting = "CUSTOMER MANAGED CERT"
managedAppSetting = "CUSTOMER MANAGED APP"
appRegistrationName = $application.DisplayName
appRegistrationSid = $application.AppId
tenantId = $tenantId
aadCertSubjectName = $certSubjectName
adminLoginType = $adminAccountType
}
$arcInstance = Get-AzConnectedMachineExtension -SubscriptionId $subscriptionId -MachineName $machineName -ResourceGroupName $resourceGroupName -Name "WindowsAgent.SqlServer"
if ($arcInstance.Setting.AdditionalProperties.AzureAD)
{
$aadSettings = $arcInstance.Setting.AdditionalProperties.AzureAD
$instanceFound = $false
$instanceNameLower = $instanceName.ToLower()
$instanceIndex = 0
for (($i = 0); $i -lt $aadSettings.Length; $i++)
{
if ($aadSettings[$i].instanceName.ToLower() -eq $instanceNameLower)
{
$instanceIndex = $i
$instanceFound = $true
break
}
}
if ($instanceFound)
{
$aadSettings[$instanceIndex] = $instanceSettings
}
else
{
$aadSettings += $instanceSettings
}
$arcInstance.Setting.AdditionalProperties.AzureAD = $aadSettings
}
else
{
$aadSettings = , $instanceSettings
$arcInstance.Setting.AdditionalProperties | Add-Member -Name 'AzureAD' -Value $aadSettings -MemberType NoteProperty
}
Write-Host "Writing Microsoft Entra setting to SQL Server Arc Extension. This may take several minutes..."
# Push settings to Arc
#
try
{
Update-AzConnectedMachineExtension -MachineName $machineName -Name "WindowsAgent.SqlServer" -ResourceGroupName $resourceGroupName -Setting $arcInstance.Setting
}
catch
{
Write-Error $_
Write-Error "Failed to write settings to Arc host"
exit 1
}
Write-Output "Success"
Настройка администратора Microsoft Entra с существующим сертификатом и приложением с помощью PowerShell
Если у вас уже есть сертификат Azure Key Vault и приложение Azure, которое вы хотите использовать для настройки администратора Microsoft Entra, можно использовать следующий сценарий PowerShell:
# Connect statement
Connect-AzAccount
#Input parameters
$subscriptionId="<subscriptionId>"
$tenantId="<tenantId>"
$machineName="<machineName>" # hostname
$instanceName="<instanceName>" # SQL Server is define as `machine_name\instance_name`
$resourceGroupName="<resourceGroupName>"
$keyVaultName="<keyVaultName>"
$certSubjectName="<certSubjectName>" # Your existing certificate name
$applicationName="<applicationName>" # Your existing application name
$adminAccountName="<adminAccountName>"
$adminAccountSid="<adminID>" # Use object ID for the Microsoft Entra user and group, or client ID for the Microsoft Entra application
$adminAccountType= 0 # 0 – for Microsoft Entra user and application, 1 for Microsoft Entra group
$keyVault = Get-AzKeyVault -VaultName $keyVaultName
if (!$keyVault)
{
Write-Error "Supplied key vault was not found in the subscription. Please specify an existing key vault"
exit 1
}
$cert = Get-AzKeyVaultCertificate -VaultName $keyVaultName -Name $certSubjectName
if (!$cert)
{
Write-Error "Supplied certificate $certSubjectName was not found for this key vault. Please specify an existing certificate"
exit 1
}
$secretId = $cert.SecretId
if ($secretId -Match "(https:\/\/[^\/]+\/secrets\/[^\/]+)(\/.*){0,1}$") {
if ($Matches[1]) {
$secretId = $Matches[1]
}
}
$application = Get-AzADApplication -DisplayName $applicationName
if (!$application)
{
Write-Error "Supplied application was not found in the subscription. Please specify an existing application"
exit 1
}
# Create the settings object to write to the Arc extension
#
$instanceSettings = @{
instanceName = $instanceName
adminLoginName = $adminAccountName
adminLoginSid = $adminAccountSid
azureCertSecretId = $secretId.replace(":443", "")
azureCertUri = $cert.Id.replace(":443", "")
azureKeyVaultResourceUID = $keyVault.ResourceId
managedCertSetting = "CUSTOMER MANAGED CERT"
managedAppSetting = "CUSTOMER MANAGED APP"
appRegistrationName = $application.DisplayName
appRegistrationSid = $application.AppId
tenantId = $tenantId
aadCertSubjectName = $certSubjectName
adminLoginType = $adminAccountType
}
$arcInstance = Get-AzConnectedMachineExtension -SubscriptionId $subscriptionId -MachineName $machineName -ResourceGroupName $resourceGroupName -Name "WindowsAgent.SqlServer"
if ($arcInstance.Setting.AdditionalProperties.AzureAD)
{
$aadSettings = $arcInstance.Setting.AdditionalProperties.AzureAD
$instanceFound = $false
$instanceNameLower = $instanceName.ToLower()
$instanceIndex = 0
for (($i = 0); $i -lt $aadSettings.Length; $i++)
{
if ($aadSettings[$i].instanceName.ToLower() -eq $instanceNameLower)
{
$instanceIndex = $i
$instanceFound = $true
break
}
}
if ($instanceFound)
{
$aadSettings[$instanceIndex] = $instanceSettings
}
else
{
$aadSettings += $instanceSettings
}
$arcInstance.Setting.AdditionalProperties.AzureAD = $aadSettings
}
else
{
$aadSettings = , $instanceSettings
$arcInstance.Setting.AdditionalProperties | Add-Member -Name 'AzureAD' -Value $aadSettings -MemberType NoteProperty
}
Write-Host "Writing Microsoft Entra setting to SQL Server Arc Extension. This may take several minutes..."
# Push settings to Arc
#
try
{
Update-AzConnectedMachineExtension -MachineName $machineName -Name "WindowsAgent.SqlServer" -ResourceGroupName $resourceGroupName -Setting $arcInstance.Setting
}
catch
{
Write-Error $_
Write-Error "Failed to write settings to Arc host"
exit 1
}
Write-Output "Success"
Следующий шаблон ARM настраивает администратора Microsoft Entra с помощью существующего сертификата Azure Key Vault и приложения Microsoft Entra.
Для шаблона ARM используются следующие входные параметры:
<machineName> — имя компьютера узла SQL Server
<Location> — расположение группы ресурсов SQL Server — Azure Arc , например West USили Central US
<tenantId>— Идентификатор клиента можно найти, перейдя в портал Azure и перейдя к ресурсу идентификатора Microsoft Entra ID. В области Обзор должен отображаться параметр Идентификатор клиента.
<instanceName> — имя экземпляра SQL Server. Имя экземпляра по умолчанию SQL Server MSSQLSERVER
<certSubjectName> — имя созданного сертификата
<subscriptionId> — идентификатор подписки. Ваш идентификатор подписки можно найти на портале Azure.
<resourceGroupName> — Имя группы ресурсов, содержащее хранилище ключей. Полное значение azureKeyVaultResourceUID можно найти, перейдя в ресурс хранилища ключей, выбрав свойства и скопируйте идентификатор ресурса.
<keyVaultName> — имя хранилища ключей
<certIdentifier>— Идентификатор сертификата Azure Key Vault. Чтобы получить идентификатор сертификата, перейдите к ресурсу хранилища ключей и выберите "Сертификаты" в разделе "Параметры". Выберите текущую версию созданного сертификата и скопируйте значение идентификатора сертификата. Дополнительные сведения см. в разделе "Добавление сертификата в Key Vault"
<certSecret> — Секретный идентификатор сертификата и можно найти в том же меню, что и идентификатор сертификата.
<appID>— Идентификатор приложения (клиента) приложения Microsoft Entra можно найти в меню "Обзор" приложения
<adminAccountName> — учетная запись администратора Microsoft Entra, которую вы хотите задать для SQL Server
<adminID>— Идентификатор объекта пользователя или группы Microsoft Entra или идентификатор приложения (клиента), если вы используете другое приложение в качестве учетной записи администратора Microsoft Entra. Дополнительные сведения см. в руководстве по созданию пользователей Microsoft Entra с помощью приложений Microsoft Entra
<adminType> — Использование 0 для пользователей и приложений Microsoft Entra, а 1 также для групп Microsoft Entra
Используйте инструкции из разделов о пользовательском развертывании на портале Azure и создании собственного шаблона с помощью редактора. Затем необходимо сохранить конфигурацию после того, как вставлен пример.
Примечание.
Для SQL Server на Linux хост-компьютеров замените WindowsAgent.SqlServerLinuxAgent.SqlServer его в скрипте.
Предоставление согласия администратора для приложения
После настройки администратора Microsoft Entra с помощью учетных данных администратора Microsoft Entra можно подключиться к SQL Server. Однако любые дальнейшие действия базы данных, связанные с созданием новых имен входа Microsoft Entra, и пользователи не будут завершать ошибку, пока не будет предоставлено согласие администратора приложению Microsoft Entra.
Примечание.
Чтобы предоставить согласие администратора для приложения, для предоставления согласия учетной записи требуется роль глобального администратора Microsoft Entra ID или администратора привилегированных ролей. Эти роли необходимы для предоставления согласия администратора для приложения, но не требуется настроить администратора Microsoft Entra.
В портал Azure выберите идентификатор Microsoft Entra Регистрация приложений> выберите только что созданное приложение. Приложение должно иметь имя, например <hostname>-<instanceName><uniqueNumber>.
Выберите меню разрешений API.
Выберите Предоставить согласие администратора.
Без предоставления согласия администратора приложению создание имени входа Microsoft Entra или пользователя в SQL Server приведет к следующей ошибке:
Msg 37455, Level 16, State 1, Line 2
Server identity does not have permissions to access MS Graph.
Использование проверки подлинности Microsoft Entra для подключения к SQL Server