Zabezpečení účtu Azure Mapy pomocí tokenu SAS

Tento článek popisuje, jak vytvořit účet Azure Mapy s bezpečně uloženým tokenem SAS, který můžete použít k volání rozhraní AZURE Mapy REST API.

Předpoklady

  • Předplatné Azure. Pokud ještě nemáte účet Azure, zaregistrujte si bezplatný účet.

  • Oprávnění role vlastníka k předplatnému Azure Potřebujete oprávnění vlastníka k:

    • Vytvořte trezor klíčů ve službě Azure Key Vault.
    • Vytvořte spravovanou identitu přiřazenou uživatelem.
    • Přiřaďte spravovanou identitu roli.
    • Vytvořte účet Azure Mapy.
  • Azure CLI se nainstalovalo k nasazení prostředků.

Ukázkový scénář: Zabezpečené úložiště tokenů SAS

Přihlašovací údaje tokenu SAS udělují úroveň přístupu, kterou určuje komukoli, kdo ho uchovává, dokud platnost tokenu nevyprší nebo se neodvolá přístup. Aplikace, které používají ověřování pomocí tokenu SAS, by měly bezpečně ukládat klíče.

Tento scénář bezpečně ukládá token SAS jako tajný kód ve službě Key Vault a distribuuje token do veřejného klienta. Události životního cyklu aplikace můžou generovat nové tokeny SAS bez přerušení aktivních připojení, která používají existující tokeny.

Další informace o konfiguraci služby Key Vault najdete v příručce pro vývojáře ve službě Azure Key Vault.

Následující ukázkový scénář používá k provedení následujících kroků dvě nasazení šablony Azure Resource Manageru (ARM):

  1. Vytvořte trezor klíčů.
  2. Vytvořte spravovanou identitu přiřazenou uživatelem.
  3. Přiřaďte roli Azure RBAC (Řízení přístupu na základě role) Azure Mapy Čtenář dat spravované identitě přiřazené uživatelem.
  4. Vytvořte účet Azure Mapy s konfigurací sdílení prostředků mezi zdroji (CORS) a připojte spravovanou identitu přiřazenou uživatelem.
  5. Vytvořte a uložte token SAS v trezoru klíčů Azure.
  6. Načtěte tajný klíč tokenu SAS z trezoru klíčů.
  7. Vytvořte požadavek rozhraní REST API služby Azure Mapy, který používá token SAS.

Po dokončení by se měly v PowerShellu pomocí Azure CLI zobrazit výsledky rozhraní REST API služby Azure MapySearch Address (Non-Batch). Prostředky Azure se nasazují s oprávněními pro připojení k účtu Azure Mapy. Existují ovládací prvky pro maximální omezení rychlosti, povolené oblasti, localhost nakonfigurované zásady CORS a Azure RBAC.

Nasazení prostředků Azure pomocí Azure CLI

Následující kroky popisují, jak vytvořit a nakonfigurovat účet Azure Mapy s ověřováním tokenu SAS. V tomto příkladu běží Azure CLI v instanci PowerShellu.

  1. Přihlaste se ke svému předplatnému Azure pomocí az login.

  2. Zaregistrujte službu Key Vault, spravované identity a azure Mapy pro vaše předplatné.

    az provider register --namespace Microsoft.KeyVault
    az provider register --namespace Microsoft.ManagedIdentity
    az provider register --namespace Microsoft.Maps
    
  3. Načtěte ID objektu Microsoft Entra.

    $id = $(az rest --method GET --url 'https://graph.microsoft.com/v1.0/me?$select=id' --headers 'Content-Type=application/json' --query "id")
    
  4. Vytvořte soubor šablony s názvem prereq.azuredeploy.json s následujícím obsahem:

    {
        "$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. Nasaďte požadované prostředky, které jste vytvořili v předchozím kroku. Zadejte vlastní hodnotu pro <group-name>. Ujistěte se, že používáte stejný location účet jako účet Azure Mapy.

    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. Vytvořte soubor šablony azuredeploy.json pro zřízení účtu Azure Mapy, přiřazení role a tokenu SAS.

    Poznámka:

    Vyřazení cenové úrovně Azure Mapy Gen1

    Cenová úroveň Gen1 je teď zastaralá a bude vyřazena 15. 9. 26. Cenová úroveň Gen2 nahrazuje cenovou úroveň Gen1 (S0 i S1). Pokud má váš účet Azure Mapy vybranou cenovou úroveň Gen1, můžete před vyřazením přepnout na ceny Gen2, jinak se automaticky aktualizuje. Další informace najdete v tématu Správa cenové úrovně účtu Azure Mapy.

    {
        "$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. Nasaďte šablonu s parametry ID ze služby Key Vault a prostředků spravované identity, které jste vytvořili v předchozím kroku. Zadejte vlastní hodnotu pro <group-name>. Při vytváření tokenu SAS nastavíte allowedRegions parametr na eastus, westus2a westcentralus. Tato umístění pak můžete použít k odesílání požadavků HTTP do koncového us.atlas.microsoft.com bodu.

    Důležité

    Token SAS uložíte do trezoru klíčů, abyste zabránili jeho přihlašovacím údajům v protokolech nasazení Azure. Tajný klíč tags tokenu SAS obsahuje také název počátečního, vypršení platnosti a podpisového klíče, který se zobrazí, kdy vyprší platnost tokenu 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"
    
  8. Vyhledejte a uložte kopii tajného klíče tokenu SAS ze služby 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. Otestujte token SAS provedením požadavku na koncový bod Azure Mapy. Tento příklad určuje, jestli us.atlas.microsoft.com vaše žádosti směruje do zeměpisu USA. Váš token SAS umožňuje oblasti v rámci zeměpisu 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"
    

Příklad kompletního skriptu

Pokud chcete spustit úplný příklad, musí být následující soubory šablony ve stejném adresáři jako aktuální relace PowerShellu:

  • prereq.azuredeploy.json pro vytvoření trezoru klíčů a spravované identity.
  • azuredeploy.json pro vytvoření účtu Azure Mapy, konfiguraci přiřazení role a spravované identity a uložení tokenu SAS do trezoru klíčů.
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"

Příklad z reálného světa

Požadavky na rozhraní API Azure Mapy můžete spouštět z většiny klientů, jako jsou C#, Java nebo JavaScript. Postman převede požadavek rozhraní API na základní fragment kódu klienta v téměř libovolném programovacím jazyce nebo architektuře, které zvolíte. Tento vygenerovaný fragment kódu můžete použít ve front-endových aplikacích.

Následující malý příklad kódu JavaScriptu ukazuje, jak můžete pomocí tokenu SAS s rozhraním JAVAScript Fetch API získat a vrátit informace o azure Mapy. Příklad používá rozhraní API get Search Address verze 1.0. Zadejte vlastní hodnotu pro <your SAS token>.

Aby tato ukázka fungovala, nezapomeňte ji spustit ze stejného zdroje jako allowedOrigins volání rozhraní API. Pokud například zadáte https://contoso.com jako allowedOrigins ve volání rozhraní API, měla by být https://contoso.comstránka HTML, která je hostitelem javascriptového skriptu.

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

Vyčištění prostředků

Pokud už prostředky Azure nepotřebujete, můžete je odstranit:

az group delete --name {group-name}

Další kroky

Nasazení šablony ARM pro rychlý start pro vytvoření účtu Azure Mapy, který používá token SAS:

Podrobnější příklady najdete tady:

Vyhledejte metriky využití rozhraní API pro váš účet Azure Mapy:

Prozkoumejte ukázky, které ukazují, jak integrovat ID Microsoft Entra s Azure Mapy: