Question

Difficulty: Very hardShared Access Signatures and Token-based Storage Security

You are developing a secure C# application using the `Azure.Storage.Blobs` SDK. The application must generate a Shared Access Signature (SAS) token that allows external clients to upload a single PDF file named `confidential.pdf` to a container named `secure-docs` in an Azure Storage account named `corpdata`.

Your application must comply with the following security and operational constraints:
- Authentication: Storage account access keys must not be used, stored, or referenced by the application. You must authenticate using the application's system-assigned managed identity.
- Permissions: The token must grant only write permissions to the specific blob. No read, delete, or list permissions should be granted.
- Protocol: Connections must be restricted to HTTPS only.
- Network Constraints: The token must only be usable from the client's public IP address `198.51.100.72198.51.100.72`.
- Validity: The token must be valid for exactly `3030` minutes from generation.
- Reliability: The token must be usable immediately upon receipt by the client, without failing due to potential clock synchronization differences (clock skew) between servers.

Which of the following C# code segments should you use to generate the SAS token?

  1. var credential = new DefaultAzureCredential();
    var blobServiceClient = new BlobServiceClient(
    new Uri("https://corpdata.blob.core.windows.net"), credential);

    UserDelegationKey delegationKey = await blobServiceClient.GetUserDelegationKeyAsync(
    startsOn: DateTimeOffset.UtcNow.AddMinutes(-15),
    expiresOn: DateTimeOffset.UtcNow.AddMinutes(45)
    );

    var sasBuilder = new BlobSasBuilder()
    {
    BlobContainerName = "secure-docs",
    BlobName = "confidential.pdf",
    Resource = "b",
    StartsOn = DateTimeOffset.UtcNow.AddMinutes(-15),
    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(30),
    Protocol = SasProtocol.Https,
    IPRange = SasIPRange.Parse("198.51.100.72")
    };
    sasBuilder.SetPermissions(BlobSasPermissions.Write);

    string sasToken = sasBuilder.ToSasQueryParameters(delegationKey, "corpdata").ToString();
    Answer
  2. B
    var sharedKeyCredential = new StorageSharedKeyCredential("corpdata", "AccountKeyString");
    var blobServiceClient = new BlobServiceClient(
    new Uri("https://corpdata.blob.core.windows.net"), sharedKeyCredential);

    var sasBuilder = new BlobSasBuilder()
    {
    BlobContainerName = "secure-docs",
    BlobName = "confidential.pdf",
    Resource = "b",
    StartsOn = DateTimeOffset.UtcNow.AddMinutes(-15),
    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(30),
    Protocol = SasProtocol.Https,
    IPRange = SasIPRange.Parse("198.51.100.72")
    };
    sasBuilder.SetPermissions(BlobSasPermissions.Write);

    string sasToken = sasBuilder.ToSasQueryParameters(sharedKeyCredential).ToString();
  3. C
    var credential = new DefaultAzureCredential();
    var blobServiceClient = new BlobServiceClient(
    new Uri("https://corpdata.blob.core.windows.net"), credential);

    UserDelegationKey delegationKey = await blobServiceClient.GetUserDelegationKeyAsync(
    startsOn: DateTimeOffset.UtcNow,
    expiresOn: DateTimeOffset.UtcNow.AddMinutes(30)
    );

    var sasBuilder = new BlobSasBuilder()
    {
    BlobContainerName = "secure-docs",
    BlobName = "confidential.pdf",
    Resource = "b",
    StartsOn = DateTimeOffset.UtcNow,
    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(30),
    Protocol = SasProtocol.Https,
    IPRange = SasIPRange.Parse("198.51.100.72")
    };
    sasBuilder.SetPermissions(BlobSasPermissions.Write);

    string sasToken = sasBuilder.ToSasQueryParameters(delegationKey, "corpdata").ToString();
  4. D
    var credential = new DefaultAzureCredential();
    var blobServiceClient = new BlobServiceClient(
    new Uri("https://corpdata.blob.core.windows.net"), credential);

    UserDelegationKey delegationKey = await blobServiceClient.GetUserDelegationKeyAsync(
    startsOn: DateTimeOffset.UtcNow.AddMinutes(-15),
    expiresOn: DateTimeOffset.UtcNow.AddMinutes(45)
    );

    var sasBuilder = new BlobSasBuilder()
    {
    BlobContainerName = "secure-docs",
    Resource = "c",
    StartsOn = DateTimeOffset.UtcNow.AddMinutes(-15),
    ExpiresOn = DateTimeOffset.UtcNow.AddMinutes(30),
    Protocol = SasProtocol.HttpsAndHttp,
    IPRange = SasIPRange.Parse("198.51.100.72")
    };
    sasBuilder.SetPermissions(BlobSasPermissions.Write);

    string sasToken = sasBuilder.ToSasQueryParameters(delegationKey, "corpdata").ToString();

Answer

The code segment that uses DefaultAzureCredential to retrieve a UserDelegationKey, sets the start time in the past to allow for clock skew, restricts the protocol to HTTPS, limits the scope to the specific blob resource, and signs the token with the delegation key.
The correct code segment uses DefaultAzureCredential to obtain a UserDelegationKey from Azure Active Directory, complying with the requirement to avoid account keys. It sets the scope specifically to the blob resource by assigning Resource to 'b' and specifying the BlobName. It handles clock skew by setting the start time to 15 minutes in the past, ensures HTTPS-only connections, and limits access to the specified client IP range.

Step-by-Step Solution

1
Identify the authentication requirement.
Managed Identity authentication must be used.
Storage account access keys are forbidden by the security policy.
2
Select the correct SAS type.
User Delegation SAS.
A User Delegation SAS is secured using Azure Active Directory credentials rather than storage account keys.
3
Configure the resource scope.
Set BlobName to 'confidential.pdf' and Resource to 'b'.
Least-privilege requires limiting access to the specific blob, not the entire container.
4
Configure protocol, network, and clock skew properties.
Set Protocol to Https, IPRange to the client's IP, and StartsOn with a negative offset.
Connections must be HTTPS-only, restricted to the client's IP, and a negative offset on StartsOn allows for clock skew so the token is usable immediately.
5
Sign and generate the SAS token.
Call ToSasQueryParameters passing the UserDelegationKey.
The token must be signed using the obtained delegation key to be authorized.

Key Concept

Shared Access Signatures (SAS) allow for secure, delegated access to Azure Storage resources. A User Delegation SAS is secured using Azure AD credentials. For security and reliability, SAS tokens must implement least-privilege, enforce HTTPS, restrict IP ranges, and subtract a brief duration from the start time to mitigate clock skew issues.
Rate this question