Crear una SAS de servicio para un blob con .NET

Una firma de acceso compartido (SAS) le permite conceder acceso limitado a los contenedores y blobs de la cuenta de almacenamiento. Cuando crea una SAS, especifica sus restricciones, incluidos los recursos de Azure Storage a los que puede acceder un cliente, los permisos que tiene en esos recursos y el tiempo durante el cual la SAS es válida.

Cada SAS se firma con una clave. Puede firmar una SAS de dos maneras:

  • Con una clave creada con las credenciales de Microsoft Entra. Una SAS firmada con credenciales de Microsoft Entra es una SAS de delegación de usuario. Un cliente que cree una SAS de delegación de usuarios debe tener asignado un rol RBAC de Azure que incluya la acción Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey. Para obtener más información, vea Creación de una SAS de delegación de usuarios.
  • Con la clave de la cuenta de almacenamiento. Tanto una SAS de servicio como una SAS de cuenta se firman con la clave de la cuenta de almacenamiento. El cliente que cree una SAS de servicio debe tener acceso directo a la clave de cuenta o asignársele el permiso Microsoft.Storage/storageAccounts/listkeys/action. Para obtener más información, vea Creación de una SAS de servicio o Creación de una SAS de cuenta.

Nota

Una SAS de delegación de usuario ofrece seguridad superior para una SAS firmada con la clave de la cuenta de almacenamiento. Microsoft recomienda el uso de una SAS de delegación de usuario siempre que sea posible. Para más información, consulte Concesión de acceso limitado a datos con firmas de acceso compartido (SAS).

En este artículo se muestra cómo usar la clave de cuenta de almacenamiento para crear un servicio de SAS para un blob con la biblioteca cliente de Azure Blob Storage para .NET.

Acerca de la SAS de servicio

Una SAS de servicio se firma con la clave de acceso de la cuenta. Use la clase StorageSharedKeyCredential para crear la credencial que se usa para firmar la SAS de servicio.

También puede usar una directiva de acceso almacenada para definir los permisos y la duración de la SAS. Si se proporciona el nombre de una directiva de acceso almacenada existente, esa directiva se asocia con la SAS. Para obtener más información sobre las directivas de acceso almacenadas, vea Definir una directiva de acceso almacenada. Si no se proporciona ninguna directiva de acceso almacenada, los ejemplos de código de este artículo muestran cómo definir los permisos y la duración de la SAS.

Creación de una SAS de servicio para un blob

En el siguiente ejemplo de código se muestra cómo crear una SAS de servicio para un recurso de blob. En primer lugar, el código comprueba que el objeto BlobClient está autorizado con una credencial de clave compartida al comprobar la propiedad CanGenerateSasUri. A continuación, genera la SAS de servicio a través de la clase BlobSasBuilder y llama a GenerateSasUri para crear un URI de SAS de servicio basado en los objetos de cliente y generador.

public static async Task<Uri> CreateServiceSASBlob(
    BlobClient blobClient,
    string storedPolicyName = null)
{
    // Check if BlobContainerClient object has been authorized with Shared Key
    if (blobClient.CanGenerateSasUri)
    {
        // Create a SAS token that's valid for one day
        BlobSasBuilder sasBuilder = new BlobSasBuilder()
        {
            BlobContainerName = blobClient.GetParentBlobContainerClient().Name,
            BlobName = blobClient.Name,
            Resource = "b"
        };

        if (storedPolicyName == null)
        {
            sasBuilder.ExpiresOn = DateTimeOffset.UtcNow.AddDays(1);
            sasBuilder.SetPermissions(BlobContainerSasPermissions.Read);
        }
        else
        {
            sasBuilder.Identifier = storedPolicyName;
        }

        Uri sasURI = blobClient.GenerateSasUri(sasBuilder);

        return sasURI;
    }
    else
    {
        // Client object is not authorized via Shared Key
        return null;
    }
}

Usar una SAS de servicio para autorizar un objeto de cliente

En el siguiente ejemplo de código se muestra cómo usar la SAS de servicio para autorizar un objeto BlobClient. Este objeto de cliente se puede usar para realizar operaciones en el recurso de blob en función de los permisos concedidos por la SAS.

En primer lugar, cree un objeto BlobServiceClient firmado con la clave de acceso de la cuenta:

string accountName = "<storage-account-name>";
string accountKey = "<storage-account-key";
StorageSharedKeyCredential storageSharedKeyCredential =
    new(accountName, accountKey);
BlobServiceClient blobServiceClient = new BlobServiceClient(
    new Uri($"https://{accountName}.blob.core.windows.net"),
    storageSharedKeyCredential);

A continuación, genere la SAS de servicio como se muestra en el ejemplo anterior y use la SAS para autorizar un objeto BlobClient:

// Create a Uri object with a service SAS appended
BlobClient blobClient = blobServiceClient
    .GetBlobContainerClient("sample-container")
    .GetBlobClient("sample-blob.txt");
