Partager via


Créer un jeton SAP de délégation d’utilisateur avec Stockage Blob Azure et JavaScript

Cet article explique comment créer un jeton SAS de délégation d’utilisateur pour utiliser la bibliothèque de client du Stockage Blob Azure v12 pour JavaScript. Une SAP de délégation d’utilisateur, introduite avec la version 2018-11-09, est sécurisée avec les informations d’identification Microsoft Entra et est prise en charge uniquement pour le service Blob :

  • Accordez l’accès à un conteneur existant.
  • Accordez l’accès à la création, à l’utilisation et à la suppression d’objets blob.

Pour créer une SAP de délégation d’utilisateur, un client doit disposer d’autorisations pour appeler l’opération blobServiceClient.getUserDelegationKey . La clé renvoyée par cette opération est utilisée pour signer la SAP de délégation d’utilisateur. Le principal de sécurité qui appelle cette opération doit se voir attribuer un rôle RBAC qui inclut l’action Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/.

Les autorisations accordées à un client qui possède la SAP sont l’intersection des autorisations qui ont été accordées au principal de sécurité qui a demandé la clé de délégation d’utilisateur et des autorisations accordées à la ressource sur le jeton SAP dans le champ autorisations signées (sp). Si une autorisation accordée au principal de sécurité via RBAC n’est pas également accordée sur le jeton SAP, cette autorisation n’est pas accordée au client qui tente d’utiliser la SAP pour accéder à la ressource.

Des exemples d’extraits de code sont disponibles dans GitHub en tant que fichiers Node.js exécutables.

Package (npm) | Exemples | Référence API | Code source de la bibliothèque | Envoyer des commentaires

Meilleures pratiques pour les jetons SAP de délégation d’utilisateur

Étant donné que toute personne disposant du jeton SAP peut l’utiliser pour accéder au conteneur et aux objets blob, vous devez configurer le jeton SAP avec les autorisations les plus restrictives qui permettent néanmoins au jeton d’effectuer les tâches nécessaires.

Bonnes pratiques pour les jetons SAP

Utiliser DefaultAzureCredential dans le cloud Azure

Pour vous authentifier auprès d’Azure sans secrets, configurez une identité managée. Cette approche permet à votre code d’utiliser DefaultAzureCredential.

Pour configurer une identité managée pour le cloud Azure :

  • Créer une identité managée
  • Définir les rôles de stockage appropriés pour l’identité
  • Configurer votre environnement Azure pour qu’il fonctionne avec votre identité managée

Lorsque ces deux tâches sont terminées, utilisez DefaultAzureCredential au lieu d’une chaîne de connexion ou d’une clé de compte. Cette approche permet à tous vos environnements d’utiliser exactement le même code source sans le problème d’utilisation des secrets dans le code source.

Utiliser DefaultAzureCredential dans le développement local

Dans votre environnement de développement local, votre identité Azure (votre compte personnel ou de développement que vous utilisez pour vous connecter au Portail Azure) doit s’authentifier auprès d’Azure pour utiliser le même code dans les runtimes locaux et cloud.

Conteneur : ajouter les dépendances nécessaires à votre application

Incluez les dépendances nécessaires pour créer un jeton SAP de conteneur.

const {
    DefaultAzureCredential
} = require('@azure/identity');
const {
    ContainerClient,
    BlobServiceClient,
    ContainerSASPermissions,
    generateBlobSASQueryParameters,
    SASProtocol
} = require('@azure/storage-blob');

// used for local environment variables
require('dotenv').config();

Conteneur : obtenir des variables d’environnement

Le nom du compte de stockage Blob et le nom du conteneur sont les valeurs minimales requises pour créer un jeton SAP de conteneur :

// Get environment variables for DefaultAzureCredential
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;

Créer une SAP avec DefaultAzureCredential

Les étapes conceptuelles suivantes sont requises pour créer un jeton SAP avec DefaultAzureCredential :

  • Configurer DefaultAzureCredential
    • Développement local : utiliser des identités personnelles et définir des rôles pour le stockage
    • Cloud Azure - Créer une identité managée
  • Utiliser DefaultAzureCredential pour obtenir la clé de délégation utilisateur avec UserDelegationKey
  • Utilisez la clé de délégation utilisateur pour construire le jeton SAP avec les champs appropriés avec generateBlobSASQueryParameters

Conteneur : créer un jeton SAP avec DefaultAzureCredential

Avec l’identité configurée, utilisez le code suivant pour créer un jeton SAP de délégation d’utilisateur pour un compte et un conteneur existants :

// Server creates User Delegation SAS Token for container
async function createContainerSas() {

    // Get environment variables
    const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
    const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;

    // Best practice: create time limits
    const TEN_MINUTES = 10 * 60 * 1000;
    const NOW = new Date();

    // Best practice: set start time a little before current time to 
    // make sure any clock issues are avoided
    const TEN_MINUTES_BEFORE_NOW = new Date(NOW.valueOf() - TEN_MINUTES);
    const TEN_MINUTES_AFTER_NOW = new Date(NOW.valueOf() + TEN_MINUTES);

    // Best practice: use managed identity - DefaultAzureCredential
    const blobServiceClient = new BlobServiceClient(
        `https://${accountName}.blob.core.windows.net`,
        new DefaultAzureCredential()
      );

    // Best practice: delegation key is time-limited  
    // When using a user delegation key, container must already exist 
    const userDelegationKey = await blobServiceClient.getUserDelegationKey(
        TEN_MINUTES_BEFORE_NOW, 
        TEN_MINUTES_AFTER_NOW
    );

    // Need only list permission to list blobs 
    const containerPermissionsForAnonymousUser = "l";

    // Best practice: SAS options are time-limited
    const sasOptions = {
        containerName,                                           
        permissions: ContainerSASPermissions.parse(containerPermissionsForAnonymousUser), 
        protocol: SASProtocol.HttpsAndHttp,
        startsOn: TEN_MINUTES_BEFORE_NOW,
        expiresOn: TEN_MINUTES_AFTER_NOW
    };
 
    const sasToken = generateBlobSASQueryParameters(
        sasOptions,
        userDelegationKey,
        accountName 
    ).toString();

    return sasToken;
}

Le code serveur précédent crée un flux de valeurs pour créer le jeton SAP de conteneur :

Une fois que vous avez créé le jeton SAP de conteneur, vous pouvez le fournir au client, qui consommera le jeton. Le client peut ensuite l’utiliser pour répertorier les objets blob dans un conteneur. Un exemple de code client montre comment tester la SAP en tant que consommateur.

Conteneur : utiliser un jeton SAP

Une fois le jeton SAP de conteneur créé, utilisez-le. En guise d’exemple d’utilisation du jeton SAP, vous :

  • Construisez une URL complète, comprenant le nom du conteneur et la chaîne de requête. La chaîne de requête est le jeton SAP.
  • Créez un ContainerClient avec l’URL du conteneur.
  • Utilisez le client : dans cet exemple, répertoriez les objets blob dans le conteneur avec listBlobsFlat.
// Client or another process uses SAS token to use container
async function listBlobs(sasToken){

    // Get environment variables
    const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
    const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
    
    // Create Url
    // SAS token is the query string with typical `?` delimiter
    const sasUrl = `https://${accountName}.blob.core.windows.net/${containerName}?${sasToken}`;
    console.log(`\nContainerUrl = ${sasUrl}\n`);

    // Create container client from SAS token url
    const containerClient = new ContainerClient(sasUrl);

    let i = 1;

    // List blobs in container
    for await (const blob of containerClient.listBlobsFlat()) {
        console.log(`Blob ${i++}: ${blob.name}`);
    }    
}

Blob : ajouter les dépendances nécessaires à votre application

Incluez les dépendances nécessaires pour créer un jeton SAP d’objet blob.

const {
    DefaultAzureCredential
} = require('@azure/identity');
const {
    BlockBlobClient,
    BlobServiceClient,
    BlobSASPermissions,
    generateBlobSASQueryParameters,
    SASProtocol
} = require('@azure/storage-blob');

