Skip to content

Commit

Permalink
Updated SasBuilder to correctly order raw string permissions (Azure#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmcc-msft authored Jul 16, 2020
1 parent 5b08da2 commit 96e4e5f
Show file tree
Hide file tree
Showing 70 changed files with 5,264 additions and 14 deletions.
1 change: 1 addition & 0 deletions sdk/storage/Azure.Storage.Blobs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 12.5.0-preview.6 (Unreleased)
- Fixed bug where BlockBlobClient and PageBlobClient would throw NullReferenceExceptions when using Uri constructor.
- Fixed bug where .WithSnapshot() and .WithVersion() would URL-encode the name of the new clients.
- Updated BlobSasBuilder to correctly order raw string permissions and make the permissions lowercase.

## 12.5.0-preview.5 (2020-07-03)
- Added support for service version 2019-12-12.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,7 @@ public void SetPermissions(Azure.Storage.Sas.BlobSasPermissions permissions) { }
public void SetPermissions(Azure.Storage.Sas.BlobVersionSasPermissions permissions) { }
public void SetPermissions(Azure.Storage.Sas.SnapshotSasPermissions permissions) { }
public void SetPermissions(string rawPermissions) { }
public void SetPermissions(string rawPermissions, bool normalize = false) { }
public Azure.Storage.Sas.BlobSasQueryParameters ToSasQueryParameters(Azure.Storage.Blobs.Models.UserDelegationKey userDelegationKey, string accountName) { throw null; }
public Azure.Storage.Sas.BlobSasQueryParameters ToSasQueryParameters(Azure.Storage.StorageSharedKeyCredential sharedKeyCredential) { throw null; }
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
Expand Down
39 changes: 39 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/Sas/BlobSasBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Security.Cryptography;
using System.Text;
Expand Down Expand Up @@ -202,6 +203,29 @@ public void SetPermissions(BlobVersionSasPermissions permissions)
Permissions = permissions.ToPermissionsString();
}

/// <summary>
/// Sets the permissions for the SAS using a raw permissions string.
/// </summary>
/// <param name="rawPermissions">
/// Raw permissions string for the SAS.
/// </param>
/// <param name="normalize">
/// If the permissions should be validated and correctly ordered.
/// </param>
public void SetPermissions(
string rawPermissions,
bool normalize = default)
{
if (normalize)
{
rawPermissions = SasExtensions.ValidateAndSanitizeRawPermissions(
permissions: rawPermissions,
validPermissionsInOrder: s_validPermissionsInOrder);
}

SetPermissions(rawPermissions);
}

/// <summary>
/// Sets the permissions for the SAS using a raw permissions string.
/// </summary>
Expand All @@ -211,6 +235,21 @@ public void SetPermissions(string rawPermissions)
Permissions = rawPermissions;
}

private static readonly List<char> s_validPermissionsInOrder = new List<char>
{
Constants.Sas.Permissions.Read,
Constants.Sas.Permissions.Add,
Constants.Sas.Permissions.Create,
Constants.Sas.Permissions.Write,
Constants.Sas.Permissions.Delete,
Constants.Sas.Permissions.DeleteBlobVersion,
Constants.Sas.Permissions.List,
Constants.Sas.Permissions.Tag,
Constants.Sas.Permissions.Update,
Constants.Sas.Permissions.Process,
Constants.Sas.Permissions.FilterByTags,
};

/// <summary>
/// Use an account's <see cref="StorageSharedKeyCredential"/> to sign this
/// shared access signature values to produce the proper SAS query
Expand Down
109 changes: 109 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/BlobSasBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// Licensed under the MIT License.

using System;
using System.Net;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Azure.Core.TestFramework;
using Azure.Storage.Blobs.Models;
using Azure.Storage.Sas;
using Azure.Storage.Test;
Expand Down Expand Up @@ -259,6 +262,112 @@ public void ToSasQueryParameters_IdentifierTest()
Assert.AreEqual(constants.Sas.Version, sasQueryParameters.Version);
}

[Test]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2019_12_12)]
[TestCase("FTPUCALXDWR")]
[TestCase("rwdxlacuptf")]
public async Task AccountPermissionsRawPermissions(string permissionsString)
{
// Arrange
await using DisposingContainer test = await GetTestContainerAsync();

AccountSasBuilder accountSasBuilder = new AccountSasBuilder
{
StartsOn = Recording.UtcNow.AddHours(-1),
ExpiresOn = Recording.UtcNow.AddHours(1),
Services = AccountSasServices.Blobs,
ResourceTypes = AccountSasResourceTypes.All
};

accountSasBuilder.SetPermissions(permissionsString);

StorageSharedKeyCredential sharedKeyCredential = new StorageSharedKeyCredential(TestConfigDefault.AccountName, TestConfigDefault.AccountKey);

Uri uri = new Uri($"{test.Container.Uri}?{accountSasBuilder.ToSasQueryParameters(sharedKeyCredential)}");

BlobContainerClient sasContainerClient = new BlobContainerClient(uri, GetOptions());

// Act
await sasContainerClient.GetPropertiesAsync();
}

