Skip to content

Commit

Permalink
Fixed storage bug where SAS content headers were not URL-encoded (#9290)
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmcc-msft authored Jan 3, 2020
1 parent 382ec5e commit c7bf0cc
Show file tree
Hide file tree
Showing 4 changed files with 371 additions and 5 deletions.
58 changes: 58 additions & 0 deletions sdk/storage/Azure.Storage.Blobs/tests/BlobBaseClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
Expand Down Expand Up @@ -1457,6 +1458,63 @@ public async Task GetPropertiesAsync_BlobSAS()

}

[Test]
public async Task GetPropertiesAsync_BlobSasWithContentHeaders()
{
var containerName = GetNewContainerName();
var blobName = GetNewBlobName();
await using DisposingContainer test = await GetTestContainerAsync(containerName: containerName);

// Arrange
BlobBaseClient blob = await GetNewBlobClient(test.Container, blobName);

BlobSasBuilder blobSasBuilder = new BlobSasBuilder
{
BlobContainerName = containerName,
BlobName = blobName,
Protocol = SasProtocol.None,
StartsOn = Recording.UtcNow.AddHours(-1),
ExpiresOn = Recording.UtcNow.AddHours(1),
IPRange = new SasIPRange(IPAddress.None, IPAddress.None),
CacheControl = "\\cache control?",
ContentDisposition = "\\content disposition?",
ContentEncoding = "\\content encoding?",
ContentLanguage = "\\content language?",
ContentType = "\\content type?"
};
blobSasBuilder.SetPermissions(
BlobSasPermissions.All);

BlobSasQueryParameters blobSasQueryParameters = blobSasBuilder.ToSasQueryParameters(GetNewSharedKeyCredentials());

// Act
string queryParametersString = blobSasQueryParameters.ToString();

// Assert
Assert.IsTrue(queryParametersString.Contains("rscc=%5Ccache+control%3F"));
Assert.IsTrue(queryParametersString.Contains("rscd=%5Ccontent+disposition%3F"));
Assert.IsTrue(queryParametersString.Contains("rsce=%5Ccontent+encoding%3F"));
Assert.IsTrue(queryParametersString.Contains("rscl=%5Ccontent+language%3F"));
Assert.IsTrue(queryParametersString.Contains("rsct=%5Ccontent+type%3F"));

BlobUriBuilder blobUriBuilder = new BlobUriBuilder(new Uri(TestConfigDefault.BlobServiceEndpoint));
blobUriBuilder.BlobName = blobName;
blobUriBuilder.BlobContainerName = containerName;
blobUriBuilder.Sas = blobSasQueryParameters;
BlockBlobClient sasBlob = InstrumentClient(new BlockBlobClient(blobUriBuilder.ToUri(), GetOptions()));
// Act
Response<BlobProperties> response = await sasBlob.GetPropertiesAsync();

// Assert
Assert.IsNotNull(response.GetRawResponse().Headers.RequestId);

Assert.IsTrue(sasBlob.Uri.Query.Contains("rscc=%5Ccache+control%3F"));
Assert.IsTrue(sasBlob.Uri.Query.Contains("rscd=%5Ccontent+disposition%3F"));
Assert.IsTrue(sasBlob.Uri.Query.Contains("rsce=%5Ccontent+encoding%3F"));
Assert.IsTrue(sasBlob.Uri.Query.Contains("rscl=%5Ccontent+language%3F"));
Assert.IsTrue(sasBlob.Uri.Query.Contains("rsct=%5Ccontent+type%3F"));
}

