Udostępnij za pośrednictwem


Zabezpieczanie konta usługi Azure Maps przy użyciu tokenu SAS

W tym artykule opisano sposób tworzenia konta usługi Azure Maps z bezpiecznym przechowywanym tokenem SAS, którego można użyć do wywoływania interfejsu API REST usługi Azure Maps.

Wymagania wstępne

  • Subskrypcja platformy Azure. Jeśli nie masz jeszcze konta platformy Azure, utwórz bezpłatne konto.

  • Uprawnienie roli właściciela w subskrypcji platformy Azure. Potrzebujesz uprawnień właściciela do:

    • Tworzenie magazynu kluczy w usłudze Azure Key Vault.
    • Utwórz tożsamość zarządzaną przypisaną przez użytkownika.
    • Przypisywanie tożsamości zarządzanej roli.
    • Utwórz konto usługi Azure Maps.
  • Interfejs wiersza polecenia platformy Azure zainstalowany w celu wdrożenia zasobów.

Przykładowy scenariusz: bezpieczny magazyn tokenu SAS

Poświadczenie tokenu sygnatury dostępu współdzielonego przyznaje poziom dostępu określony każdemu, kto go przechowuje, dopóki token nie wygaśnie lub nie zostanie odwołany. Aplikacje korzystające z uwierzytelniania tokenu SAS powinny bezpiecznie przechowywać klucze.

Ten scenariusz bezpiecznie przechowuje token SAS jako wpis tajny w usłudze Key Vault i dystrybuuje token do klienta publicznego. Zdarzenia cyklu życia aplikacji mogą generować nowe tokeny SAS bez przerywania aktywnych połączeń korzystających z istniejących tokenów.

Aby uzyskać więcej informacji na temat konfigurowania usługi Key Vault, zobacz przewodnik dewelopera usługi Azure Key Vault.

Poniższy przykładowy scenariusz używa dwóch wdrożeń szablonów usługi Azure Resource Manager (ARM) w celu wykonania następujących kroków:

  1. Tworzenie magazynu kluczy.
  2. Utwórz tożsamość zarządzaną przypisaną przez użytkownika.
  3. Przypisz rolę Czytelnik danych usługi Azure Maps na podstawie ról (RBAC) do tożsamości zarządzanej przypisanej przez użytkownika.
  4. Utwórz konto usługi Azure Maps z konfiguracją współużytkowania zasobów między źródłami (CORS) i dołącz tożsamość zarządzaną przypisaną przez użytkownika.
  5. Tworzenie i zapisywanie tokenu SAS w magazynie kluczy platformy Azure.
  6. Pobierz wpis tajny tokenu SAS z magazynu kluczy.
  7. Utwórz żądanie interfejsu API REST usługi Azure Maps, które używa tokenu SAS.

Po zakończeniu wyniki interfejsu API REST usługi Azure Maps Search Address (Non-Batch) powinny być widoczne w programie PowerShell za pomocą interfejsu wiersza polecenia platformy Azure. Zasoby platformy Azure są wdrażane z uprawnieniami w celu nawiązania połączenia z kontem usługi Azure Maps. Istnieją kontrolki dotyczące maksymalnego limitu szybkości, dozwolonych regionów, localhost skonfigurowanych zasad CORS i kontroli dostępu opartej na rolach platformy Azure.

Wdrażanie zasobów platformy Azure za pomocą interfejsu wiersza polecenia platformy Azure

