Erstellen eines SAS-Tokens für die Benutzerdelegierung mit Azure Blob Storage und JavaScript

In diesem Artikel erfahren Sie, wie Sie in der Azure Blob Storage-Clientbibliothek v12 für JavaScript ein SAS-Token für die Benutzerdelegierung erstellen. Eine mit Version 2018-11-09 eingeführte Benutzerdelegierungs-SAS ist mit Microsoft Entra-Anmeldeinformationen gesichert und wird für den Blob-Dienst nur für folgende Zwecke unterstützt:

  • Gewähren des Zugriffs auf einen vorhandenen Container
  • Gewähren des Zugriffs zum Erstellen, Verwenden und Löschen von Blobs

Zum Erstellen einer Benutzerdelegierungs-SAS muss ein Client über Berechtigungen zum Aufrufen des Vorgangs blobServiceClient.getUserDelegationKey verfügen. Der von diesem Vorgang zurückgegebene Schlüssel wird zum Signieren der Benutzerdelegierungs-SAS verwendet. Dem Sicherheitsprinzipal, der diesen Vorgang aufruft, muss eine RBAC-Rolle zugewiesen sein, die Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action enthält.

Die einem Client gewährten Berechtigungen, der die SAS besitzt, sind die Schnittmenge der Berechtigungen, die dem Sicherheitsprinzipal gewährt wurden, der den Benutzerdelegierungsschlüssel angefordert hat, und der Berechtigungen, die der Ressource im SAS-Token im Feld der signierten Berechtigungen (sp) gewährt wurden. Wenn eine Berechtigung, die dem Sicherheitsprinzipal über RBAC gewährt wurde, nicht auch dem SAS-Token gewährt wird, wird diese Berechtigung dem Client, der versucht, die SAS für den Zugriff auf die Ressource zu verwenden, nicht gewährt.

Die Beispielcodeausschnitte sind in GitHub als ausführbare Node.js-Dateien verfügbar.

Paket (npm) | Beispiele | API-Dokumentation | Bibliothekquellcode | Feedback einreichen

Best Practices für SAS-Token für die Benutzerdelegierung

Da jede Person mit dem SAS-Token auf den Container und Blobs zugreifen kann, sollten Sie das SAS-Token mit den restriktivsten Berechtigungen definieren, mit denen das Token die erforderlichen Aufgaben ausführen kann.

Best Practices für SAS-Token

Verwenden von DefaultAzureCredential in der Azure-Cloud

Um sich ohne Geheimnisse bei Azure zu authentifizieren, richten Sie eine verwaltete Identität ein. Mit diesem Ansatz kann Ihr Code DefaultAzureCredential verwenden.

So richten Sie eine verwaltete Identität für die Azure-Cloud ein:

  • Erstellen einer verwalteten Identität
  • Festlegen der entsprechenden Speicherrollen für die Identität
  • Konfigurieren Ihrer Azure-Umgebung für die verwaltete Identität

Wenn diese beiden Aufgaben abgeschlossen sind, verwenden Sie DefaultAzureCredential anstelle einer Verbindungszeichenfolge oder eines Kontoschlüssels. Mit diesem Ansatz können alle Ihre Umgebungen exakt den gleichen Quellcode verwenden, ohne dass im Quellcode Geheimnisse preisgegeben werden müssen.

Verwenden von DefaultAzureCredential in der lokalen Entwicklung

In Ihrer lokalen Entwicklungsumgebung muss sich Ihre Azure-Identität (Ihr persönliches Konto oder Entwicklungskonto, das Sie zum Anmelden beim Azure-Portal verwenden) bei Azure authentifizieren, damit ein und derselbe Code in lokalen und Cloudruntimes verwendet werden kann.

Container: Hinzufügen erforderlicher Abhängigkeiten zu Ihrer Anwendung

Schließen Sie die erforderlichen Abhängigkeiten ein, um ein Container-SAS-Token zu erstellen.

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

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

Container: Abrufen von Umgebungsvariablen

Die Namen des Blob Storage-Kontos und -Containers sind die Werte, die zum Erstellen eines Container-SAS-Tokens mindestens erforderlich sind:

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

Erstellen einer SAS mit DefaultAzureCredential

Die folgenden konzeptionellen Schritte sind erforderlich, um ein SAS-Token mit DefaultAzureCredential zu erstellen:

  • Einrichten von DefaultAzureCredential
    • Lokale Entwicklung – Verwenden einer persönlichen Identität und Festlegen von Rollen für den Speicher
    • Azure-Cloud – Erstellen einer verwalteten Identität
  • Verwenden von DefaultAzureCredential zum Abrufen des Benutzerdelegierungsschlüssels mit UserDelegationKey
  • Verwenden des Benutzerdelegierungsschlüssels zum Erstellen des SAS-Tokens mit den entsprechenden Feldern mit generateBlobSASQueryParameters

Container: Erstellen eines SAS-Tokens mit DefaultAzureCredential

Nach dem Konfigurieren der Identität verwenden Sie den folgenden Code, um das SAS-Token für die Benutzerdelegierung für ein vorhandenes Konto und einen vorhandenen Container zu erstellen:

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

Der hier gezeigte Servercode erstellt eine Reihe von Werten zum Erstellen des Container-SAS-Tokens:

Nachdem Sie das Container-SAS-Token erstellt haben, können Sie es für den Client bereitstellen, der das Token verwenden soll. Der Client kann es dann verwenden, um die Blobs in einem Container aufzulisten. Ein Clientcodebeispiel zeigt, wie Sie die SAS als Consumer testen.

Container: Verwenden des SAS-Tokens

Nachdem das Container-SAS-Token erstellt wurde, verwenden Sie es. Beispiele für die Verwendung des SAS-Tokens:

  • Erstellen Sie eine vollständige URL, einschließlich Containername und Abfragezeichenfolge. Die Abfragezeichenfolge ist das SAS-Token.
  • Erstellen Sie einen ContainerClient mit der Container-URL.
  • Verwenden Sie den Client: In diesem Beispiel listen Sie Blobs im Container mit listBlobsFlat auf.
// 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: Hinzufügen erforderlicher Abhängigkeiten zu Ihrer Anwendung

Schließen Sie die erforderlichen Abhängigkeiten ein, um ein Blob-SAS-Token zu erstellen.

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

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

Blob: Abrufen der Umgebungsvariablen

Die Namen des Blob Storage-Kontos und -Containers sind die Werte, die zum Erstellen eines Blob-SAS-Tokens mindestens erforderlich sind:

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

Wenn Sie ein Blob-SAS-Token erstellen, müssen Sie den Blobnamen kennen. Dieser wird vorab festgelegt und kann ein zufälliger Blobname, ein vom Benutzer übermittelter Blobname oder ein von Ihrer Anwendung generierter Name sein.

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

Blob: Erstellen eines SAS-Tokens mit DefaultAzureCredential

Nach dem Konfigurieren der Identität verwenden Sie den folgenden Code, um das SAS-Token für die Benutzerdelegierung für ein vorhandenes Konto und einen vorhandenen Container zu erstellen:

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

Der hier gezeigte Code erstellt eine Reihe von Werten zum Erstellen des Container-SAS-Tokens:

Nachdem Sie das Blob-SAS-Token erstellt haben, können Sie es für den Client bereitstellen, der das Token verwenden soll. Der Client kann es dann verwenden, um einen Blob hochzuladen. Ein Clientcodebeispiel zeigt, wie Sie die SAS als Consumer testen.

Blob: Verwenden des SAS-Tokens

Nachdem das Blob-SAS-Token erstellt wurde, verwenden Sie es. Beispiele für die Verwendung des SAS-Tokens:

  • Erstellen Sie eine vollständige URL, einschließlich Containername, Blobname und Abfragezeichenfolge. Die Abfragezeichenfolge ist das SAS-Token.
  • Erstellen Sie einen BlockBlobClient mit der Container-URL.
  • Verwenden Sie den Client: In diesem Beispiel laden Sie den Blob mit upload hoch.
// 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);    
}

Siehe auch