Skip to content

Commit

Permalink
[Storage] SAS Credential in Storage. (Azure#17646)
Browse files Browse the repository at this point in the history
* Add AzureSasCredential

* corner case.

* api.

* core as project ref (todo undo this)

* first client.

* hack azure core in webjobs for now.

* api.

* constructors.

* blob tests.

* datalake tests.

* share tests + take out sas on share and service clients as there isn't much APIs that would work with sas there.

* queues tests.

* well that works. nvm.

* remarks.

* error message.

* predicate shouldn't be optional.

* post-merge tweaks.

* message about right UriBuilder.

* added uri validation.

* changelog.

* user delegation sas change.

* batch.

* this test doesn't work well in playback mode.

* pr feedback.

* comments.

* validation.

* undo project references workaround.

* undo webjobs project ref workaround.
  • Loading branch information
kasobol-msft authored and annelo-msft committed Feb 17, 2021
1 parent f72766f commit 1d0b1e3
Show file tree
Hide file tree
Showing 125 changed files with 7,795 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,24 @@ public async Task Batch_SasUri_NotOwner()
Assert.AreEqual(403, ex.Status);
}

[Test]
[LiveOnly]
public async Task Batch_AzureSasCredential()
{
// Create a container using SAS for Auth
await using DisposingContainer test = await GetTestContainerAsync();

var serviceClient = GetServiceClient_SharedKey();
var sas = GetAccountSasCredentials().SasToken;
var sasServiceClient = InstrumentClient(new BlobServiceClient(serviceClient.Uri, new AzureSasCredential(sas), GetOptions()));
await using TestScenario scenario = Scenario(sasServiceClient);
Uri[] blobs = await scenario.CreateBlobUrisAsync(test.Container, 2);
BlobBatchClient client = scenario.GetBlobBatchClient();
Response[] responses = await client.DeleteBlobsAsync(blobs);

scenario.AssertStatus(202, responses);
}