W poniższych krokach opisano sposób tworzenia i konfigurowania konta usługi Azure Maps przy użyciu uwierzytelniania tokenu SAS. W tym przykładzie interfejs wiersza polecenia platformy Azure jest uruchamiany w wystąpieniu programu PowerShell.

  1. Zaloguj się do subskrypcji platformy Azure przy użyciu polecenia az login.

  2. Zarejestruj usługę Key Vault, tożsamości zarządzane i usługę Azure Maps dla subskrypcji.

    az provider register --namespace Microsoft.KeyVault
    az provider register --namespace Microsoft.ManagedIdentity
    az provider register --namespace Microsoft.Maps
    
  3. Pobierz identyfikator obiektu Entra firmy Microsoft.

    $id = $(az rest --method GET --url 'https://graph.microsoft.com/v1.0/me?$select=id' --headers 'Content-Type=application/json' --query "id")
    
  4. Utwórz plik szablonu o nazwie prereq.azuredeploy.json z następującą zawartością:

    {
        "$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')]"
            }
        }
    }
    
    
  5. Wdróż zasoby wymagań wstępnych utworzonych w poprzednim kroku. Podaj własną wartość dla elementu <group-name>. Upewnij się, że używasz tego samego location konta usługi Azure Maps.

    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)
    
  6. Utwórz plik szablonu azuredeploy.json , aby aprowizować konto usługi Azure Maps, przypisanie roli i token SAS.

    Uwaga

    Wycofanie warstwy cenowej usługi Azure Maps Gen1

    Warstwa cenowa Gen1 jest teraz przestarzała i zostanie wycofana w dniu 15.09.26. Warstwa cenowa Gen2 zastępuje warstwę cenową Gen1 (zarówno S0, jak i S1). Jeśli konto usługi Azure Maps ma wybraną warstwę cenową Gen1, możesz przełączyć się na cennik gen2 przed wycofaniem. W przeciwnym razie zostanie on automatycznie zaktualizowany. Aby uzyskać więcej informacji, zobacz Zarządzanie warstwą cenową konta usługi 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",
                    "secondaryKey"
                ],
                "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]"
                }
            }
        ]
    }
    
  7. Wdróż szablon przy użyciu parametrów identyfikatora z usługi Key Vault i zasobów tożsamości zarządzanej utworzonych w poprzednim kroku. Podaj własną wartość dla elementu <group-name>. Podczas tworzenia tokenu SAS należy ustawić allowedRegions parametr na eastus, westus2i westcentralus. Następnie możesz użyć tych lokalizacji, aby wysyłać żądania HTTP do punktu końcowego us.atlas.microsoft.com .

    Ważne

    Token SAS można zapisać w magazynie kluczy, aby zapobiec wyświetlaniu poświadczeń w dziennikach wdrażania platformy Azure. Klucz tajny tokenu sygnatury dostępu współdzielonego tags zawiera również nazwę początkową, wygasaną i podpisywania klucza, aby pokazać, kiedy token SAS wygaśnie.

     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"
    
  8. Zlokalizuj i zapisz kopię pojedynczego wpisu tajnego tokenu SAS z usługi Key Vault.

    $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)
    
  9. Przetestuj token SAS, wysyłając żądanie do punktu końcowego usługi Azure Maps. W tym przykładzie określono parametr , us.atlas.microsoft.com aby upewnić się, że trasy żądania do lokalizacji geograficznej USA. Token SYGNATURy dostępu współdzielonego umożliwia regionom w lokalizacji geograficznej USA.

    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"
    

Kompletny przykład skryptu

Aby uruchomić kompletny przykład, następujące pliki szablonu muszą znajdować się w tym samym katalogu co bieżąca sesja programu PowerShell:

  • prereq.azuredeploy.json utworzyć magazyn kluczy i tożsamość zarządzaną.
  • azuredeploy.json utworzyć konto usługi Azure Maps, skonfigurować przypisanie roli i tożsamość zarządzaną oraz przechowywać token SAS w magazynie kluczy.
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"

Przykład rzeczywisty

Żądania można uruchamiać do interfejsów API usługi Azure Maps z większości klientów, takich jak C#, Java lub JavaScript. Platformy programistyczne interfejsu API, takie jak bruno lub Postman , mogą konwertować żądanie interfejsu API na podstawowy fragment kodu klienta w niemal dowolnym wybranym języku programowania lub strukturze. W aplikacjach frontonu możesz użyć wygenerowanych fragmentów kodu.

Poniższy mały przykładowy kod JavaScript pokazuje, jak można użyć tokenu SAS z interfejsem API pobierania języka JavaScript w celu pobrania i zwrócenia informacji usługi Azure Maps. W przykładzie użyto interfejsu API pobierania adresu wyszukiwania w wersji 1.0. Podaj własną wartość dla elementu <your SAS token>.

Aby ten przykład działał, upewnij się, że jest uruchamiany z poziomu tego samego źródła co allowedOrigins wywołanie interfejsu API. Jeśli na przykład zostanie podane https://contoso.com jako allowedOrigins w wywołaniu interfejsu API, strona HTML, która hostuje skrypt JavaScript, powinna mieć wartość 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
  });

Czyszczenie zasobów

Gdy zasoby platformy Azure nie są już potrzebne, możesz je usunąć:

az group delete --name {group-name}

Następne kroki

Wdróż szablon usługi ARM z przewodnikiem Szybki start, aby utworzyć konto usługi Azure Maps korzystające z tokenu SAS:

Aby uzyskać bardziej szczegółowe przykłady, zobacz:

Znajdź metryki użycia interfejsu API dla konta usługi Azure Maps:

Zapoznaj się z przykładami pokazującymi, jak zintegrować identyfikator entra firmy Microsoft z usługą Azure Maps: