SAS 토큰으로 Azure Maps 계정 보호
이 문서에서는 Azure Maps REST API를 호출하는 데 사용할 수 있는 안전하게 저장된 SAS 토큰으로 Azure Maps 계정을 만드는 방법을 설명합니다.
필수 구성 요소
Azure 구독 아직 Azure 계정이 없으면 무료 계정에 등록합니다.
Azure 구독에 대한 소유자 역할 권한입니다. 다음을 수행하려면 소유자 권한이 필요합니다.
- Azure Key Vault에서 Key Vault 만들기
- 사용자가 할당한 관리 ID 만들기
- 관리 ID 역할을 할당합니다.
- Azure Maps 계정을 만듭니다.
리소스를 배포하기 위해 Azure CLI가 설치되었습니다.
예제 시나리오: SAS 토큰 보안 스토리지
SAS 토큰 자격 증명은 토큰이 만료되거나 액세스가 취소될 때까지 자격 증명을 보유한 모든 사람에게 지정된 액세스 수준을 부여합니다. SAS 토큰 인증을 사용하는 애플리케이션은 키를 안전하게 저장해야 합니다.
이 시나리오는 SAS 토큰을 Key Vault에 비밀로 안전하게 저장하고 토큰을 공용 클라이언트에 배포합니다. 애플리케이션 수명 주기 이벤트는 기존 토큰을 사용하는 활성 연결을 중단하지 않고 새 SAS 토큰을 생성할 수 있습니다.
Key Vault 구성에 대한 자세한 내용은 Azure Key Vault 개발자 가이드를 참조하세요.
다음 예제 시나리오에서는 두 가지 ARM(Azure Resource Manager) 템플릿 배포를 사용하여 다음 단계를 수행합니다.
- 키 자격 증명 모음을 생성합니다.
- 사용자가 할당한 관리 ID 만들기
- 사용자 할당 관리 ID에 Azure RBAC(역할 기반 액세스 제어) Azure Maps 데이터 읽기 권한자 역할을 할당합니다.
- CORS(원본 간 리소스 공유) 구성으로 Azure Maps 계정을 만들고 사용자가 할당한 관리 ID를 연결합니다.
- Azure Key Vault에서 SAS 토큰을 만들고 저장합니다.
- 키 자격 증명 모음에서 SAS 토큰 비밀을 검색합니다.
- SAS 토큰을 사용하는 Azure Maps REST API 요청을 만듭니다.
완료하면 Azure CLI를 사용하는 PowerShell에 Azure Maps Search Address (Non-Batch)
REST API 결과가 표시되어야 합니다. Azure 리소스는 Azure Maps 계정에 연결할 수 있는 권한으로 배포됩니다. 최대 속도 제한, 허용 지역, localhost
구성된 CORS 정책 및 Azure RBAC에 대한 제어가 있습니다.
Azure CLI를 사용하여 Azure 리소스 배포
다음 단계에서는 SAS 토큰 인증을 사용하여 Azure Maps 계정을 만들고 구성하는 방법을 설명합니다. 이 예에서 Azure CLI는 PowerShell 인스턴스에서 실행됩니다.
az login
을 사용하여 Azure 구독에 로그인합니다.구독에 대한 Key Vault, 관리 ID 및 Azure Maps 등록
az provider register --namespace Microsoft.KeyVault az provider register --namespace Microsoft.ManagedIdentity az provider register --namespace Microsoft.Maps
Microsoft Entra 개체 ID를 검색합니다.
$id = $(az rest --method GET --url 'https://graph.microsoft.com/v1.0/me?$select=id' --headers 'Content-Type=application/json' --query "id")
다음 콘텐츠로 prereq.azuredeploy.json이라는 템플릿 파일을 만듭니다.
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "location": { "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { "description": "Specifies the location for all the resources." } }, "keyVaultName": { "type": "string", "defaultValue": "[concat('vault', uniqueString(resourceGroup().id))]", "metadata": { "description": "Specifies the name of the key vault." } }, "userAssignedIdentityName": { "type": "string", "defaultValue": "[concat('identity', uniqueString(resourceGroup().id))]", "metadata": { "description": "The name for your managed identity resource." } }, "objectId": { "type": "string", "metadata": { "description": "Specifies the object ID of a user, service principal, or security group in the Azure AD tenant for the vault. The object ID must be unique for the set of access policies. Get it by using Get-AzADUser or Get-AzADServicePrincipal cmdlets." } }, "secretsPermissions": { "type": "array", "defaultValue": [ "list", "get", "set" ], "metadata": { "description": "Specifies the permissions to secrets in the vault. Valid values are: all, get, list, set, delete, backup, restore, recover, and purge." } } }, "resources": [ { "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "name": "[parameters('userAssignedIdentityName')]", "apiVersion": "2018-11-30", "location": "[parameters('location')]" }, { "apiVersion": "2021-04-01-preview", "type": "Microsoft.KeyVault/vaults", "name": "[parameters('keyVaultName')]", "location": "[parameters('location')]", "properties": { "tenantId": "[subscription().tenantId]", "sku": { "name": "Standard", "family": "A" }, "enabledForTemplateDeployment": true, "accessPolicies": [ { "objectId": "[parameters('objectId')]", "tenantId": "[subscription().tenantId]", "permissions": { "secrets": "[parameters('secretsPermissions')]" } } ] } } ], "outputs": { "userIdentityResourceId": { "type": "string", "value": "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentityName'))]" }, "userAssignedIdentityPrincipalId": { "type": "string", "value": "[reference(parameters('userAssignedIdentityName')).principalId]" }, "keyVaultName": { "type": "string", "value": "[parameters('keyVaultName')]" } } }
이전 단계에서 만든 필수 리소스를 배포합니다.
<group-name>
에 고유한 값을 제공합니다. Azure Maps 계정과 동일한location
을 사용해야 합니다.az group create --name <group-name> --location "East US" $outputs = $(az deployment group create --name ExampleDeployment --resource-group <group-name> --template-file "./prereq.azuredeploy.json" --parameters objectId=$id --query "[properties.outputs.keyVaultName.value, properties.outputs.userAssignedIdentityPrincipalId.value, properties.outputs.userIdentityResourceId.value]" --output tsv)
템플릿 파일 azuredeploy.json을 만들어 Azure Maps 계정, 역할 할당 및 SAS 토큰을 프로비저닝합니다.
참고 항목
Azure Maps Gen1 가격 책정 계층 사용 중지
Gen1 가격 책정 계층은 이제 더 이상 사용되지 않으며 26/9/15에 사용 중지됩니다. Gen2 가격 책정 계층은 Gen1(S0 및 S1 모두) 가격 책정 계층을 대체합니다. Azure Maps 계정에 Gen1 가격 책정 계층이 선택된 경우 사용 중지되기 전에 Gen2 가격 책정으로 전환할 수 있습니다. 그렇지 않으면 자동으로 업데이트됩니다. 자세한 내용은 Azure Maps 계정의 가격 책정 계층 관리를 참조하세요.
{ "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "location": { "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { "description": "Specifies the location for all the resources." } }, "keyVaultName": { "type": "string", "metadata": { "description": "Specifies the resourceId of the key vault." } }, "accountName": { "type": "string", "defaultValue": "[concat('map', uniqueString(resourceGroup().id))]", "metadata": { "description": "The name for your Azure Maps account." } }, "userAssignedIdentityResourceId": { "type": "string", "metadata": { "description": "Specifies the resourceId for the user assigned managed identity resource." } }, "userAssignedIdentityPrincipalId": { "type": "string", "metadata": { "description": "Specifies the resourceId for the user assigned managed identity resource." } }, "pricingTier": { "type": "string", "allowedValues": [ "S0", "S1", "G2" ], "defaultValue": "G2", "metadata": { "description": "The pricing tier for the account. Use S0 for small-scale development. Use S1 or G2 for large-scale applications." } }, "kind": { "type": "string", "allowedValues": [ "Gen1", "Gen2" ], "defaultValue": "Gen2", "metadata": { "description": "The pricing tier for the account. Use Gen1 for small-scale development. Use Gen2 for large-scale applications." } }, "guid": { "type": "string", "defaultValue": "[guid(resourceGroup().id)]", "metadata": { "description": "Input string for new GUID associated with assigning built in role types." } }, "startDateTime": { "type": "string", "defaultValue": "[utcNow('u')]", "metadata": { "description": "Current Universal DateTime in ISO 8601 'u' format to use as the start of the SAS token." } }, "duration" : { "type": "string", "defaultValue": "P1Y", "metadata": { "description": "The duration of the SAS token. P1Y is maximum, ISO 8601 format is expected." } }, "maxRatePerSecond": { "type": "int", "defaultValue": 500, "minValue": 1, "maxValue": 500, "metadata": { "description": "The approximate maximum rate per second the SAS token can be used." } }, "signingKey": { "type": "string", "defaultValue": "primaryKey", "allowedValues": [ "primaryKey", "seconaryKey" ], "metadata": { "description": "The specified signing key which will be used to create the SAS token." } }, "allowedOrigins": { "type": "array", "defaultValue": [], "maxLength": 10, "metadata": { "description": "The specified application's web host header origins (example: https://www.azure.com) which the Azure Maps account allows for CORS." } }, "allowedRegions": { "type": "array", "defaultValue": [], "metadata": { "description": "The specified SAS token allowed locations where the token may be used." } } }, "variables": { "accountId": "[resourceId('Microsoft.Maps/accounts', parameters('accountName'))]", "Azure Maps Data Reader": "[subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '423170ca-a8f6-4b0f-8487-9e4eb8f49bfa')]", "sasParameters": { "signingKey": "[parameters('signingKey')]", "principalId": "[parameters('userAssignedIdentityPrincipalId')]", "maxRatePerSecond": "[parameters('maxRatePerSecond')]", "start": "[parameters('startDateTime')]", "expiry": "[dateTimeAdd(parameters('startDateTime'), parameters('duration'))]", "regions": "[parameters('allowedRegions')]" } }, "resources": [ { "name": "[parameters('accountName')]", "type": "Microsoft.Maps/accounts", "apiVersion": "2023-06-01", "location": "[parameters('location')]", "sku": { "name": "[parameters('pricingTier')]" }, "kind": "[parameters('kind')]", "properties": { "cors": { "corsRules": [ { "allowedOrigins": "[parameters('allowedOrigins')]" } ] } }, "identity": { "type": "UserAssigned", "userAssignedIdentities": { "[parameters('userAssignedIdentityResourceId')]": {} } } }, { "apiVersion": "2020-04-01-preview", "name": "[concat(parameters('accountName'), '/Microsoft.Authorization/', parameters('guid'))]", "type": "Microsoft.Maps/accounts/providers/roleAssignments", "dependsOn": [ "[parameters('accountName')]" ], "properties": { "roleDefinitionId": "[variables('Azure Maps Data Reader')]", "principalId": "[parameters('userAssignedIdentityPrincipalId')]", "principalType": "ServicePrincipal" } }, { "apiVersion": "2021-04-01-preview", "type": "Microsoft.KeyVault/vaults/secrets", "name": "[concat(parameters('keyVaultName'), '/', parameters('accountName'))]", "dependsOn": [ "[variables('accountId')]" ], "tags": { "signingKey": "[variables('sasParameters').signingKey]", "start" : "[variables('sasParameters').start]", "expiry" : "[variables('sasParameters').expiry]" }, "properties": { "value": "[listSas(variables('accountId'), '2023-06-01', variables('sasParameters')).accountSasToken]" } } ] }
Key Vault의 ID 매개 변수와 이전 단계에서 만든 관리 ID 리소스를 사용하여 템플릿을 배포합니다.
<group-name>
에 고유한 값을 제공합니다. SAS 토큰을 만들 때allowedRegions
매개 변수를eastus
,westus2
및westcentralus
로 설정합니다. 그런 다음 이 위치를 사용하여us.atlas.microsoft.com
엔드포인트에 HTTP 요청을 할 수 있습니다.Important
Azure 배포 로그에 해당 자격 증명이 표시되지 않도록 SAS 토큰을 키 자격 증명 모음에 저장합니다. SAS 토큰 비밀의
tags
에는 SAS 토큰이 만료되는 시기를 표시하기 위해 시작, 만료 및 서명 키 이름도 포함됩니다.az deployment group create --name ExampleDeployment --resource-group <group-name> --template-file "./azuredeploy.json" --parameters keyVaultName="$($outputs[0])" userAssignedIdentityPrincipalId="$($outputs[1])" userAssignedIdentityResourceId="$($outputs[2])" allowedOrigins="['http://localhost']" allowedRegions="['eastus', 'westus2', 'westcentralus']" maxRatePerSecond="10"
Key Vault에서 단일 SAS 토큰 비밀의 복사본을 찾아 저장합니다.
$secretId = $(az keyvault secret list --vault-name $outputs[0] --query "[? contains(name,'map')].id" --output tsv) $sasToken = $(az keyvault secret show --id "$secretId" --query "value" --output tsv)
Azure Maps 엔드포인트에 요청을 만들어 SAS 토큰을 테스트합니다. 이 예에서는 요청이 미국 지역으로 라우팅되도록
us.atlas.microsoft.com
을 지정합니다. SAS 토큰은 미국 지역 내의 지역을 허용합니다.az rest --method GET --url 'https://us.atlas.microsoft.com/search/address/json?api-version=1.0&query=1 Microsoft Way, Redmond, WA 98052' --headers "Authorization=jwt-sas $($sasToken)" --query "results[].address"
전체 스크립트 예
전체 예를 실행하려면 다음 템플릿 파일이 현재 PowerShell 세션과 동일한 디렉터리에 있어야 합니다.
- prereq.azuredeploy.json을 사용하여 키 자격 증명 모음 및 관리 ID를 만듭니다.
- azuredeploy.json을 사용하여 Azure Maps 계정을 만들고, 역할 할당 및 관리 ID를 구성하고, SAS 토큰을 키 자격 증명 모음에 저장합니다.
az login
az provider register --namespace Microsoft.KeyVault
az provider register --namespace Microsoft.ManagedIdentity
az provider register --namespace Microsoft.Maps
$id = $(az rest --method GET --url 'https://graph.microsoft.com/v1.0/me?$select=id' --headers 'Content-Type=application/json' --query "id")
az group create --name <group-name> --location "East US"
$outputs = $(az deployment group create --name ExampleDeployment --resource-group <group-name> --template-file "./prereq.azuredeploy.json" --parameters objectId=$id --query "[properties.outputs.keyVaultName.value, properties.outputs.userAssignedIdentityPrincipalId.value, properties.outputs.userIdentityResourceId.value]" --output tsv)
az deployment group create --name ExampleDeployment --resource-group <group-name> --template-file "./azuredeploy.json" --parameters keyVaultName="$($outputs[0])" userAssignedIdentityPrincipalId="$($outputs[1])" userAssignedIdentityResourceId="$($outputs[2])" allowedOrigins="['http://localhost']" allowedRegions="['eastus', 'westus2', 'westcentralus']" maxRatePerSecond="10"
$secretId = $(az keyvault secret list --vault-name $outputs[0] --query "[? contains(name,'map')].id" --output tsv)
$sasToken = $(az keyvault secret show --id "$secretId" --query "value" --output tsv)
az rest --method GET --url 'https://us.atlas.microsoft.com/search/address/json?api-version=1.0&query=1 Microsoft Way, Redmond, WA 98052' --headers "Authorization=jwt-sas $($sasToken)" --query "results[].address"
실제 예제
C#, Java 또는 JavaScript와 같은 대부분의 클라이언트에서 Azure Maps API에 대한 요청을 실행할 수 있습니다. bruno 또는 Postman과 같은 API 개발 플랫폼은 선택한 거의 모든 프로그래밍 언어 또는 프레임워크에서 API 요청을 기본 클라이언트 코드 조각으로 변환할 수 있습니다. 프런트 엔드 애플리케이션에서 생성된 코드 조각을 사용할 수 있습니다.
다음 작은 JavaScript 코드 예는 SAS 토큰을 JavaScript Fetch API와 함께 사용하여 Azure Maps 정보를 가져오고 반환하는 방법을 보여 줍니다. 이 예제에서는 검색 주소 가져오기 API 버전 1.0을 사용합니다. <your SAS token>
에 고유한 값을 제공합니다.
이 샘플이 작동하려면 API 호출에 대한 allowedOrigins
와 동일한 원본 내에서 샘플을 실행해야 합니다. 예를 들어 API 호출에서 https://contoso.com
을 allowedOrigins
로 제공하는 경우 JavaScript 스크립트를 호스팅하는 HTML 페이지는 https://contoso.com
이어야 합니다.
async function getData(url = 'https://us.atlas.microsoft.com/search/address/json?api-version=1.0&query=1 Microsoft Way, Redmond, WA 98052') {
const response = await fetch(url, {
method: 'GET',
mode: 'cors',
headers: {
'Content-Type': 'application/json',
'Authorization': 'jwt-sas <your SAS token>',
}
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData('https://us.atlas.microsoft.com/search/address/json?api-version=1.0&query=1 Microsoft Way, Redmond, WA 98052')
.then(data => {
console.log(data); // JSON data parsed by `data.json()` call
});
리소스 정리
Azure 리소스가 더 이상 필요하지 않은 경우 해당 리소스를 삭제합니다.
az group delete --name {group-name}
다음 단계
빠른 시작 ARM 템플릿을 배포하여 SAS 토큰을 사용하는 Azure Maps 계정을 만듭니다.
더 자세한 예시는 다음을 참조하세요.
Azure Maps 계정에 대한 API 사용 현황 메트릭을 확인하는 방법을 알아봅니다.
Microsoft Entra ID를 Azure Maps와 통합하는 방법을 보여 주는 샘플을 살펴봅니다.