[Test]
public async Task GetPropertiesAsync_BlobIdentitySAS()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"Entries": [
{
"RequestUri": "http://seanstagetest.blob.core.windows.net/test-container-affc2cd9-cee4-869a-cb2b-9a80cb58e54d?restype=container",
"RequestMethod": "PUT",
"RequestHeaders": {
"Authorization": "Sanitized",
"traceparent": "00-d088e64ce66dac43abca56d2e1811f30-31f28b0b1e499c48-00",
"User-Agent": [
"azsdk-net-Storage.Blobs/12.1.0-dev.20200103.1\u002B0e0c22e672bc86f72c031a4e0ca3ff7881fe7bfe",
"(.NET Core 4.6.28207.04; Microsoft Windows 10.0.18363 )"
],
"x-ms-blob-public-access": "container",
"x-ms-client-request-id": "a040aa48-17e8-da54-fa49-9e1a38b88c89",
"x-ms-date": "Fri, 03 Jan 2020 18:29:28 GMT",
"x-ms-return-client-request-id": "true",
"x-ms-version": "2019-02-02"
},
"RequestBody": null,
"StatusCode": 201,
"ResponseHeaders": {
"Content-Length": "0",
"Date": "Fri, 03 Jan 2020 18:29:27 GMT",
"ETag": "\u00220x8D7907ADE3E8B94\u0022",
"Last-Modified": "Fri, 03 Jan 2020 18:29:28 GMT",
"Server": [
"Windows-Azure-Blob/1.0",
"Microsoft-HTTPAPI/2.0"
],
"x-ms-client-request-id": "a040aa48-17e8-da54-fa49-9e1a38b88c89",
"x-ms-request-id": "7b269c76-401e-0038-6963-c236fb000000",
"x-ms-version": "2019-02-02"
},
"ResponseBody": []
},
{
"RequestUri": "http://seanstagetest.blob.core.windows.net/test-container-affc2cd9-cee4-869a-cb2b-9a80cb58e54d/test-blob-8adc09f5-fead-b331-11ca-96e2f9421fc7",
"RequestMethod": "PUT",
"RequestHeaders": {
"Authorization": "Sanitized",
"Content-Length": "1024",
"traceparent": "00-fa96bbaf630ffd43aedf6530fcce696a-5c963e576412cd4f-00",
"User-Agent": [
"azsdk-net-Storage.Blobs/12.1.0-dev.20200103.1\u002B0e0c22e672bc86f72c031a4e0ca3ff7881fe7bfe",
"(.NET Core 4.6.28207.04; Microsoft Windows 10.0.18363 )"
],
"x-ms-blob-type": "BlockBlob",
"x-ms-client-request-id": "c0eb7143-0d26-92c0-0626-24a262020018",
"x-ms-date": "Fri, 03 Jan 2020 18:29:28 GMT",
"x-ms-return-client-request-id": "true",
"x-ms-version": "2019-02-02"
},
"RequestBody": "C9NtUMr/d7a/XyVFBdVZnXYXmU8Bf977JrLrjKAvRKvab1CFBgK0STKK4InxDtUl7wGjIB89iIz0cikYE\u002BsVkBp6a5WE1JZ0Y1Addp9VChjcxZyeiySMnObEkJTZmzVGdE9vd6I/oRtrL7zPIBHsn2gRO05PdwT17c6uwEMCmsca1gJP5ZJ1nSSAM1xovXzV1/EsyGDn9/1KeYnUkODYaJT0tEoPnbnVm54pzkOojTBR2ehS1dJnM94EBGsJoQxDqMrHcwkyxTk3Vy3CvSm6ouxZgrf3hpLCjYFrCplNy/mR5SV44RknHxOvGn6lpXW1SmJ/sB9VSyE4BOaHxrug6YszMNgDQcDSMmKjSGsTHOcLtr83zhvaPJkDQNwzn1hYDzHzcnSdsgihrH28sQO2JOj\u002BfBD7aRpvWPQ\u002B/wHjn5MJSzk6IKpzbgO3lSKdHoqWTRz0NCNIXKUWgxmAX7IHvgzqsmbJfAM9iw0MRNT30jpqp7Hl72pvwe6TI5yR8w9Qr9cWsmskzNEYt6kVOxjRH7HfFbcBIs6hevB3NlhnrJj9vJT84R/ORdrfzDfBWobWwgPrsd1YT40IdDd6rZZ4sQoQGH\u002BD1D2RENDcIVWW4CBqoHRUe/q7pWwH9G3nU5hEZhstsEIHU\u002B3FWaAMey44cZMXEAwiJDUQVXISfODQqb03mLo5aTDeY02HjiJZrio\u002Bz4LZ0EOLIkLmHFvP9NcM9a/j1ONz/gdjOK2/m5UStqZI1Kxd99l5rHV3UkzVDm52eplzdtlGy9B7dZiVzIat1Ga0hyAqr/3WaSht\u002B6y6jik/SSD7n0DNAQnc4oFB4\u002BDuyn7mIIZNS8ucnAyw2c8jwOduVoJlsTQm54YXTcx7lYZIfjEt1G2j8f1VXwIzHCc5uCGa041diRhKvzkANv7\u002BIAeGaFqe9ut6y2WFEFIx8spe3pSq4cH46/UY4xQzorv/Vz/7rbPNmsI2IAgn2HnGGM1uolhpUz5FjX1lhhLXRiiqhbgTNkQXkUPSdMG50RN8UctHxABjlgQAtSA2ZxSwXtnffVLAs\u002BKIVxAUl959jLxp6TRHj4EoRu\u002BzEoEk4CkuIRXn2lPBu53ov2zvTv4lgylkzH7fac9XtzZiDKFhY3fm5nXIlbJoqC2XXtAUOPjwjo9XvxOrTrhGkCIcXq78h1v1CGeJXe53\u002ByRRSAr\u002BQn8\u002BcX4SCaNjO5e9gQWPTEp\u002BmtZ0Hi\u002BQZzGh4MTvWgatR02j3eww6n63ks3PzNvo56/Z0q00iiNPrQpNcSjfc\u002BGRDzm37G5dTrBXvIxiwJpVuPkVFYdYeL0pUzDh4nlW2B7sPryhMPtAfIT93c2X7exv97gvyl5ZOJZ8jpg\u002Be2s2AQ==",
"StatusCode": 201,
"ResponseHeaders": {
"Content-Length": "0",
"Content-MD5": "xtQ/QWLUqcBN0QuMbJ5ynw==",
"Date": "Fri, 03 Jan 2020 18:29:28 GMT",
"ETag": "\u00220x8D7907ADE5680BB\u0022",
"Last-Modified": "Fri, 03 Jan 2020 18:29:28 GMT",
"Server": [
"Windows-Azure-Blob/1.0",
"Microsoft-HTTPAPI/2.0"
],
"x-ms-client-request-id": "c0eb7143-0d26-92c0-0626-24a262020018",
"x-ms-content-crc64": "8JhwtDtTaF0=",
"x-ms-request-id": "7b269c79-401e-0038-6a63-c236fb000000",
"x-ms-request-server-encrypted": "true",
"x-ms-version": "2019-02-02"
},
"ResponseBody": []
},
{
"RequestUri": "http://seanstagetest.blob.core.windows.net/test-container-affc2cd9-cee4-869a-cb2b-9a80cb58e54d/test-blob-8adc09f5-fead-b331-11ca-96e2f9421fc7?sv=2019-02-02\u0026st=2020-01-03T17%3A29%3A28Z\u0026se=2020-01-03T19%3A29%3A28Z\u0026sr=b\u0026sp=racwd\u0026rscc=%5Ccache\u002Bcontrol%3F\u0026rscd=%5Ccontent\u002Bdisposition%3F\u0026rsce=%5Ccontent\u002Bencoding%3F\u0026rscl=%5Ccontent\u002Blanguage%3F\u0026rsct=%5Ccontent\u002Btype%3F\u0026sig=Sanitized",
"RequestMethod": "HEAD",
"RequestHeaders": {
"traceparent": "00-5bc968519514c644bdd47d5142d4d2d4-fbe602e8170e064c-00",
"User-Agent": [
"azsdk-net-Storage.Blobs/12.1.0-dev.20200103.1\u002B0e0c22e672bc86f72c031a4e0ca3ff7881fe7bfe",
"(.NET Core 4.6.28207.04; Microsoft Windows 10.0.18363 )"
],
"x-ms-client-request-id": "0afa33fd-767f-d6da-ade3-7bb78fe59bd2",
"x-ms-return-client-request-id": "true",
"x-ms-version": "2019-02-02"
},
"RequestBody": null,
"StatusCode": 200,
"ResponseHeaders": {
"Accept-Ranges": "bytes",
"Cache-Control": "\\cache control?",
"Content-Disposition": "\\content disposition?",
"Content-Encoding": "\\content encoding?",
"Content-Language": "\\content language?",
"Content-Length": "1024",
"Content-MD5": "xtQ/QWLUqcBN0QuMbJ5ynw==",
"Content-Type": "\\content type?",
"Date": "Fri, 03 Jan 2020 18:29:28 GMT",
"ETag": "\u00220x8D7907ADE5680BB\u0022",
"Last-Modified": "Fri, 03 Jan 2020 18:29:28 GMT",
"Server": [
"Windows-Azure-Blob/1.0",
"Microsoft-HTTPAPI/2.0"
],
"Vary": "Origin",
"x-ms-access-tier": "Hot",
"x-ms-access-tier-inferred": "true",
"x-ms-blob-type": "BlockBlob",
"x-ms-client-request-id": "0afa33fd-767f-d6da-ade3-7bb78fe59bd2",
"x-ms-creation-time": "Fri, 03 Jan 2020 18:29:28 GMT",
"x-ms-lease-state": "available",
"x-ms-lease-status": "unlocked",
"x-ms-request-id": "7b269c7a-401e-0038-6b63-c236fb000000",
"x-ms-server-encrypted": "true",
"x-ms-version": "2019-02-02"
},
"ResponseBody": []
},
{
"RequestUri": "http://seanstagetest.blob.core.windows.net/test-container-affc2cd9-cee4-869a-cb2b-9a80cb58e54d?restype=container",
"RequestMethod": "DELETE",
"RequestHeaders": {
"Authorization": "Sanitized",
"traceparent": "00-48af9d1fd3874c47affe57ed91ef455d-18c72f0fd4ce4446-00",
"User-Agent": [
"azsdk-net-Storage.Blobs/12.1.0-dev.20200103.1\u002B0e0c22e672bc86f72c031a4e0ca3ff7881fe7bfe",
"(.NET Core 4.6.28207.04; Microsoft Windows 10.0.18363 )"
],
"x-ms-client-request-id": "2fa4982b-f608-4f99-0112-7c94eedab34c",
"x-ms-date": "Fri, 03 Jan 2020 18:29:28 GMT",
"x-ms-return-client-request-id": "true",
"x-ms-version": "2019-02-02"
},
"RequestBody": null,
"StatusCode": 202,
"ResponseHeaders": {
"Content-Length": "0",
"Date": "Fri, 03 Jan 2020 18:29:28 GMT",
"Server": [
"Windows-Azure-Blob/1.0",
"Microsoft-HTTPAPI/2.0"
],
"x-ms-client-request-id": "2fa4982b-f608-4f99-0112-7c94eedab34c",
"x-ms-request-id": "7b269c7b-401e-0038-6c63-c236fb000000",
"x-ms-version": "2019-02-02"
},
"ResponseBody": []
}
],
"Variables": {
"DateTimeOffsetNow": "2020-01-03T10:29:28.8544288-08:00",
"RandomSeed": "880505182",
"Storage_TestConfigDefault": "ProductionTenant\nseanstagetest\nU2FuaXRpemVk\nhttp://seanstagetest.blob.core.windows.net\nhttp://seanstagetest.file.core.windows.net\nhttp://seanstagetest.queue.core.windows.net\nhttp://seanstagetest.table.core.windows.net\n\n\n\n\nhttp://seanstagetest-secondary.blob.core.windows.net\nhttp://seanstagetest-secondary.file.core.windows.net\nhttp://seanstagetest-secondary.queue.core.windows.net\nhttp://seanstagetest-secondary.table.core.windows.net\n\nSanitized\n\n\nCloud\nBlobEndpoint=http://seanstagetest.blob.core.windows.net/;QueueEndpoint=http://seanstagetest.queue.core.windows.net/;FileEndpoint=http://seanstagetest.file.core.windows.net/;BlobSecondaryEndpoint=http://seanstagetest-secondary.blob.core.windows.net/;QueueSecondaryEndpoint=http://seanstagetest-secondary.queue.core.windows.net/;FileSecondaryEndpoint=http://seanstagetest-secondary.file.core.windows.net/;AccountName=seanstagetest;AccountKey=Sanitized"
}
}
Loading

0 comments on commit c7bf0cc

Please sign in to comment.