Uri blobSASURI = await CreateServiceSASBlob(blobClient);

// Create a blob client object representing 'sample-blob.txt' with SAS authorization
BlobClient blobClientSAS = new BlobClient(blobSASURI);

Definición de una directiva de acceso almacenada

Una directiva de acceso almacenada proporciona un nivel de control adicional sobre una firma de acceso compartido (SAS) de nivel de servicio en el lado del servidor. Establecer una directiva de acceso almacenada para agrupar firmas de acceso compartido y proporcionar restricciones adicionales para firmas sujetas a la directiva.

Puede usar una directiva de acceso almacenada para cambiar la hora de inicio, la hora de expiración o los permisos para una firma. También puede usar una directiva de acceso almacenada para revocar una firma después de su emisión. Esta sección se centra en los contenedores de blobs, pero también se admiten directivas de acceso almacenadas para recursos compartidos de archivos, colas y tablas.

Para administrar las directivas de acceso almacenadas en un recurso de contenedor, llame a uno de los métodos siguientes desde un objeto BlobContainerClient:

Crear o modificar una directiva de acceso almacenada

Puede establecer un máximo de cinco directivas de acceso en un recurso a la vez. Cada campo SignedIdentifier, con su campo Id único, corresponde a una directiva de acceso. Al intentar establecer más de cinco directivas de acceso al mismo tiempo, el servicio devuelve el código de estado 400 (Bad Request).

En el ejemplo de código siguiente, se muestra cómo crear dos directivas de acceso almacenadas en un recurso de contenedor:

public static async Task CreateStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    // Create a stored access policy with read and write permissions, valid for one day
    List<BlobSignedIdentifier> signedIdentifiers = new List<BlobSignedIdentifier>
    {
        new BlobSignedIdentifier
        {
            Id = "sample-read-write-policy",
            AccessPolicy = new BlobAccessPolicy
            {
                StartsOn = DateTimeOffset.UtcNow,
                ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
                Permissions = "rw"
            }
        },
        new BlobSignedIdentifier
        {
            Id = "sample-read-policy",
            AccessPolicy = new BlobAccessPolicy
            {
                StartsOn = DateTimeOffset.UtcNow,
                ExpiresOn = DateTimeOffset.UtcNow.AddDays(1),
                Permissions = "r"
            }
        }
    };

    // Set the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

También puede modificar una directiva existente. En el ejemplo de código siguiente, se muestra cómo modificar una única directiva de acceso almacenada para actualizar la fecha de expiración de la directiva:

public static async Task ModifyStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    BlobContainerAccessPolicy accessPolicy = await containerClient.GetAccessPolicyAsync();
    List<BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers.ToList();

    // Modify the expiration date a single policy
    var samplePolicy = signedIdentifiers.FirstOrDefault(item => item.Id == "sample-read-policy");
    samplePolicy.AccessPolicy.PolicyExpiresOn = DateTimeOffset.UtcNow.AddDays(7);

    // Update the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

Revocar o eliminar una directiva de acceso almacenada

Para revocar una directiva de acceso almacenada, puede eliminarla, cambiar el identificador firmado para cambiarle el nombre, o bien cambiar la hora de expiración a un valor en el pasado. Al cambiar el identificador firmado se interrumpen las asociaciones entre las firmas existentes y la directiva de acceso almacenada. El cambio de la hora de expiración a un valor en el pasado hace que las firmas asociadas expiren. La eliminación o modificación de la directiva de acceso almacenada afecta inmediatamente a todas las firmas de acceso compartido asociadas a ella.

En el ejemplo de código siguiente, se muestra cómo revocar una directiva al cambiar la propiedad Id del identificador firmado:

public static async Task RevokeStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    BlobContainerAccessPolicy accessPolicy = await containerClient.GetAccessPolicyAsync();
    List<BlobSignedIdentifier> signedIdentifiers = accessPolicy.SignedIdentifiers.ToList();

    // Revoke a single policy by changing its name
    var samplePolicy = signedIdentifiers.FirstOrDefault(item => item.Id == "sample-read-policy");
    samplePolicy.Id = "sample-read-policy-revoke";

    // Update the container's access policy
    await containerClient.SetAccessPolicyAsync(permissions: signedIdentifiers);
}

También puede quitar todas las directivas de acceso de un recurso de contenedor al llamar a SetAccessPolicyAsync con un parámetro vacío permissions. En el ejemplo siguiente, se muestra cómo eliminar todas las directivas de acceso almacenadas de un contenedor especificado:

public static async Task DeleteStoredAccessPolicyAsync(BlobContainerClient containerClient)
{
    // Remove all stored access policies for the container resource
    await containerClient.SetAccessPolicyAsync();
}

Recursos

Para más información sobre cómo crear una SAS de servicio con la biblioteca cliente de Azure Blob Storage para .NET, vea los recursos siguientes.

Recursos de la biblioteca cliente

Consulte también