Sichern eines Azure Maps-Kontos mit einem SAS-Token

In diesem Artikel wird beschrieben, wie Sie ein Azure Maps-Konto mit einem sicher gespeicherten SAS-Token erstellen, das Sie zum Aufrufen der Azure Maps-REST-API verwenden können.

Voraussetzungen

  • Ein Azure-Abonnement. Falls Sie noch kein Azure-Konto haben, registrieren Sie sich für ein kostenloses.

  • Rollenberechtigung Besitzer für das Azure-Abonnement. Sie benötigen die Berechtigungen Besitzer für folgende Aufgaben:

    • Erstellen Sie einen Schlüsseltresor in Azure Key Vault.
    • Erstellen Sie eine benutzerseitig zugewiesene verwaltete Identität.
    • Weisen Sie die verwaltete Identität einer Rolle zu.
    • Erstellen Sie ein Azure Maps-Konto.
  • Installierte Azure CLI zum Bereitstellen der Ressourcen.

Beispielszenario: Sicherer SAS-Tokenspeicher

Anmeldeinformationen für ein SAS-Token gewähren die angegebene Zugriffsebene jeder Person, die sie besitzt, bis zum Ablauf des Tokens oder zum Widerruf des Zugriffs. Anwendungen, die die SAS-Tokenauthentifizierung nutzen, sollten die Schlüssel sicher speichern.

In diesem Szenario wird ein SAS-Token im Schlüsseltresor als Geheimnis sicher gespeichert und in einen öffentlichen Client verteilt. Ereignisse im Lebenszyklus einer Anwendung können neue SAS-Token generieren, ohne aktive Verbindungen zu unterbrechen, die vorhandene Token nutzen.

Weitere Informationen zum Konfigurieren von Key Vault finden Sie im Leitfaden für Azure Key Vault-Entwickler.

Im folgenden Beispielszenario werden zwei Azure Resource Manager (ARM)-Vorlagenbereitstellungen verwendet, um die folgenden Schritte auszuführen:

  1. Erstellen eines Schlüsseltresors
  2. Erstellen Sie eine benutzerseitig zugewiesene verwaltete Identität.
  3. Weisen Sie die Rolle Leseberechtigter für Azure Maps-Daten der rollenbasierten Zugriffssteuerung (Role-Based Access Control, RBAC) in Azure der benutzerseitig zugewiesenen verwalteten Identität zu.
  4. Erstellen Sie ein Azure Maps-Konto mit einer CORS-Konfiguration (Cross Origin Resource Sharing), und fügen Sie die benutzerseitig zugewiesene verwaltete Identität an.
  5. Erstellen Sie ein SAS-Token, und speichern Sie es im Azure-Schlüsseltresor.
  6. Rufen Sie das SAS-Tokengeheimnis aus dem Schlüsseltresor ab.
  7. Erstellen Sie eine Azure Maps-REST-API-Anforderung, die das SAS-Token verwendet.

Wenn Sie damit fertig sind, sollten die Ergebnisse Search Address (Non-Batch) der Azure Maps-REST-API in PowerShell mit Azure CLI angezeigt werden. Die Azure-Ressourcen werden mit Berechtigungen zum Herstellen einer Verbindung mit dem Azure Maps-Konto bereitgestellt. Es gibt Steuerelemente für maximale Ratenbegrenzung, zulässige Regionen, konfigurierte CORS-Richtlinie localhost und Azure RBAC.

Azure-Ressourcenbereitstellung mit der Azure CLI