// used for local environment variables
require('dotenv').config();

Blob : définir les variables d’environnement

Le nom du compte de stockage Blob et le nom du conteneur sont les valeurs minimales requises pour créer un jeton SAP d’objet blob :

const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;

Lorsque vous devez créer un jeton SAP d’objet blob, vous devez avoir le nom de l’objet blob pour créer le jeton SAP. Cela sera prédéterminé comme un nom d’objet blob aléatoire, un nom d’objet blob soumis par l’utilisateur ou un nom généré à partir de votre application.

// Create random blob name for text file
const blobName = `${(0|Math.random()*9e6).toString(36)}.txt`;

Objet blob : créer un jeton SAP avec DefaultAzureCredential

Avec l’identité configurée, utilisez le code suivant pour créer un jeton SAP de délégation d’utilisateur pour un compte et un conteneur existants :

// Server creates User Delegation SAS Token for blob
async function createBlobSas(blobName) {

    // Get environment variables
    const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
    const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;

    // Best practice: create time limits
    const TEN_MINUTES = 10 * 60 * 1000;
    const NOW = new Date();

    // Best practice: set start time a little before current time to 
    // make sure any clock issues are avoided
    const TEN_MINUTES_BEFORE_NOW = new Date(NOW.valueOf() - TEN_MINUTES);
    const TEN_MINUTES_AFTER_NOW = new Date(NOW.valueOf() + TEN_MINUTES);

    // Best practice: use managed identity - DefaultAzureCredential
    const blobServiceClient = new BlobServiceClient(
        `https://${accountName}.blob.core.windows.net`,
        new DefaultAzureCredential()
      );

    // Best practice: delegation key is time-limited  
    // When using a user delegation key, container must already exist 
    const userDelegationKey = await blobServiceClient.getUserDelegationKey(
        TEN_MINUTES_BEFORE_NOW, 
        TEN_MINUTES_AFTER_NOW
    );

    // Need only create/write permission to upload file
    const blobPermissionsForAnonymousUser = "cw"

    // Best practice: SAS options are time-limited
    const sasOptions = {
        blobName,
        containerName,                                           
        permissions: BlobSASPermissions.parse(blobPermissionsForAnonymousUser), 
        protocol: SASProtocol.HttpsAndHttp,
        startsOn: TEN_MINUTES_BEFORE_NOW,
        expiresOn: TEN_MINUTES_AFTER_NOW
    };
 
    const sasToken = generateBlobSASQueryParameters(
        sasOptions,
        userDelegationKey,
        accountName 
    ).toString();

    return sasToken;
}

Le code précédent crée un flux de valeurs pour créer le jeton SAP de conteneur :

Une fois que vous avez créé le jeton SAP d’objet blob, vous pouvez le fournir au client, qui consommera le jeton. Le client peut ensuite l’utiliser pour charger un objet blob. Un exemple de code client montre comment tester la SAP en tant que consommateur.

Blob : utiliser le jeton SAP

Une fois le jeton SAP d’objet blob créé, utilisez-le. En guise d’exemple d’utilisation du jeton SAP, vous :

  • Construisez une URL complète, comprenant le nom du conteneur, le nom d’objet blob et la chaîne de requête. La chaîne de requête est le jeton SAP.
  • Créez un BlockBlobClient avec l’URL du conteneur.
  • Utilisez le client : dans cet exemple, chargez un objet blob avec upload.
// Client or another process uses SAS token to upload content to blob
async function uploadStringToBlob(blobName, sasToken, textAsString){

    // Get environment variables
    const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
    const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;

    // Create Url SAS token as query string with typical `?` delimiter
    const sasUrl = `https://${accountName}.blob.core.windows.net/${containerName}/${blobName}?${sasToken}`;
    console.log(`\nBlobUrl = ${sasUrl}\n`);

    // Create blob client from SAS token url
    const blockBlobClient = new BlockBlobClient(sasUrl);

    // Upload string
    await blockBlobClient.upload(textAsString, textAsString.length, undefined);    
}

Voir aussi