diff --git a/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncryptedFlux.java b/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncryptedFlux.java index 7f1c0f7b2769..319756981ccf 100644 --- a/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncryptedFlux.java +++ b/sdk/storage/azure-storage-blob-cryptography/src/test/java/com/azure/storage/blob/specialized/cryptography/EncryptedFlux.java @@ -142,7 +142,7 @@ public EncryptedFlux(int testCase, AsyncKeyEncryptionKey key, APISpec spec) thro this.plainText = spec.getRandomData(DOWNLOAD_SIZE - 2); // This will yield two bytes of padding... for fun. EncryptedBlob encryptedBlob = new EncryptedBlobAsyncClient( - null, null, BlobServiceVersion.getLatest(), null, null, null, null, null, key, "keyWrapAlgorithm") + null, "https://random.blob.core.windows.net", BlobServiceVersion.getLatest(), null, null, null, null, null, key, "keyWrapAlgorithm") .encryptBlob(Flux.just(this.plainText)).block(); this.cipherText = APISpec.collectBytesInBuffer(encryptedBlob.getCiphertextFlux()).block(); this.encryptionData = encryptedBlob.getEncryptionData(); diff --git a/sdk/storage/azure-storage-blob/CHANGELOG.md b/sdk/storage/azure-storage-blob/CHANGELOG.md index 548b137d4b19..bcc283e39043 100644 --- a/sdk/storage/azure-storage-blob/CHANGELOG.md +++ b/sdk/storage/azure-storage-blob/CHANGELOG.md @@ -2,6 +2,7 @@ ## 12.7.0-beta.1 (Unreleased) - Fixed a bug that caused auth failures when constructing a client to a secondary endpoint using token auth. +- Modified client constructors to throw on invalid urls early to prevent SAS tokens from being logged in Exceptions. ## 12.6.1 (2020-05-06) - Updated `azure-core` version to `1.5.0` to pickup fixes for percent encoding `UTF-8` and invalid leading bytes in a body string. diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java index 007d0650c23d..f98bd03a7c47 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobContainerAsyncClient.java @@ -42,6 +42,7 @@ import com.azure.storage.common.implementation.StorageImplUtils; import reactor.core.publisher.Mono; +import java.net.URI; import java.time.Duration; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; @@ -55,8 +56,8 @@ import static com.azure.core.util.FluxUtil.monoError; import static com.azure.core.util.FluxUtil.pagedFluxError; import static com.azure.core.util.FluxUtil.withContext; -import static com.azure.storage.common.Utility.STORAGE_TRACING_NAMESPACE_VALUE; import static com.azure.core.util.tracing.Tracer.AZ_TRACING_NAMESPACE_KEY; +import static com.azure.storage.common.Utility.STORAGE_TRACING_NAMESPACE_VALUE; /** * Client to a container. It may only be instantiated through a {@link BlobContainerClientBuilder} or via the method @@ -112,6 +113,13 @@ public final class BlobContainerAsyncClient { BlobContainerAsyncClient(HttpPipeline pipeline, String url, BlobServiceVersion serviceVersion, String accountName, String containerName, CpkInfo customerProvidedKey, EncryptionScope encryptionScope, BlobContainerEncryptionScope blobContainerEncryptionScope) { + /* Check to make sure the uri is valid. We don't want the error to occur later in the generated layer + when the sas token has already been applied. */ + try { + URI.create(url); + } catch (IllegalArgumentException ex) { + throw logger.logExceptionAsError(ex); + } this.azureBlobStorage = new AzureBlobStorageBuilder() .pipeline(pipeline) .url(url) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java index 163fb7b91ed9..ff24c1a12cf1 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/BlobServiceAsyncClient.java @@ -40,6 +40,7 @@ import com.azure.storage.common.sas.AccountSasSignatureValues; import reactor.core.publisher.Mono; +import java.net.URI; import java.time.Duration; import java.time.OffsetDateTime; import java.util.ArrayList; @@ -103,6 +104,13 @@ public final class BlobServiceAsyncClient { BlobServiceAsyncClient(HttpPipeline pipeline, String url, BlobServiceVersion serviceVersion, String accountName, CpkInfo customerProvidedKey, EncryptionScope encryptionScope, BlobContainerEncryptionScope blobContainerEncryptionScope, boolean anonymousAccess) { + /* Check to make sure the uri is valid. We don't want the error to occur later in the generated layer + when the sas token has already been applied. */ + try { + URI.create(url); + } catch (IllegalArgumentException ex) { + throw logger.logExceptionAsError(ex); + } this.azureBlobStorage = new AzureBlobStorageBuilder() .pipeline(pipeline) .url(url) diff --git a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java index cfa417c04718..4062478e4b78 100644 --- a/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java +++ b/sdk/storage/azure-storage-blob/src/main/java/com/azure/storage/blob/specialized/BlobAsyncClientBase.java @@ -59,6 +59,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.MalformedURLException; +import java.net.URI; import java.net.URL; import java.nio.ByteBuffer; import java.nio.channels.AsynchronousFileChannel; @@ -139,6 +140,13 @@ protected BlobAsyncClientBase(HttpPipeline pipeline, String url, BlobServiceVers protected BlobAsyncClientBase(HttpPipeline pipeline, String url, BlobServiceVersion serviceVersion, String accountName, String containerName, String blobName, String snapshot, CpkInfo customerProvidedKey, EncryptionScope encryptionScope) { + /* Check to make sure the uri is valid. We don't want the error to occur later in the generated layer + when the sas token has already been applied. */ + try { + URI.create(url); + } catch (IllegalArgumentException ex) { + throw logger.logExceptionAsError(ex); + } this.azureBlobStorage = new AzureBlobStorageBuilder() .pipeline(pipeline) .url(url) diff --git a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAPITest.groovy b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAPITest.groovy index 9de90f238737..5b4828d39d74 100644 --- a/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAPITest.groovy +++ b/sdk/storage/azure-storage-blob/src/test/java/com/azure/storage/blob/ServiceAPITest.groovy @@ -4,27 +4,14 @@ package com.azure.storage.blob import com.azure.identity.DefaultAzureCredentialBuilder -import com.azure.identity.EnvironmentCredentialBuilder -import com.azure.storage.blob.models.BlobAnalyticsLogging -import com.azure.storage.blob.models.BlobContainerItem -import com.azure.storage.blob.models.BlobContainerListDetails -import com.azure.storage.blob.models.BlobCorsRule -import com.azure.storage.blob.models.BlobMetrics -import com.azure.storage.blob.models.BlobRetentionPolicy -import com.azure.storage.blob.models.BlobServiceProperties -import com.azure.storage.blob.models.CustomerProvidedKey -import com.azure.storage.blob.models.ListBlobContainersOptions -import com.azure.storage.blob.models.StaticWebsite - -import com.azure.storage.common.StorageSharedKeyCredential -import com.azure.storage.blob.models.BlobStorageException - +import com.azure.storage.blob.models.* import com.azure.storage.common.policy.RequestRetryOptions import com.azure.storage.common.policy.RequestRetryPolicy import com.azure.storage.common.sas.AccountSasPermission import com.azure.storage.common.sas.AccountSasResourceType import com.azure.storage.common.sas.AccountSasService import com.azure.storage.common.sas.AccountSasSignatureValues +import spock.lang.Unroll import java.time.Duration import java.time.OffsetDateTime @@ -532,4 +519,29 @@ class ServiceAPITest extends APISpec { then: notThrown(Exception) } + + @Unroll + def "sas token does not show up on invalid uri"() { + setup: + /* random sas token. this does not actually authenticate anything. */ + def mockSas = "?sv=2019-10-10&ss=b&srt=sco&sp=r&se=2019-06-04T12:04:58Z&st=2090-05-04T04:04:58Z&spr=http&sig=doesntmatter" + + when: + BlobServiceClient client = new BlobServiceClientBuilder() + .endpoint(service) + .sasToken(mockSas) + .buildClient(); + client.getBlobContainerClient(container) + .getBlobClient("blobname") + + then: + def e = thrown(IllegalArgumentException) + !e.getMessage().contains(mockSas) + + where: + service | container || _ + "https://doesntmatter. blob.core.windows.net" | "containername" || _ + "https://doesntmatter.blob.core.windows.net" | "container name" || _ + /* Note: the check is on the blob builder as well but I can't test it this way since we encode all blob names - so it will not be invalid. */ + } } diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[0].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[0].json new file mode 100644 index 000000000000..d3803998d14b --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[0].json @@ -0,0 +1,105 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcsastokendoesnotshowuponinvaliduri0555729625f76b47?restype=container", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "bf9bf799-e167-411a-97e9-552ac22a5e80" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D7FD07BB0063F4", + "Last-Modified" : "Wed, 20 May 2020 21:49:54 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "15ce2a1e-601e-0096-57f0-2e4471000000", + "Date" : "Wed, 20 May 2020 21:49:53 GMT", + "x-ms-client-request-id" : "bf9bf799-e167-411a-97e9-552ac22a5e80" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "522f7e7c-4201-41eb-b455-3ed29a0b7927", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "d043da61-101e-000a-03f0-2ee917000000", + "Date" : "Wed, 20 May 2020 21:49:55 GMT", + "x-ms-client-request-id" : "522f7e7c-4201-41eb-b455-3ed29a0b7927" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "cef8048a-c027-4788-b8b9-30e8038059b9", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "9b5a6e75-301e-0032-64f0-2e4dd7000000", + "Date" : "Wed, 20 May 2020 21:49:55 GMT", + "x-ms-client-request-id" : "cef8048a-c027-4788-b8b9-30e8038059b9" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcsastokendoesnotshowuponinvaliduri&comp=list", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "b793f994-bd25-4ef8-a6bf-4060bb15c690" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "d1bd715e-801e-0045-54f0-2e9843000000", + "Body" : "jtcsastokendoesnotshowuponinvalidurijtcsastokendoesnotshowuponinvaliduri0555729625f76b47Wed, 20 May 2020 21:49:54 GMT\"0x8D7FD07BB0063F4\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Wed, 20 May 2020 21:49:57 GMT", + "x-ms-client-request-id" : "b793f994-bd25-4ef8-a6bf-4060bb15c690", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcsastokendoesnotshowuponinvaliduri0555729625f76b47?restype=container", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "cd14b8d7-a9ee-4c1f-8a8f-62e408c1cd47" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "0f0cec0e-c01e-0009-2cf0-2e0873000000", + "Date" : "Wed, 20 May 2020 21:49:57 GMT", + "x-ms-client-request-id" : "cd14b8d7-a9ee-4c1f-8a8f-62e408c1cd47" + }, + "Exception" : null + } ], + "variables" : [ "jtcsastokendoesnotshowuponinvaliduri0555729625f76b47" ] +} \ No newline at end of file diff --git a/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[1].json b/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[1].json new file mode 100644 index 000000000000..196535628985 --- /dev/null +++ b/sdk/storage/azure-storage-blob/src/test/resources/session-records/ServiceAPITestsastokendoesnotshowuponinvaliduri[1].json @@ -0,0 +1,105 @@ +{ + "networkCallRecords" : [ { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcsastokendoesnotshowuponinvaliduri0138028e4e760e5e?restype=container", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "43908848-6eb4-4046-9a96-b1063d286e66" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "ETag" : "0x8D7FD07BDFE0B11", + "Last-Modified" : "Wed, 20 May 2020 21:49:59 GMT", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "201", + "x-ms-request-id" : "782b810b-301e-001d-64f0-2e401c000000", + "Date" : "Wed, 20 May 2020 21:49:58 GMT", + "x-ms-client-request-id" : "43908848-6eb4-4046-9a96-b1063d286e66" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "e84e7786-891b-4004-9b07-2fb0822b1682", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "ce91ccdd-901e-0059-66f0-2eca23000000", + "Date" : "Wed, 20 May 2020 21:50:00 GMT", + "x-ms-client-request-id" : "e84e7786-891b-4004-9b07-2fb0822b1682" + }, + "Exception" : null + }, { + "Method" : "PUT", + "Uri" : "https://REDACTED.blob.core.windows.net?restype=service&comp=properties", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "837d9bc7-0312-4d76-b4b1-00a4b6612890", + "Content-Type" : "application/xml; charset=utf-8" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "a47ab135-e01e-006c-7ef0-2ea637000000", + "Date" : "Wed, 20 May 2020 21:50:01 GMT", + "x-ms-client-request-id" : "837d9bc7-0312-4d76-b4b1-00a4b6612890" + }, + "Exception" : null + }, { + "Method" : "GET", + "Uri" : "https://REDACTED.blob.core.windows.net?prefix=jtcsastokendoesnotshowuponinvaliduri&comp=list", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "815812d5-ebbb-4346-be0c-765f4f8677a8" + }, + "Response" : { + "Transfer-Encoding" : "chunked", + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "StatusCode" : "200", + "x-ms-request-id" : "532b205c-701e-001c-49f0-2e1fc0000000", + "Body" : "jtcsastokendoesnotshowuponinvalidurijtcsastokendoesnotshowuponinvaliduri0138028e4e760e5eWed, 20 May 2020 21:49:59 GMT\"0x8D7FD07BDFE0B11\"unlockedavailable$account-encryption-keyfalsefalsefalse", + "Date" : "Wed, 20 May 2020 21:50:01 GMT", + "x-ms-client-request-id" : "815812d5-ebbb-4346-be0c-765f4f8677a8", + "Content-Type" : "application/xml" + }, + "Exception" : null + }, { + "Method" : "DELETE", + "Uri" : "https://REDACTED.blob.core.windows.net/jtcsastokendoesnotshowuponinvaliduri0138028e4e760e5e?restype=container", + "Headers" : { + "x-ms-version" : "2019-07-07", + "User-Agent" : "azsdk-java-azure-storage-blob/12.7.0-beta.1 (11.0.7; Windows 10 10.0)", + "x-ms-client-request-id" : "d16b3202-4412-4062-8ff1-fa9bf6d8907e" + }, + "Response" : { + "x-ms-version" : "2019-07-07", + "Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0", + "retry-after" : "0", + "Content-Length" : "0", + "StatusCode" : "202", + "x-ms-request-id" : "80c8813c-f01e-0094-48f0-2efac9000000", + "Date" : "Wed, 20 May 2020 21:50:02 GMT", + "x-ms-client-request-id" : "d16b3202-4412-4062-8ff1-fa9bf6d8907e" + }, + "Exception" : null + } ], + "variables" : [ "jtcsastokendoesnotshowuponinvaliduri0138028e4e760e5e" ] +} \ No newline at end of file