Questo articolo descrive come configurare l'amministratore di Microsoft Entra per consentire l'autenticazione con Microsoft Entra ID (in precedenza Azure Active Directory) per SQL Server usando il portale di Azure e le API, ad esempio:
Anche se Microsoft Entra ID è il nuovo nome per Azure Active Directory (Azure AD), per evitare l'interruzione degli ambienti esistenti, la denominazione Azure AD è tuttora mantenuta in alcuni elementi hardcoded, ad esempio campi dell'interfaccia utente, provider di connessioni, codici errore e cmdlet. In questo articolo i due nomi sono intercambiabili.
Prerequisiti
SQL Server 2022 (16.x) o versione successiva è installato.
Preparazione prima della configurazione di un amministratore di Microsoft Entra
Le autorizzazioni seguenti sono necessarie per configurare un amministratore di Microsoft Entra nelle risorse di SQL Server - Azure Arc e Key Vault.
Configurare le autorizzazioni per Azure Arc
Segui la guida per assicurarti che SQL Server sia connesso ad Azure Arc. L'utente che configura l'amministratore di Microsoft Entra per la risorsa SQL Server - Azure Arc deve avere il ruolo Collaboratore per il server.
Seleziona SQL Server - Azure Arc e seleziona l'istanza per l'host SQL Server.
Seleziona Controllo di accesso (IAM).
Seleziona Aggiungi>Aggiungi assegnazione di ruolo per aggiungere il ruolo Collaboratore all'utente che configura l'amministratore di Microsoft Entra.
Configurare le autorizzazioni per Azure Key Vault
Se non hai un account Azure Key Vault, crealo. L'utente che configura l'amministratore di Microsoft Entra deve avere il ruolo di Collaboratore in Azure Key Vault. Per aggiungere un ruolo a un utente in Azure Key Vault:
Per confermare, vai alla pagina della risorsa e seleziona Visualizzazione JSON in alto a destra nella casella Essentials nella pagina Panoramica. In Identità sarà disponibile il principalId.
Seleziona Crea.
Devi selezionare Crea per assicurarti che vengano applicate le autorizzazioni. Per assicurarti che le autorizzazioni siano state archiviate, aggiorna la finestra del browser e verifica che la riga per l'istanza di Azure Arc sia ancora presente.
Impostare i criteri di accesso per gli utenti di Microsoft Entra
Nel portale di Azure, accedi all’istanza di Azure Key Vault e seleziona Criteri di accesso.
Seleziona Aggiungi criteri di accesso.
Per Autorizzazioni chiave, seleziona Get, List e Create.
Per Autorizzazioni segrete, seleziona Get, List e Set.
Per Autorizzazioni certificato, seleziona Get, List e Create.
Per Seleziona entità, aggiungi l'utente Microsoft Entra che vuoi usare per connetterti a SQL Server.
Seleziona Aggiungi e quindi Salva.
Configurazione dell'amministratore di Microsoft Entra per SQL Server
Le nuove API e le funzionalità del portale consentono agli utenti di configurare un amministratore di Microsoft Entra per SQL Server senza dover creare separatamente un certificato di Azure e un'applicazione Microsoft Entra. Seleziona una scheda per informazioni su come configurare un amministratore di Microsoft Entra per SQL Server connesso ad Azure Arc con la creazione automatica di certificati e applicazioni.
Usa il portale di Azure per configurare un amministratore di Microsoft Entra, creare un certificato di Azure Key Vault e un'applicazione Microsoft Entra nello stesso processo. Questa operazione è necessaria per usare l'autenticazione di Microsoft Entra con SQL Server.
Seleziona Microsoft Entra ID e Purview in Impostazioni dal menu della risorsa.
Seleziona Imposta amministratore per aprire il riquadro Microsoft Entra ID e scegli un account che verrà aggiunto come account di accesso amministratore a SQL Server.
Seleziona Certiificato gestito dal servizio.
Seleziona Cambia insieme di credenziali delle chiavi e seleziona la risorsa Azure Key Vault esistente.
Seleziona Registrazione app gestita dal servizio.
Seleziona Salva. In questo modo viene inviata una richiesta all'agente server Arc, che configura l'autenticazione di Microsoft Entra per l'istanza di SQL Server. Il completamento dell'operazione può richiedere alcuni minuti; attendi fino a quando il processo di salvataggio non viene confermato con Saved successfully prima di tentare un accesso a Microsoft Entra.
La registrazione dell'app gestita dal servizio esegue le operazioni seguenti:
Crea un certificato nell'insieme di credenziali delle chiavi con un nome nel formato <hostname>-<instanceName><uniqueNumber>.
Crea un'applicazione Microsoft Entra con un nome come <hostname>-<instanceName><uniqueNumber> e assegna le autorizzazioni necessarie a tale applicazione. Per altre informazioni, vedi Concedere le autorizzazioni delle applicazioni
Assegna il nuovo certificato in Azure Key Vault all'applicazione.
Salva queste impostazioni in Azure Arc.
Nota
I certificati creati per Microsoft Entra non vengono ruotati automaticamente. I clienti possono scegliere di fornire il proprio certificato e la propria applicazione per la configurazione dell'amministratore di Microsoft Entra. Per ulteriori informazioni, vedi Esercitazione: Configurare l'autenticazione di Microsoft Entra per SQL Server.
Az.ConnectedMachine 0.5.1 o versione successiva è obbligatorio
Per installare il modulo Az.ConnectedMachine usa az extension add --name ConnectedMachine. Per verificare quale versione dell'interfaccia della riga di comando di Azure è installata, utilizza az version.
Per lo script dell'interfaccia della riga di comando di Azure vengono usati i parametri di input seguenti:
<applicationName> - Nome dell’applicazione che verrà creata
<certSubjectName> - Nome del certificato che verrà creato
<keyVaultName> - Nome dell’insieme di credenziali delle chiavi. Questo insieme di credenziali delle chiavi deve essere creato prima di eseguire lo script
<machineName> - Nome del computer dell'host di SQL Server
<resourceGroupName> - Nome del gruppo di risorse che contiene l’istanza di SQL Server - Azure Arc
<adminAccountName> - L’account amministratore di Microsoft Entra che vuoi configurare per SQL Server
<instanceName> - Parametro facoltativo per le istanze denominate di SQL Server. Utilizza questo parametro quando disponi di un'istanza denominata. Se omesso, viene utilizzato il nome predefinito di MSSQLSERVER
<tenantId> - Parametro facoltativo per l'ID tenant. L'ID tenant è disponibile aprendo il portale di Azure e andando alla risorsa Microsoft Entra ID. Nel riquadro Panoramica dovrebbe essere visualizzato il valore di ID tenant. Se omesso, l'ID tenant predefinito viene usato come parametro
<subscriptionId> - Parametro facoltativo per l'ID sottoscrizione. L'ID sottoscrizione è disponibile nel portale di Azure. Se omesso, viene usato l'ID sottoscrizione predefinito
Per usare lo script dell'interfaccia della riga di comando di Azure seguente, salva lo script come file .ps1 ed esegui questo comando:
Script dell'interfaccia della riga di comando di Azure
Nota
Per i computer host SQL Server in Linux, sostituisci WindowsAgent.SqlServer con LinuxAgent.SqlServer nello script.
# 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"
Il completamento dell’esecuzione dello script può richiedere alcuni minuti. Al termine del processo, verrà visualizzato un messaggio simile al seguente:
Name Location ProvisioningState
---- -------- -----------------
WindowsAgent.SqlServer westus2 Succeeded
Success
Configurazione di un amministratore di Microsoft Entra con un certificato e un'applicazione esistenti usando l'interfaccia della riga di comando di Azure
Se disponi già di un certificato di Azure Key Vault e di un'applicazione Azure che vuoi usare per configurare un amministratore di Microsoft Entra, puoi usare lo script dell'interfaccia della riga di comando seguente:
# 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"
I certificati creati per la configurazione di Microsoft Entra non vengono ruotati automaticamente.
Per questa esercitazione sono necessari i moduli seguenti. Installa le versioni più recenti dei moduli o versioni successive della versione riportata di seguito:
Az.Accounts 3.37.0
Az.ConnectedMachine 0.5.0
Az.KeyVault 4.5.0
Az.Resources 6.0.0
Per lo script PowerShell vengono usati i parametri di input seguenti:
<applicationName> - Nome dell’applicazione che verrà creata
<certSubjectName> - Nome del certificato che verrà creato
<keyVaultName> - Nome dell’insieme di credenziali delle chiavi. Questo insieme di credenziali delle chiavi deve essere creato prima di eseguire lo script
<machineName> - Nome del computer dell'host di SQL Server
<resourceGroupName> - Nome del gruppo di risorse che contiene l’istanza di SQL Server - Azure Arc
<adminAccountName> - L’account amministratore di Microsoft Entra che vuoi configurare per SQL Server
<instanceName> - Parametro facoltativo per le istanze denominate di SQL Server. Utilizza questo parametro quando disponi di un'istanza denominata. Se omesso, viene utilizzato il nome predefinito di MSSQLSERVER
<tenantId> - Parametro facoltativo per l'ID tenant. L'ID tenant è disponibile aprendo il portale di Azure e andando alla risorsa Microsoft Entra ID. Nel riquadro Panoramica dovrebbe essere visualizzato il valore di ID tenant. Se omesso, l'ID tenant predefinito viene usato come parametro
<subscriptionId> - Parametro facoltativo per l'ID sottoscrizione. L'ID sottoscrizione è disponibile nel portale di Azure. Se omesso, viene usato l'ID sottoscrizione predefinito
Per usare lo script di PowerShell seguente, salva lo script come file .ps1 ed esegui il comando seguente:
Per i computer host SQL Server in Linux, sostituisci WindowsAgent.SqlServer con LinuxAgent.SqlServer nello 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
)
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"
Configurazione di un amministratore di Microsoft Entra con un certificato e un'applicazione esistenti usando PowerShell
Se disponi già di un certificato di Azure Key Vault e di un'applicazione Azure che vuoi utilizzare per configurare un amministratore di Microsoft Entra, puoi utilizzare lo script di PowerShell seguente:
# 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"
Il modello di ARM seguente configura un amministratore di Microsoft Entra usando un certificato di Azure Key Vault esistente e un'applicazione Microsoft Entra.
Per il modello di ARM vengono usati i parametri di input seguenti:
<machineName> - Nome del computer dell'host di SQL Server
<Location> - Posizione della risorsa SQL Server - Azure Arc, ad esempio West US o Central US
<tenantId> - L'ID tenant è disponibile aprendo il portale di Azure e andando alla risorsa Microsoft Entra ID. Nel riquadro Panoramica dovrebbe essere visualizzato l’ID tenant
<instanceName> - Nome dell'istanza di SQL Server. Il nome dell'istanza predefinita di SQL Server è MSSQLSERVER
<certSubjectName> - Nome del certificato creato
<subscriptionId> - ID sottoscrizione. L'ID sottoscrizione è disponibile nel portale di Azure
<resourceGroupName> - Nome del gruppo di risorse contenente l'insieme di credenziali delle chiavi. Il valore azureKeyVaultResourceUID completo è disponibile andando alla risorsa dell’insieme di credenziali delle chiavi, selezionando Proprietà e copiando l’ID risorsa
<keyVaultName> - Nome dell’insieme di credenziali delle chiavi
<certIdentifier> - L’identificatore del certificato del certificato di Azure Key Vault. Per ottenere l’identificatore del certificato, vai alla risorsa dell’insieme di credenziali delle chiavi e seleziona Certificati in Impostazioni. Seleziona la versione corrente del certificato creato e copia il valore dell’identificatore del certificato. Per ulteriori informazioni, vedi Aggiungere un certificato all’insieme di credenziali delle chiavi
<certSecret> - L’Identificatore segreto del certificato, disponibile nello stesso menu dell'identificatore del certificato
Concedere il consenso amministratore all'applicazione
Dopo aver configurato l'amministratore di Microsoft Entra, l'uso delle credenziali di amministratore di Microsoft Entra ti consente di connetterti a SQL Server. Tuttavia, eventuali ulteriori attività di database che coinvolgono la creazione di nuovi account di accesso e utenti di Microsoft Entra avranno esito negativo fino a quando non viene concesso il consenso amministratore all'applicazione Microsoft Entra.
Nota
Per concedere il consenso amministratore per l'applicazione, l'account che concede il consenso richiede un ruolo di amministratore globale o amministratore con ruolo con privilegi di Microsoft Entra ID. Questi ruoli sono necessari per concedere il consenso amministratore per l'applicazione, ma non sono necessari per configurare l'amministratore di Microsoft Entra.
Nel portale di Azure, seleziona Microsoft Entra ID>Registrazioni app, seleziona l’applicazione appena creata. L'applicazione deve avere un nome come <hostname>-<instanceName><uniqueNumber>.
Seleziona il menu Autorizzazioni API.
Seleziona Concedi consenso amministratore.
Se non si concede il consenso amministratore all'applicazione, la creazione di un account di accesso o di un utente di Microsoft Entra in SQL Server genererà l'errore seguente:
Msg 37455, Level 16, State 1, Line 2
Server identity does not have permissions to access MS Graph.
Uso dell’autenticazione di Microsoft Entra per connettersi a SQL Server
L'autenticazione di Microsoft Entra è ora configurata per SQL Server connesso ad Azure Arc. Segui le sezioni dopo aver configurato l'amministratore di Microsoft Entra nell'articolo Esercitazione: Configurare l'autenticazione di Microsoft Entra per SQL Server per connetterti a SQL Server usando l'autenticazione di Microsoft Entra.