Compartilhar via


Criar um token SAS de delegação de usuário com o Armazenamento de Blobs do Azure e JavaScript

Este artigo mostra como criar um token SAS de delegação de usuário na biblioteca de clientes do Armazenamento de Blobs do Azure v12 para JavaScript. Uma SAS de delegação de usuário, introduzida com a versão 2018-11-09, é segura com credenciais do Microsoft Entra e tem suporte para o serviço Blob apenas para:

  • Conceder acesso a um contêiner existente.
  • Conceder acesso para criar, usar e excluir blobs.

Para criar uma SAS de delegação de usuário, um cliente precisa ter permissões para chamar a operação blobServiceClient.getUserDelegationKey. A chave retornada por essa operação é usada para assinar a SAS de delegação de usuário. A entidade de segurança que chama essa operação precisa ter uma função RBAC que inclua Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey.

As permissões concedidas a um cliente que possui a SAS são a interseção das permissões concedidas à entidade de segurança que solicitou a chave de delegação do usuário e das permissões concedidas ao recurso no token SAS no campo de permissões assinadas (sp). Se uma permissão concedida à entidade de segurança por meio do RBAC não for concedida também no token SAS, essa permissão não será concedida ao cliente que tenta usar a SAS para acessar o recurso.

Os snippets de código de exemplo estão disponíveis no GitHub como arquivos Node.js executáveis.

Pacote (npm) | Amostras | Referência de API | Código-fonte da biblioteca | Fazer comentários

Melhores práticas para tokens SAS de delegação de usuário

Como qualquer pessoa com o token SAS pode usá-lo para acessar o contêiner e os blobs, você precisa definir o token SAS com as permissões mais restritivas que ainda permitam que o token conclua as tarefas necessárias.

Melhores práticas para tokens SAS

Usar a DefaultAzureCredential na nuvem do Azure

Para autenticar no Azure, sem segredos, configure a identidade gerenciada. Isso permite que o código use DefaultAzureCredential.

Para configurar a identidade gerenciada para a nuvem do Azure:

  • Criar uma identidade gerenciada
  • Defina as Funções de armazenamento apropriadas para a identidade
  • Configurar o ambiente do Azure para funcionar com a identidade gerenciada

Quando essas duas tarefas forem concluídas, use DefaultAzureCredential em vez de uma cadeia de conexão ou chave de conta. Isso permite que todos os ambientes usem exatamente o mesmo código-fonte sem o problema de usar segredos nele.

Usar DefaultAzureCredential no desenvolvimento local

No ambiente de desenvolvimento local, sua identidade do Azure (a conta pessoal ou de desenvolvimento que você usa para entrar no portal do Azure) precisa se autenticar no Azure para usar o mesmo código em runtimes locais e de nuvem.

Contêiner: adicionar as dependências necessárias ao aplicativo

Inclua as dependências necessárias para criar um token SAS de contêiner.

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

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

Contêiner: obter variáveis de ambiente

O nome da conta do Armazenamento de Blobs e o nome do contêiner são os valores mínimos necessários para criar um token SAS de contêiner:

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

Criar uma SAS com DefaultAzureCredential

As seguintes etapas conceituais são necessárias para criar um token SAS com DefaultAzureCredential:

  • Configurar DefaultAzureCredential
    • Desenvolvimento local – usar a identidade pessoal e definir funções para armazenamento
    • Nuvem do Azure – criar identidade gerenciada
  • Use DefaultAzureCredential para obter a chave de delegação do usuário com UserDelegationKey
  • Use a chave de delegação do usuário para construir o token SAS com os campos apropriados com generateBlobSASQueryParameters

Contêiner: criar token SAS com DefaultAzureCredential

Com a identidade configurada, use o seguinte código para criar o Token SAS de delegação de usuário para uma conta e um contêiner existentes:

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

O código de servidor anterior cria um fluxo de valores para criar o token SAS do contêiner:

Depois de criar o token SAS do contêiner, você poderá fornecê-lo ao cliente que o consumirá. Em seguida, o cliente poderá usá-lo para listar os blobs em um contêiner. Um exemplo de código de cliente mostra como testar a SAS como consumidor.

Contêiner: usar token SAS

Depois que o token SAS do contêiner for criado, use o token. Como exemplo de uso do token SAS, você:

  • Constrói uma URL completa, incluindo o nome do contêiner e a cadeia de caracteres de consulta. A cadeia de caracteres de consulta é o token SAS.
  • Cria um ContainerClient com a URL do contêiner.
  • Usa o cliente: neste exemplo, liste os blobs no contêiner com 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: adicionar dependências necessárias ao aplicativo

Inclua as dependências necessárias para criar um token SAS de 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: obter variáveis de ambiente

O nome da conta do Armazenamento de Blobs e o nome do contêiner são os valores mínimos necessários para criar um token SAS de blob:

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

Quando precisa criar um token SAS de blob, você precisa ter o nome do blob para criar o token SAS. Ele será predeterminado, como um nome de blob aleatório, um nome de blob enviado pelo usuário ou um nome gerado do aplicativo.

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

Blob: criar token SAS com DefaultAzureCredential

Com a identidade configurada, use o seguinte código para criar o Token SAS de delegação de usuário para uma conta e um contêiner existentes:

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

O código anterior cria um fluxo de valores para criar o token SAS do contêiner:

Depois de criar o token SAS do blob, você poderá fornecê-lo ao cliente que o consumirá. Em seguida, o cliente poderá usá-lo para carregar um blob. Um exemplo de código de cliente mostra como testar a SAS como consumidor.

Blob: usar token SAS

Depois que o token SAS do blob for criado, use o token. Como exemplo de uso do token SAS, você:

  • Constrói uma URL completa, incluindo o nome do contêiner, o nome do blob e a cadeia de caracteres de consulta. A cadeia de caracteres de consulta é o token SAS.
  • Crie um BlockBlobClient com a URL do contêiner.
  • Usar o cliente: neste exemplo, carregue o blob com 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);    
}

Confira também