또한 Azure Portal에서 자동화된 인증서 만들기 및 애플리케이션 등록을 허용하는 SQL Server용 Microsoft Entra 관리자를 설정하기 위해 업데이트된 기능을 살펴보겠습니다. 이전에는 SQL Server에 대한 Microsoft Entra 인증을 설정 하려면 Azure 인증서 및 애플리케이션 등록을 사용하여 Microsoft Entra 관리자를 수동으로 설정해야 했습니다.
새 API 및 포털 기능을 사용하면 사용자가 Azure 인증서 및 Microsoft Entra 애플리케이션을 별도로 만들지 않고도 SQL Server용 Microsoft Entra 관리자를 설정할 수 있습니다. 탭을 선택하여 자동 인증서 및 애플리케이션 생성을 사용하여 Azure Arc에 연결된 SQL Server에 대한 Microsoft Entra 관리자를 설정하는 방법을 알아봅니다.
Azure Portal을 사용하여 Microsoft Entra 관리자를 설정하고, 동일한 프로세스에서 Azure Key Vault 인증서 및 Microsoft Entra 애플리케이션을 만듭니다. SQL Server에서 Microsoft Entra 인증을 사용하는 데 필요합니다.
Azure Portal을 사용하여 Microsoft Entra 관리자 설정
Azure Portal로 이동하여 SQL Server – Azure Arc를 선택합니다. SQL Server 호스트의 인스턴스를 선택합니다.
SQL Server - Azure Arc 리소스의 상태를 확인하고, 속성 메뉴로 이동하여 연결되어 있는지 확인합니다. 자세한 내용은 Arc 지원 SQL Server 리소스의 유효성 검사를 참조 하세요.
리소스 메뉴에서 설정 아래에서 Microsoft Entra ID 및 Purview를 선택합니다.
관리 설정을 선택하여 Microsoft Entra ID 창을 열고 SQL Server에 관리자 로그인으로 추가될 계정을 선택합니다.
서비스 관리 인증서를 선택합니다.
키 자격 증명 모음 변경을 선택하고 기존 Azure Key Vault 리소스를 선택합니다.
서비스 관리 앱 등록을 선택합니다.
저장을 선택합니다. 그러면 Arc 서버 에이전트에 요청을 보내며, 이 에이전트는 해당 SQL Server 인스턴스에 대한 Microsoft Entra 인증을 구성합니다. 작업을 완료하는 데 몇 분 정도 걸릴 수 있습니다. Microsoft Entra 로그인을 시도하기 전에 저장 프로세스가 확인될 Saved successfully
때까지 기다립니다.
서비스 관리 앱 등록은 다음을 수행합니다.
- 키 자격 증명 모음에 양식
<hostname>-<instanceName><uniqueNumber>
의 이름을 사용하여 인증서를 만듭니다.
- 이름이 같은
<hostname>-<instanceName><uniqueNumber>
Microsoft Entra 애플리케이션을 만들고 해당 애플리케이션에 필요한 권한을 할당합니다. 자세한 내용은 애플리케이션 권한 부여를 참조 하세요.
- Azure Key Vault의 새 인증서를 애플리케이션에 할당합니다.
- 이러한 설정을 Azure Arc에 저장합니다.
참고 항목
Microsoft Entra용으로 만든 인증서는 자동으로 회전되지 않습니다. 고객은 Microsoft Entra 관리자 설정에 대한 자체 인증서 및 애플리케이션을 제공하도록 선택할 수 있습니다. 자세한 내용은 자습서: SQL Server에 대한 Microsoft Entra 인증 설정을 참조 하세요.
아래 Azure CLI 스크립트는 Microsoft Entra 관리자를 설정하고, Azure Key Vault 인증서를 만들고, Microsoft Entra 애플리케이션을 만듭니다. 인증서 및 애플리케이션이 이미 있는 경우 Microsoft Entra 관리자를 설정하기 위한 샘플 스크립트를 제공하는 추가 섹션이 있습니다.
참고 항목
Microsoft Entra 설치를 위해 만든 인증서는 자동으로 회전되지 않습니다.
- Azure CLI 버전 2.37.0 이상이 필요합니다.
- Az.커넥트edMachine 0.5.1 이상이 필요합니다.
모듈을 설치하려면 . Az.ConnectedMachine
를 사용합니다 az extension add --name ConnectedMachine
. 설치된 az version
Azure CLI 버전을 검사 .
다음 입력 매개 변수는 Azure CLI 스크립트에 사용됩니다.
<applicationName>
- 만들 애플리케이션 이름
<certSubjectName>
- 만들 인증서 이름
<keyVaultName>
- 키 자격 증명 모음 이름입니다. 스크립트를 실행하기 전에 이 키 자격 증명 모음을 만들어야 합니다.
<machineName>
- SQL Server 호스트의 컴퓨터 이름
<resourceGroupName>
- SQL Server를 포함하는 리소스 그룹 이름 - Azure Arc 인스턴스
<adminAccountName>
- SQL Server에 대해 설정하려는 Microsoft Entra 관리자 계정
<instanceName>
- SQL Server 명명된 인스턴스에 대한 선택적 매개 변수입니다. 명명된 인스턴스가 있는 경우 이 매개 변수를 사용합니다. 생략하면 기본 이름이 MSSQLSERVER
사용됩니다.
<tenantId>
- 테넌트 ID에 대한 선택적 매개 변수입니다. 테넌트 ID는 Azure Portal로 이동하여 Microsoft Entra ID 리소스로 이동하여 찾을 수 있습니다. 개요 창에테넌트 ID가 표시됩니다. 생략하면 기본 테넌트 ID가 매개 변수로 사용됩니다.
<subscriptionId>
- 구독 ID에 대한 선택적 매개 변수입니다. 구독 ID는 Azure Portal에서 찾을 수 있습니다. 생략하면 기본 구독 ID가 사용됩니다.
아래의 Azure CLI 스크립트를 사용하려면 스크립트를 파일로 .ps1
저장하고 다음 명령을 실행합니다.
./aadAzCliSetup.ps1 -applicationName "<applicationName>" -certSubjectName "<certSubjectName>" -keyVaultName "<keyVaultName>" -machineName "<machineName>" -resourceGroupName "<resourceGroupName>" -adminAccountName "<adminAccountName>" -instanceName "<instanceName>" -tenantId "<tenantId>" -subscriptionId "<subscriptionId>"
Azure CLI 스크립트
참고 항목
Sql Server on Linux 호스트 컴퓨터의 경우 스크립트에서 바꿉 WindowsAgent.SqlServer
LinuxAgent.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
Azure CLI를 사용하여 기존 인증서 및 애플리케이션으로 Microsoft Entra 관리자 설정
기존 Azure Key Vault 인증서와 Microsoft Entra 관리자를 설정하는 데 사용하려는 Azure 애플리케이션이 이미 있는 경우 다음 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 certficate"
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"
아래 PowerShell 스크립트는 Microsoft Entra 관리자를 설정하고, Azure Key Vault 인증서를 만들고, Microsoft Entra 애플리케이션을 만듭니다. 인증서 및 애플리케이션이 이미 있는 경우 Microsoft Entra 관리자를 설정하기 위한 샘플 스크립트를 제공하는 추가 섹션이 있습니다.
참고 항목
Microsoft Entra 설치를 위해 만든 인증서는 자동으로 회전되지 않습니다.
이 자습서에는 다음 모듈이 필요합니다. 최신 버전의 모듈을 설치하거나 아래의 언급된 버전보다 높은 버전을 설치합니다.
- Az.Accounts 3.37.0
- Az.커넥트edMachine 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>
- SQL Server에 대해 설정하려는 Microsoft Entra 관리자 계정
<instanceName>
- SQL Server 명명된 인스턴스에 대한 선택적 매개 변수입니다. 명명된 인스턴스가 있는 경우 이 매개 변수를 사용합니다. 생략하면 기본 이름이 MSSQLSERVER
사용됩니다.
<tenantId>
- 테넌트 ID에 대한 선택적 매개 변수입니다. 테넌트 ID는 Azure Portal로 이동하여 Microsoft Entra ID 리소스로 이동하여 찾을 수 있습니다. 개요 창에테넌트 ID가 표시됩니다. 생략하면 기본 테넌트 ID가 매개 변수로 사용됩니다.
<subscriptionId>
- 구독 ID에 대한 선택적 매개 변수입니다. 구독 ID는 Azure Portal에서 찾을 수 있습니다. 생략하면 기본 구독 ID가 사용됩니다.
아래 PowerShell 스크립트를 사용하려면 스크립트를 파일로 .ps1
저장하고 다음 명령을 실행합니다.
./aadPowerShellsetup.ps1 -applicationName "<applicationName>" -certSubjectName "<certSubjectName>" -keyVaultName "<keyVaultName>" -machineName "<machineName>" -resourceGroupName "<resourceGroupName>" -adminAccountName "<adminAccountName>" -instanceName "<instanceName>" -tenantId "<tenantId>" -subscriptionId "<subscriptionId>"
PowerShell 스크립트
Sql Server on Linux 호스트 컴퓨터의 경우 스크립트에서 바꿉 WindowsAgent.SqlServer
LinuxAgent.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"
PowerShell을 사용하여 기존 인증서 및 애플리케이션으로 Microsoft Entra 관리자 설정
기존 Azure Key Vault 인증서와 Microsoft Entra 관리자를 설정하는 데 사용하려는 Azure 애플리케이션이 이미 있는 경우 다음 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 템플릿은 기존 Azure Key Vault 인증서 및 Microsoft Entra 애플리케이션을 사용하여 Microsoft Entra 관리자를 설정합니다.
ARM 템플릿에 사용되는 입력 매개 변수는 다음과 같습니다.
<machineName>
- SQL Server 호스트의 컴퓨터 이름
<Location>
- SQL Server의 위치 - Azure Arc 리소스 그룹(예: West US
또는 Central US
<tenantId>
- Azure Portal로 이동하여 Microsoft Entra ID 리소스로 이동하여 테넌트 ID를 찾을 수 있습니다. 개요 창에 테넌트 ID가 표시됩니다.
<instanceName>
- SQL Server 인스턴스 이름입니다. SQL Server의 기본 인스턴스 이름은 다음과 같습니다. MSSQLSERVER
<certSubjectName>
- 만든 인증서 이름
<subscriptionId>
- 구독 ID입니다. 구독 ID는 Azure Portal에서 찾을 수 있습니다.
<resourceGroupName>
- 키 자격 증명 모음을 포함하는 리소스 그룹 이름입니다. Key Vault 리소스로 이동하여 속성을 선택하고 리소스 ID를 복사하여 전체 azureKeyVaultResourceUID 값을 찾을 수 있습니다.
<keyVaultName>
- 키 자격 증명 모음 이름
<certIdentifier>
- Azure Key Vault 인증서의 인증서 식별자입니다. 인증서 식별자를 가져오려면 Key Vault 리소스로 이동하고 설정 아래에서 인증서를 선택합니다. 만든 인증서의 현재 버전을 선택하고 인증서 식별자 값을 복사합니다. 자세한 내용은 Key Vault에 인증서 추가를 참조 하세요.
<certSecret>
- 인증서의 비밀 식별자이며 인증서 식별자와 동일한 메뉴에서 찾을 수 있습니다.
<applicationName>
- 만든 Microsoft Entra 애플리케이션의 이름
<appID>
- Microsoft Entra 애플리케이션의 애플리케이션(클라이언트) ID는 애플리케이션의 개요 메뉴에서 찾을 수 있습니다.
<adminAccountName>
- SQL Server에 대해 설정하려는 Microsoft Entra 관리자 계정
<adminID>
- 다른 애플리케이션을 Microsoft Entra 관리자 계정으로 사용하는 경우 Microsoft Entra 사용자 또는 그룹의 개체 ID 또는 애플리케이션의 애플리케이션(클라이언트) ID입니다. 자세한 내용은 자습서: Microsoft Entra 애플리케이션을 사용하여 Microsoft Entra 사용자 만들기를 참조 하세요.
<adminType>
- Microsoft Entra 사용자 및 애플리케이션 및 1
Microsoft Entra 그룹에 사용 0
Azure Portal의 사용자 지정 배포를 사용하고 편집기에서 사용자 고유의 템플릿을 빌드합니다. 다음으로, 예제에 붙여넣은 후에 구성을 저장합니다.
참고 항목
Sql Server on Linux 호스트 컴퓨터의 경우 스크립트에서 바꿉 WindowsAgent.SqlServer
LinuxAgent.SqlServer
니다.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"resources": [
{
"type": "Microsoft.HybridCompute/machines/extensions",
"apiVersion": "2022-03-10",
"name": "<machineName>/WindowsAgent.SqlServer",
"location": "<Location>",
"properties": {
"publisher": "Microsoft.AzureData",
"type": "WindowsAgent.SqlServer",
"settings": {
"AzureAD": [
{
"tenantId": "<tenantId>",
"instanceName": "<instanceName>",
"managedCertSetting": "CUSTOMER MANAGED CERT",
"aadCertSubjectName": "<certSubjectName>",
"azureKeyVaultResourceUID": "/subscriptions/<subscriptionId>/resourceGroups/<resourceGroupName>/providers/Microsoft.KeyVault/vaults/<keyVaultName>",
"azureCertUri": "<certIdentifier>",
"azureCertSecretId": "<certSecret>",
"managedAppSetting": "CUSTOMER MANAGED APP",
"appRegistrationName": "<applicationName>",
"appRegistrationSid": "<appID>",
"adminLoginName": "<adminAccountName>",
"adminLoginSid" : "<adminID>",
"adminLoginType": 0
}
]
}
}
}
]
}
Microsoft Entra 관리자가 설정되면 Microsoft Entra 관리자 자격 증명을 사용하여 SQL Server에 연결할 수 있습니다. 그러나 새 Microsoft Entra 로그인 및 사용자 만들기와 관련된 추가 데이터베이스 활동은 관리자 동의가 Microsoft Entra 애플리케이션에 부여될 때까지 실패합니다.
애플리케이션에 관리자 동의를 부여하지 않으면 SQL Server에서 Microsoft Entra 로그인 또는 사용자를 만들면 다음 오류가 발생합니다.
이제 Azure Arc에 연결된 SQL Server에 대해 Microsoft Entra 인증이 설정되었습니다. 자습서: Microsoft Entra 인증을 사용하여 SQL Server에 연결하도록 SQL Server에 대한 Microsoft Entra 인증 설정 문서에서 Microsoft Entra 관리자를 설정한 후 섹션을 따릅니다.