In den folgenden Schritten wird beschrieben, wie Sie ein Azure Maps-Konto mit SAS-Tokenauthentifizierung erstellen und konfigurieren. In diesem Beispiel wird Azure CLI in einer PowerShell-Instanz ausgeführt.

  1. Melden Sie sich bei Ihrem Azure-Abonnement mit az login an.

  2. Registrieren Sie Azure Key Vault, verwaltete Identitäten und Azure Maps für Ihr Abonnement.

    az provider register --namespace Microsoft.KeyVault
    az provider register --namespace Microsoft.ManagedIdentity
    az provider register --namespace Microsoft.Maps
    
  3. Rufen Sie Ihre Microsoft Entra-Objekt-ID ab.

    $id = $(az rest --method GET --url 'https://graph.microsoft.com/v1.0/me?$select=id' --headers 'Content-Type=application/json' --query "id")
    
  4. Erstellen Sie eine Vorlagendatei namens prereq.azuredeploy.json mit folgendem Inhalt:

    {
        "$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. Stellen Sie die erforderlichen Ressourcen bereit, die Sie im vorhergehenden Schritt erstellt haben. Geben Sie Ihren eigenen Wert für <group-name> an. Stellen Sie sicher, dass Sie denselben Speicherort (location) wie das Azure Maps-Konto verwenden.

    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. Erstellen Sie die Vorlagendatei azuredeploy.json zur Bereitstellung des Azure Maps-Kontos, der Rollenzuweisung und des SAS-Tokens.

    Hinweis

    Einstellung des Azure Maps-Tarifs „Gen1”

    Der Tarif Gen1 ist jetzt veraltet und wird am 15.09.2026 eingestellt. Der Tarif Gen2 ersetzt den Tarif Gen1 (S0 und S1). Wenn für Ihr Azure Maps Konto der Tarif Gen1 ausgewählt ist, können Sie vor der Einstellung zum Tarif Gen2 wechseln, andernfalls erfolgt zu diesem Zeitpunkt eine automatische Umstellung. Weitere Informationen finden Sie unter Verwalten des Tarifs Ihres Azure Maps-Kontos.

    {
        "$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]"
                }
            }
        ]
    }
    
  7. Stellen Sie die Vorlage mit den ID-Parametern aus Key Vault und den Ressourcen für verwaltete Identitäten bereit, die Sie im vorhergehenden Schritt erstellt haben. Geben Sie Ihren eigenen Wert für <group-name> an. Beim Erstellen des SAS-Tokens legen Sie den Parameter allowedRegions auf eastus, westus2 und westcentralus fest. Sie können diese Standorte nutzen, um HTTP-Anforderungen an den Endpunkt us.atlas.microsoft.com zu senden.

    Wichtig

    Sie speichern das SAS-Token im Schlüsseltresor, um zu verhindern, dass seine Anmeldeinformationen in den Azure-Bereitstellungsprotokollen angezeigt werden. Die Tags (tags) des SAS-Tokengeheimnisses enthalten außerdem den Beginn, den Ablauf und den Namen des Signaturschlüssels, um zu zeigen, wann das SAS-Token abläuft.

     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. Suchen Sie das einzelne SAS-Tokengeheimnis aus Azure Key Vault, und speichern Sie eine Kopie davon.

    $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. Testen Sie das SAS-Token, indem Sie eine Anforderung an einen Azure Maps-Endpunkt senden. In diesem Beispiel wird der Wert us.atlas.microsoft.com angegeben, um sicherzustellen, dass Ihre Anforderung an die US-Geografie weitergeleitet wird. Ihr SAS-Token lässt Regionen innerhalb der US-Geografie zu.

    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"
    

Vollständiges Beispiel für ein Skript

Zur Ausführung des vollständigen Beispiels müssen sich die folgenden Vorlagendateien in demselben Verzeichnis wie die aktuelle PowerShell-Sitzung befinden:

  • prereq.azuredeploy.json zum Erstellen des Schlüsseltresors und der verwalteten Identität.
  • azuredeploy.json zum Erstellen des Azure Maps-Kontos, Konfigurieren der Rollenzuweisung und verwalteten Identität sowie zum Speichern des SAS-Tokens im Schlüsseltresor.
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"

Beispiel aus der realen Welt

Sie können Anforderungen an Azure Maps-APIs über die meisten Clients ausführen, z. B. C#, Java oder JavaScript. Postman konvertiert eine API-Anforderung in einen einfachen Clientcodeausschnitt in fast jeder Programmiersprache oder jedem Framework, die bzw. das Sie auswählen. Sie können diesen generierten Codeausschnitt in Ihren Front-End-Anwendungen verwenden.

Das folgende kleine JavaScript-Codebeispiel zeigt, wie Sie Ihr SAS-Token bei der Fetch-API von JavaScript verwenden können, um Azure Maps-Informationen abzurufen und zurückzugeben. Das Beispiel verwendet die API Get Search Address (Suchadresse abrufen), Version 1.0. Geben Sie Ihren eigenen Wert für <your SAS token> an.

Damit dieses Beispiel funktioniert, müssen Sie es aus demselben Ursprung wie die allowedOrigins für den API-Aufruf ausführen. Wenn Sie beispielsweise https://contoso.com im API-Aufruf als allowedOrigins angeben, sollte https://contoso.com die HTML-Seite zum Hosten des JavaScripts sein.

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
  });

Bereinigen von Ressourcen

Wenn Sie die Azure-Ressourcen nicht mehr benötigen, können Sie sie löschen:

az group delete --name {group-name}

Nächste Schritte

Stellen Sie eine ARM-Schnellstartvorlage zum Erstellen eines Azure Maps-Kontos bereit, das ein SAS-Token verwendet:

Ausführlichere Beispiele finden Sie unter:

Suchen der API-Nutzungsmetriken für Ihr Azure Maps-Konto:

Sehen Sie sich Beispiele an, die zeigen, wie Sie Microsoft Entra ID in Azure Maps integrieren: