Creación de un token de SAS de delegación de usuarios con Azure Blob Storage y JavaScript
En este artículo se muestra cómo crear un token de SAS de delegación de usuarios en la biblioteca cliente de Azure Blob Storage v12 para JavaScript. Una SAS de delegación de usuarios, introducida con la versión 2018-11-09, protegida con credenciales de Microsoft Entra, solo se admite para Blob service para:
- Conceder acceso a un contenedor existente.
- Conceder acceso para crear, usar y eliminar blobs.
Para crear una firma de acceso compartido de delegación de usuarios, el cliente debe tener permisos para llamar a la operación blobServiceClient.getUserDelegationKey. La clave devuelta por esta operación se usa para firmar la firma de acceso compartido de delegación de usuarios. La entidad de seguridad que llama a esta operación debe tener asignado un rol RBAC que incluya la acción Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/.
Los permisos concedidos a un cliente que posea la firma de acceso compartido son la intersección de los permisos concedidos a la entidad de seguridad que solicitó la clave de delegación de usuarios y los concedidos al recurso en el token de SAS en el campo permisos firmados (sp). Si un permiso concedido a la entidad de seguridad a través de RBAC no se concede además en el token de SAS, no se concederá al cliente que intenta usar la firma de acceso compartido para acceder al recurso.
Los fragmentos de código de ejemplo están disponibles en GitHub como archivos de Node.js ejecutables.
Paquete (npm) | Ejemplos | Referencia de la API | Código fuente de la biblioteca | Hacer comentarios
Procedimientos recomendados para los tokens de SAS de delegación de usuarios
Dado que cualquier persona con el token de SAS puede usarlo para acceder al contenedor y los blobs, debe definirlo con los permisos más restrictivos que permitan que el token complete las tareas necesarias.
Procedimientos recomendados para los tokens de SAS
Uso de DefaultAzureCredential en la nube de Azure
Para autenticarse en Azure, sin secretos, configure la identidad administrada. Este enfoque permite que el código use DefaultAzureCredential.
Para configurar la identidad administrada para la nube de Azure:
- Creación de una entidad administrada
- Establecimiento de los roles de almacenamiento adecuados para la identidad
- Configuración del entorno de Azure para que funcione con la identidad administrada
Cuando se completen estas dos tareas, use DefaultAzureCredential en lugar de una cadena de conexión o una clave de cuenta. Este enfoque permite que todos los entornos usen el mismo código fuente exacto sin el problema de usar secretos en el código fuente.
Uso de DefaultAzureCredential para el entorno de desarrollo local
En el entorno de desarrollo local, la identidad de Azure (su cuenta de desarrollo personal o de desarrollo que use para iniciar sesión en Azure Portal) debe autenticarse en Azure para usar el mismo código en los entornos de ejecución locales y en la nube.
Contenedor: incorporación de las dependencias necesarias a la aplicación
Incluya las dependencias necesarias para crear un token de SAS de contenedor.
const {
DefaultAzureCredential
} = require('@azure/identity');
const {
ContainerClient,
BlobServiceClient,
ContainerSASPermissions,
generateBlobSASQueryParameters,
SASProtocol
} = require('@azure/storage-blob');
// used for local environment variables
require('dotenv').config();
Contenedor: obtención de las variables de entorno
El nombre de la cuenta de Blob Storage y el nombre del contenedor son los valores mínimos necesarios para crear un token de SAS de contenedor:
// Get environment variables for DefaultAzureCredential
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
Creación de una SAS con DefaultAzureCredential
Los pasos conceptuales siguientes son necesarios para crear un token de SAS con DefaultAzureCredential:
- Configuración de DefaultAzureCredential
- Desarrollo local: uso de la identidad personal y establecimiento de roles para el almacenamiento
- Nube de Azure: creación de una identidad administrada
- Uso de DefaultAzureCredential para obtener la clave de delegación de usuarios con UserDelegationKey
- Uso de la clave de delegación de usuarios para construir el token de SAS con los campos adecuados con generateBlobSASQueryParameters
Contenedor: creación de un token de SAS con DefaultAzureCredential
Con la identidad configurada, use el código siguiente para crear el token de SAS de delegación de usuarios para una cuenta y un contenedor 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;
}
El código de servidor anterior crea un flujo de valores para crear el token de SAS del contenedor:
- Creación de BlobServiceClient con DefaultAzureCredential
- Use la operación blobServiceClient.getUserDelegationKey para crear UserDelegationKey
- Use la clave para crear la cadena de token de SAS con generateBlobSASQueryParameters
Una vez creado el token de SAS del contenedor, puede proporcionárselo al cliente que consumirá el token. Después, este puede usarlo para enumerar los blobs de un contenedor. En un ejemplo de código de cliente se muestra cómo probar la SAS como consumidor.
Contenedor: uso del token de SAS
Una vez creado el token de SAS del contenedor, úselo. Como ejemplo del uso del token de SAS, puede hacer lo siguiente:
- Construya una dirección URL completa, incluido el nombre del contenedor y la cadena de consulta. La cadena de consulta es el token de SAS.
- Cree un ContainerClient con la dirección URL del contenedor.
- Use el cliente: en este ejemplo, enumere los blobs del contenedor con 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: incorporación de las dependencias necesarias a la aplicación
Incluya las dependencias necesarias para crear un token de SAS de n blobs.
const {
DefaultAzureCredential
} = require('@azure/identity');
const {
BlockBlobClient,
BlobServiceClient,
BlobSASPermissions,
generateBlobSASQueryParameters,
SASProtocol
} = require('@azure/storage-blob');
// used for local environment variables
require('dotenv').config();
Blob: obtención de las variables de entorno
El nombre de la cuenta de Blob Storage y el nombre del contenedor son los valores mínimos necesarios para crear un token de SAS de blob:
const accountName = process.env.AZURE_STORAGE_ACCOUNT_NAME;
const containerName = process.env.AZURE_STORAGE_BLOB_CONTAINER_NAME;
Cuando necesite crear un token de SAS de blob, debe tener el nombre del blob para crear el token de SAS. Esto será predeterminado, como un nombre de blob aleatorio, un nombre de blob enviado por el usuario o un nombre generado a partir de la aplicación.
// Create random blob name for text file
const blobName = `${(0|Math.random()*9e6).toString(36)}.txt`;
Blob: creación de un token de SAS con DefaultAzureCredential
Con la identidad configurada, use el código siguiente para crear el token de SAS de delegación de usuarios para una cuenta y un contenedor 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;
}
El código anterior crea un flujo de valores para crear el token de SAS del contenedor:
- Creación de BlobServiceClient con DefaultAzureCredential
- Use la operación blobServiceClient.getUserDelegationKey para crear UserDelegationKey
- Use la clave para crear la cadena del token de SAS. Si el nombre del blob no se especificó en las opciones, el token de SAS es un token de contenedor.
Una vez creado el token de SAS del blob, puede proporcionárselo al cliente que consumirá el token. Después, el cliente podrá usarlo para cargar un blob. En un ejemplo de código de cliente se muestra cómo probar la SAS como consumidor.
Blob: uso del token de SAS
Una vez creado el token de SAS de blob, úselo. Como ejemplo del uso del token de SAS, puede hacer lo siguiente:
- Construya una dirección URL completa, incluido el nombre del contenedor, el nombre del blob y la cadena de consulta. La cadena de consulta es el token de SAS.
- Cree un BlockBlobClient con la dirección URL del contenedor.
- Use el cliente: en este ejemplo, cargue el blob con cargar.
// 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);
}