// TODO: Add a requirement that one of the test tenants is in a
// different account so we can verify batch requests fail across
// multiple storage accounts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public partial class BlobChangeFeedClient
protected BlobChangeFeedClient() { }
public BlobChangeFeedClient(string connectionString) { }
public BlobChangeFeedClient(string connectionString, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlobChangeFeedClient(System.Uri serviceUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobChangeFeedClient(System.Uri serviceUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobChangeFeedClient(System.Uri serviceUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobChangeFeedClient(System.Uri serviceUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,31 @@ public BlobChangeFeedClient(Uri serviceUri, StorageSharedKeyCredential credentia
_blobServiceClient = new BlobServiceClient(serviceUri, credential, options);
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobChangeFeedClient"/>
/// class.
/// </summary>
/// <param name="serviceUri">
/// A <see cref="Uri"/> referencing the blob service.
/// This is likely to be similar to "https://{account_name}.blob.core.windows.net".
/// Must not contain shared access signature, which should be passed in the second parameter.
/// </param>
/// <param name="credential">
/// The shared access signature credential used to sign requests.
/// </param>
/// <param name="options">
/// Optional client options that define the transport pipeline
/// policies for authentication, retries, etc., that are applied to
/// every request.
/// </param>
/// <remarks>
/// This constructor should only be used when shared access signature needs to be updated during lifespan of this client.
/// </remarks>
public BlobChangeFeedClient(Uri serviceUri, AzureSasCredential credential, BlobClientOptions options = default)
{
_blobServiceClient = new BlobServiceClient(serviceUri, credential, options);
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobChangeFeedClient"/>
/// class.
Expand Down
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.8.0-beta.2 (Unreleased)
- Fixed bug where the Stream returned by BlobBaseClient.OpenRead() would return a different Length after calls to Seek().
- Fixed bug where BlobBaseClient.Exists() did not function correctly for blob encrypted with Customer Provided Key or Encryption Scope.
- Added support for AzureSasCredential. That allows SAS rotation for long living clients.

## 12.8.0-beta.1 (2020-12-07)
- Added support for service version 2020-04-08.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ public partial class BlobClient : Azure.Storage.Blobs.Specialized.BlobBaseClient
protected BlobClient() { }
public BlobClient(string connectionString, string blobContainerName, string blobName) { }
public BlobClient(string connectionString, string blobContainerName, string blobName, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlobClient(System.Uri blobUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobClient(System.Uri blobUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobClient(System.Uri blobUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -60,6 +61,7 @@ public partial class BlobContainerClient
protected BlobContainerClient() { }
public BlobContainerClient(string connectionString, string blobContainerName) { }
public BlobContainerClient(string connectionString, string blobContainerName, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlobContainerClient(System.Uri blobContainerUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobContainerClient(System.Uri blobContainerUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobContainerClient(System.Uri blobContainerUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobContainerClient(System.Uri blobContainerUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -119,6 +121,7 @@ public partial class BlobServiceClient
protected BlobServiceClient() { }
public BlobServiceClient(string connectionString) { }
public BlobServiceClient(string connectionString, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlobServiceClient(System.Uri serviceUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobServiceClient(System.Uri serviceUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobServiceClient(System.Uri serviceUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobServiceClient(System.Uri serviceUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -1224,6 +1227,7 @@ public partial class AppendBlobClient : Azure.Storage.Blobs.Specialized.BlobBase
protected AppendBlobClient() { }
public AppendBlobClient(string connectionString, string blobContainerName, string blobName) { }
public AppendBlobClient(string connectionString, string blobContainerName, string blobName, Azure.Storage.Blobs.BlobClientOptions options) { }
public AppendBlobClient(System.Uri blobUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public AppendBlobClient(System.Uri blobUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public AppendBlobClient(System.Uri blobUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public AppendBlobClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -1257,6 +1261,7 @@ public partial class BlobBaseClient
protected BlobBaseClient() { }
public BlobBaseClient(string connectionString, string blobContainerName, string blobName) { }
public BlobBaseClient(string connectionString, string blobContainerName, string blobName, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlobBaseClient(System.Uri blobUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobBaseClient(System.Uri blobUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobBaseClient(System.Uri blobUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlobBaseClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -1361,6 +1366,7 @@ public partial class BlockBlobClient : Azure.Storage.Blobs.Specialized.BlobBaseC
protected BlockBlobClient() { }
public BlockBlobClient(string connectionString, string containerName, string blobName) { }
public BlockBlobClient(string connectionString, string blobContainerName, string blobName, Azure.Storage.Blobs.BlobClientOptions options) { }
public BlockBlobClient(System.Uri blobUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlockBlobClient(System.Uri blobUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlockBlobClient(System.Uri blobUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public BlockBlobClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down Expand Up @@ -1407,6 +1413,7 @@ public partial class PageBlobClient : Azure.Storage.Blobs.Specialized.BlobBaseCl
protected PageBlobClient() { }
public PageBlobClient(string connectionString, string blobContainerName, string blobName) { }
public PageBlobClient(string connectionString, string blobContainerName, string blobName, Azure.Storage.Blobs.BlobClientOptions options) { }
public PageBlobClient(System.Uri blobUri, Azure.AzureSasCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public PageBlobClient(System.Uri blobUri, Azure.Core.TokenCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public PageBlobClient(System.Uri blobUri, Azure.Storage.Blobs.BlobClientOptions options = null) { }
public PageBlobClient(System.Uri blobUri, Azure.Storage.StorageSharedKeyCredential credential, Azure.Storage.Blobs.BlobClientOptions options = null) { }
Expand Down
28 changes: 28 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/AppendBlobClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,34 @@ public AppendBlobClient(Uri blobUri, StorageSharedKeyCredential credential, Blob
AssertNoClientSideEncryption(options);
}

/// <summary>
/// Initializes a new instance of the <see cref="AppendBlobClient"/>
/// class.
/// </summary>
/// <param name="blobUri">
/// A <see cref="Uri"/> referencing the append blob that includes the
/// name of the account, the name of the container, and the name of
/// the blob.
/// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
/// Must not contain shared access signature, which should be passed in the second parameter.
/// </param>
/// <param name="credential">
/// The shared access signature credential used to sign requests.
/// </param>
/// <param name="options">
/// Optional client options that define the transport pipeline
/// policies for authentication, retries, etc., that are applied to
/// every request.
/// </param>
/// <remarks>
/// This constructor should only be used when shared access signature needs to be updated during lifespan of this client.
/// </remarks>
public AppendBlobClient(Uri blobUri, AzureSasCredential credential, BlobClientOptions options = default)
: base(blobUri, credential, options)
{
AssertNoClientSideEncryption(options);
}

/// <summary>
/// Initializes a new instance of the <see cref="AppendBlobClient"/>
/// class.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Azure.Storage.Common\src\Azure.Storage.Common.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="$(AzureCoreSharedSources)Argument.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
<Compile Include="$(AzureCoreSharedSources)AzureResourceProviderNamespaceAttribute.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
<Compile Include="$(AzureCoreSharedSources)AzureSasCredentialSynchronousPolicy.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
<Compile Include="$(AzureCoreSharedSources)OperationHelpers.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
<Compile Include="$(AzureCoreSharedSources)RetriableStream.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
<Compile Include="$(AzureCoreSharedSources)ArrayBufferWriter.cs" Link="Shared\Core\%(RecursiveDir)\%(Filename)%(Extension)" />
Expand Down
28 changes: 28 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,33 @@ public BlobBaseClient(Uri blobUri, StorageSharedKeyCredential credential, BlobCl
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobBaseClient"/>
/// class.
/// </summary>
/// <param name="blobUri">
/// A <see cref="Uri"/> referencing the blob that includes the
/// name of the account, the name of the container, and the name of
/// the blob.
/// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
/// Must not contain shared access signature, which should be passed in the second parameter.
/// </param>
/// <param name="credential">
/// The shared access signature credential used to sign requests.
/// </param>
/// <param name="options">
/// Optional client options that define the transport pipeline
/// policies for authentication, retries, etc., that are applied to
/// every request.
/// </param>
/// <remarks>
/// This constructor should only be used when shared access signature needs to be updated during lifespan of this client.
/// </remarks>
public BlobBaseClient(Uri blobUri, AzureSasCredential credential, BlobClientOptions options = default)
: this(blobUri, credential.AsPolicy<BlobUriBuilder>(blobUri), options, null)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobBaseClient"/>
/// class.
Expand Down Expand Up @@ -352,6 +379,7 @@ internal BlobBaseClient(
BlobClientOptions options,
StorageSharedKeyCredential storageSharedKeyCredential)
{
Argument.AssertNotNull(blobUri, nameof(blobUri));
options ??= new BlobClientOptions();
_uri = blobUri;
if (!string.IsNullOrEmpty(blobUri.Query))
Expand Down
27 changes: 27 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/BlobClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,33 @@ public BlobClient(Uri blobUri, StorageSharedKeyCredential credential, BlobClient
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobClient"/>
/// class.
/// </summary>
/// <param name="blobUri">
/// A <see cref="Uri"/> referencing the blob that includes the
/// name of the account, the name of the container, and the name of
/// the blob.
/// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}/{blob_name}".
/// Must not contain shared access signature, which should be passed in the second parameter.
/// </param>
/// <param name="credential">
/// The shared access signature credential used to sign requests.
/// </param>
/// <param name="options">
/// Optional client options that define the transport pipeline
/// policies for authentication, retries, etc., that are applied to
/// every request.
/// </param>
/// <remarks>
/// This constructor should only be used when shared access signature needs to be updated during lifespan of this client.
/// </remarks>
public BlobClient(Uri blobUri, AzureSasCredential credential, BlobClientOptions options = default)
: base(blobUri, credential, options)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobClient"/>
/// class.
Expand Down
27 changes: 27 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/src/BlobContainerClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,32 @@ public BlobContainerClient(Uri blobContainerUri, StorageSharedKeyCredential cred
_storageSharedKeyCredential = credential;
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobContainerClient"/>
/// class.
/// </summary>
/// <param name="blobContainerUri">
/// A <see cref="Uri"/> referencing the blob container that includes the
/// name of the account and the name of the container.
/// This is likely to be similar to "https://{account_name}.blob.core.windows.net/{container_name}".
/// Must not contain shared access signature, which should be passed in the second parameter.
/// </param>
/// <param name="credential">
/// The shared access signature credential used to sign requests.
/// </param>
/// <param name="options">
/// Optional client options that define the transport pipeline
/// policies for authentication, retries, etc., that are applied to
/// every request.
/// </param>
/// <remarks>
/// This constructor should only be used when shared access signature needs to be updated during lifespan of this client.
/// </remarks>
public BlobContainerClient(Uri blobContainerUri, AzureSasCredential credential, BlobClientOptions options = default)
: this(blobContainerUri, credential.AsPolicy<BlobUriBuilder>(blobContainerUri), options)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="BlobContainerClient"/>
/// class.
Expand Down Expand Up @@ -317,6 +343,7 @@ public BlobContainerClient(Uri blobContainerUri, TokenCredential credential, Blo
/// </param>
internal BlobContainerClient(Uri blobContainerUri, HttpPipelinePolicy authentication, BlobClientOptions options)
{
Argument.AssertNotNull(blobContainerUri, nameof(blobContainerUri));
_uri = blobContainerUri;
options ??= new BlobClientOptions();
_pipeline = options.Build(authentication);
Expand Down
Loading

0 comments on commit 1d0b1e3

Please sign in to comment.