Skip to content

Commit 368f65e

Browse files
authored
Fixed bug where BlobBaseClient.Exists() did not function correctly for blob encrypted with Customer Provided Key or Encryption Scope. (Azure#17599)
1 parent 13aff10 commit 368f65e

File tree

7 files changed

+672
-11
lines changed

7 files changed

+672
-11
lines changed

sdk/storage/Azure.Storage.Blobs/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## 12.8.0-beta.2 (Unreleased)
44
- Fixed bug where the Stream returned by BlobBaseClient.OpenRead() would return a different Length after calls to Seek().
5+
- Fixed bug where BlobBaseClient.Exists() did not function correctly for blob encrypted with Customer Provided Key or Encryption Scope.
56

67
## 12.8.0-beta.1 (2020-12-07)
78
- Added support for service version 2020-04-08.

sdk/storage/Azure.Storage.Blobs/src/BlobBaseClient.cs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2911,14 +2911,11 @@ private async Task<Response<bool>> ExistsInternal(
29112911

29122912
try
29132913
{
2914-
Response<BlobPropertiesInternal> response = await BlobRestClient.Blob.GetPropertiesAsync(
2915-
ClientDiagnostics,
2916-
Pipeline,
2917-
Uri,
2918-
version: Version.ToVersionString(),
2914+
Response<BlobProperties> response = await GetPropertiesInternal(
2915+
conditions: default,
29192916
async: async,
2920-
operationName: $"{nameof(BlobBaseClient)}.{nameof(Exists)}",
2921-
cancellationToken: cancellationToken)
2917+
cancellationToken: cancellationToken,
2918+
$"{nameof(BlobBaseClient)}.{nameof(Exists)}")
29222919
.ConfigureAwait(false);
29232920

29242921
return Response.FromValue(true, response.GetRawResponse());
@@ -3084,7 +3081,7 @@ public virtual Response<BlobProperties> GetProperties(
30843081
CancellationToken cancellationToken = default) =>
30853082
GetPropertiesInternal(
30863083
conditions,
3087-
false, // async
3084+
async: false,
30883085
cancellationToken)
30893086
.EnsureCompleted();
30903087

@@ -3119,7 +3116,7 @@ public virtual async Task<Response<BlobProperties>> GetPropertiesAsync(
31193116
CancellationToken cancellationToken = default) =>
31203117
await GetPropertiesInternal(
31213118
conditions,
3122-
true, // async
3119+
async: true,
31233120
cancellationToken)
31243121
.ConfigureAwait(false);
31253122

@@ -3144,6 +3141,9 @@ await GetPropertiesInternal(
31443141
/// Optional <see cref="CancellationToken"/> to propagate
31453142
/// notifications that the operation should be cancelled.
31463143
/// </param>
3144+
/// <param name="operationName">
3145+
/// The name of the calling operation.
3146+
/// </param>
31473147
/// <returns>
31483148
/// A <see cref="Response{BlobProperties}"/> describing the
31493149
/// blob's properties.
@@ -3155,8 +3155,10 @@ await GetPropertiesInternal(
31553155
internal async Task<Response<BlobProperties>> GetPropertiesInternal(
31563156
BlobRequestConditions conditions,
31573157
bool async,
3158-
CancellationToken cancellationToken)
3158+
CancellationToken cancellationToken,
3159+
string operationName = default)
31593160
{
3161+
operationName ??= $"{nameof(BlobBaseClient)}.{nameof(GetProperties)}";
31603162
using (Pipeline.BeginLoggingScope(nameof(BlobBaseClient)))
31613163
{
31623164
Pipeline.LogMethodEnter(
@@ -3181,7 +3183,7 @@ internal async Task<Response<BlobProperties>> GetPropertiesInternal(
31813183
ifNoneMatch: conditions?.IfNoneMatch,
31823184
ifTags: conditions?.TagConditions,
31833185
async: async,
3184-
operationName: "BlobBaseClient.GetProperties",
3186+
operationName: operationName,
31853187
cancellationToken: cancellationToken)
31863188
.ConfigureAwait(false);
31873189

sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3186,6 +3186,42 @@ public async Task ExistsAsync_NotExists()
31863186
Assert.IsFalse(response.Value);
31873187
}
31883188

3189+
[Test]
3190+
public async Task ExistsAsync_Exists_CPK()
3191+
{
3192+
await using DisposingContainer test = await GetTestContainerAsync();
3193+
3194+
// Arrange
3195+
AppendBlobClient blob = InstrumentClient(test.Container.GetAppendBlobClient(GetNewBlobName()));
3196+
CustomerProvidedKey customerProvidedKey = GetCustomerProvidedKey();
3197+
blob = InstrumentClient(blob.WithCustomerProvidedKey(customerProvidedKey));
3198+
await blob.CreateIfNotExistsAsync();
3199+
3200+
// Act
3201+
Response<bool> response = await blob.ExistsAsync();
3202+
3203+
// Assert
3204+
Assert.IsTrue(response.Value);
3205+
}
3206+
3207+
[Test]
3208+
[ServiceVersion(Min = BlobClientOptions.ServiceVersion.V2019_07_07)]
3209+
public async Task ExistsAsync_Exists_EncryptionScope()
3210+
{
3211+
await using DisposingContainer test = await GetTestContainerAsync();
3212+
3213+
// Arrange
3214+
AppendBlobClient blob = InstrumentClient(test.Container.GetAppendBlobClient(GetNewBlobName()));
3215+
blob = InstrumentClient(blob.WithEncryptionScope(TestConfigDefault.EncryptionScope));
3216+
await blob.CreateIfNotExistsAsync();
3217+
3218+
// Act
3219+
Response<bool> response = await blob.ExistsAsync();
3220+
3221+
// Assert
3222+
Assert.IsTrue(response.Value);
3223+
}
3224+
31893225
[Test]
31903226
public async Task ExistsAsync_ContainerNotExists()
31913227
{

sdk/storage/Azure.Storage.Blobs/tests/SessionRecords/BlobBaseClientTests/ExistsAsync_Exists_CPK.json

Lines changed: 158 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)