[Test]
public async Task AccountPermissionsRawPermissions_InvalidPermission()
{
// Arrange
await using DisposingContainer test = await GetTestContainerAsync();

AccountSasBuilder accountSasBuilder = new AccountSasBuilder
{
StartsOn = Recording.UtcNow.AddHours(-1),
ExpiresOn = Recording.UtcNow.AddHours(1),
Services = AccountSasServices.Blobs,
ResourceTypes = AccountSasResourceTypes.All
};

// Act
TestHelper.AssertExpectedException(
() => accountSasBuilder.SetPermissions("werteyfg"),
new ArgumentException("e is not a valid SAS permission"));
}

[Test]
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2019_12_12)]
[TestCase("TLXDWCAR")]
[TestCase("racwdxlt")]
public async Task ContainerPermissionsRawPermissions(string permissionsString)
{
// Arrange
await using DisposingContainer test = await GetTestContainerAsync();

BlobSasBuilder blobSasBuilder = new BlobSasBuilder
{
StartsOn = Recording.UtcNow.AddHours(-1),
ExpiresOn = Recording.UtcNow.AddHours(1),
BlobContainerName = test.Container.Name
};

blobSasBuilder.SetPermissions(
rawPermissions: permissionsString,
normalize: true);

StorageSharedKeyCredential sharedKeyCredential = new StorageSharedKeyCredential(TestConfigDefault.AccountName, TestConfigDefault.AccountKey);

BlobUriBuilder blobUriBuilder = new BlobUriBuilder(test.Container.Uri)
{
Sas = blobSasBuilder.ToSasQueryParameters(sharedKeyCredential)
};

BlobContainerClient sasContainerClient = new BlobContainerClient(blobUriBuilder.ToUri(), GetOptions());

// Act
await foreach (BlobItem blobItem in sasContainerClient.GetBlobsAsync())
{
// Just make sure the call succeeds.
}
}

[Test]
public async Task ContainerPermissionsRawPermissions_Invalid()
{
// Arrange
await using DisposingContainer test = await GetTestContainerAsync();

BlobSasBuilder blobSasBuilder = new BlobSasBuilder
{
StartsOn = Recording.UtcNow.AddHours(-1),
ExpiresOn = Recording.UtcNow.AddHours(1),
BlobContainerName = test.Container.Name
};

// Act
TestHelper.AssertExpectedException(
() => blobSasBuilder.SetPermissions(
rawPermissions: "ptsdfsd",
normalize: true),
new ArgumentException("s is not a valid SAS permission"));
}

private BlobSasBuilder BuildBlobSasBuilder(bool includeBlob, bool includeSnapshot, string containerName, string blobName, TestConstants constants)
{
var builder = new BlobSasBuilder
Expand Down
18 changes: 7 additions & 11 deletions sdk/storage/Azure.Storage.Blobs/tests/BlobTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -446,19 +446,15 @@ public BlobSasQueryParameters GetNewBlobServiceSasCredentialsSnapshot(string con
return builder.ToSasQueryParameters(sharedKeyCredentials ?? GetNewSharedKeyCredentials());
}

private static string ToSasVersion(BlobClientOptions.ServiceVersion serviceVersion)
public static string ToSasVersion(BlobClientOptions.ServiceVersion serviceVersion)
{
switch (serviceVersion)
return serviceVersion switch
{
case BlobClientOptions.ServiceVersion.V2019_02_02:
return "2019-02-02";
case BlobClientOptions.ServiceVersion.V2019_07_07:
return "2019-07-07";
case BlobClientOptions.ServiceVersion.V2019_12_12:
return "2019-12-12";
default:
throw new ArgumentException("Invalid service version");
}
BlobClientOptions.ServiceVersion.V2019_02_02 => "2019-02-02",
BlobClientOptions.ServiceVersion.V2019_07_07 => "2019-07-07",
BlobClientOptions.ServiceVersion.V2019_12_12 => "2019-12-12",
_ => throw new ArgumentException("Invalid service version"),
};
}

public async Task<PageBlobClient> CreatePageBlobClientAsync(BlobContainerClient container, long size)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 96e4e5f

Please sign in to comment.