Skip to content

Commit

Permalink
Added support for HttpPipelinePosition in Storage Client builders (Az…
Browse files Browse the repository at this point in the history
  • Loading branch information
gapra-msft authored Oct 6, 2020
1 parent 7b6aae6 commit 0487306
Show file tree
Hide file tree
Showing 65 changed files with 2,196 additions and 70 deletions.
2 changes: 1 addition & 1 deletion sdk/storage/azure-storage-blob-cryptography/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Release History

## 12.9.0-beta.2 (Unreleased)

- Added support to specify whether or not a pipeline policy should be added per call or per retry.

## 12.9.0-beta.1 (2020-10-01)
- Added support to set BlobParallelUploadOptions.computeMd5 so the service can perform an md5 verification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpPipelineBuilder;
import com.azure.core.http.HttpPipelinePosition;
import com.azure.core.http.policy.AddDatePolicy;
import com.azure.core.http.policy.BearerTokenAuthenticationPolicy;
import com.azure.core.http.policy.HttpLogOptions;
Expand Down Expand Up @@ -95,7 +96,8 @@ public final class EncryptedBlobClientBuilder {
private SasTokenCredential sasTokenCredential;

private HttpClient httpClient;
private final List<HttpPipelinePolicy> additionalPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perCallPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perRetryPolicies = new ArrayList<>();
private HttpLogOptions logOptions;
private RequestRetryOptions retryOptions = new RequestRetryOptions();
private HttpPipeline httpPipeline;
Expand Down Expand Up @@ -194,6 +196,7 @@ private HttpPipeline getHttpPipeline() {
userAgentConfiguration));
policies.add(new RequestIdPolicy());

policies.addAll(perCallPolicies);
HttpPolicyProviders.addBeforeRetryPolicies(policies);
policies.add(new RequestRetryPolicy(retryOptions));

Expand All @@ -208,7 +211,7 @@ private HttpPipeline getHttpPipeline() {
policies.add(new SasTokenCredentialPolicy(sasTokenCredential));
}

policies.addAll(additionalPolicies);
policies.addAll(perRetryPolicies);

HttpPolicyProviders.addAfterRetryPolicies(policies);

Expand Down Expand Up @@ -461,7 +464,12 @@ public EncryptedBlobClientBuilder httpClient(HttpClient httpClient) {
* @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
*/
public EncryptedBlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
this.additionalPolicies.add(Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null"));
Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null");
if (pipelinePolicy.getPipelinePosition() == HttpPipelinePosition.PER_CALL) {
perCallPolicies.add(pipelinePolicy);
} else {
perRetryPolicies.add(pipelinePolicy);
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package com.azure.storage.blob.specialized.cryptography

import com.azure.core.http.HttpPipelineCallContext
import com.azure.core.http.HttpPipelineNextPolicy
import com.azure.core.http.HttpPipelinePosition
import com.azure.core.http.HttpResponse
import com.azure.core.http.policy.HttpPipelinePolicy
import com.azure.storage.blob.models.BlobStorageException
import com.azure.storage.blob.models.CustomerProvidedKey
import reactor.core.publisher.Mono

class BlobCryptographyBuilderTest extends APISpec {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ package com.azure.storage.blob.specialized.cryptography

import com.azure.core.cryptography.AsyncKeyEncryptionKey
import com.azure.core.cryptography.AsyncKeyEncryptionKeyResolver
import com.azure.core.http.HttpPipelineCallContext
import com.azure.core.http.HttpPipelineNextPolicy
import com.azure.core.http.HttpPipelinePosition
import com.azure.core.http.HttpResponse
import com.azure.core.http.policy.HttpPipelinePolicy
import com.azure.identity.DefaultAzureCredentialBuilder
import com.azure.storage.blob.BlobContainerClient
import com.azure.storage.blob.BlobServiceClientBuilder
Expand Down Expand Up @@ -30,6 +35,7 @@ import com.microsoft.azure.storage.blob.CloudBlockBlob
import reactor.core.Exceptions
import reactor.core.publisher.Flux
import reactor.core.publisher.Hooks
import reactor.core.publisher.Mono
import reactor.test.StepVerifier
import spock.lang.Requires
import spock.lang.Shared
Expand Down Expand Up @@ -1462,6 +1468,33 @@ class EncyptedBlockBlobAPITest extends APISpec {
3 * Constants.MB| Constants.MB || 4 // Encryption padding will add an extra block
}

def getPerCallVersionPolicy() {
return new HttpPipelinePolicy() {
@Override
Mono<HttpResponse> process(HttpPipelineCallContext context, HttpPipelineNextPolicy next) {
context.getHttpRequest().setHeader("x-ms-version","2017-11-09")
return next.process()
}
@Override
HttpPipelinePosition getPipelinePosition() {
return HttpPipelinePosition.PER_CALL
}
}
}

// This tests the policy is in the right place because if it were added per retry, it would be after the credentials and auth would fail because we changed a signed header.
def "Per call policy"() {
def client = getEncryptedClientBuilder(fakeKey, fakeKeyResolver, primaryCredential, bec.getBlobUrl(), getPerCallVersionPolicy()).buildEncryptedBlobClient()

client.upload(new ByteArrayInputStream(new byte[0]), 0)

when:
def response = client.getPropertiesWithResponse(null, null, null)

then:
notThrown(BlobStorageException)
response.getHeaders().getValue("x-ms-version") == "2017-11-09"
}

def compareListToBuffer(List<ByteBuffer> buffers, ByteBuffer result) {
result.position(0)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
{
"networkCallRecords" : [ {
"Method" : "PUT",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368?restype=container",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "9e008824-846e-402a-948d-0a1702ae1bf0"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"ETag" : "0x8D86973BE7A6EEA",
"Last-Modified" : "Mon, 05 Oct 2020 21:15:11 GMT",
"retry-after" : "0",
"Content-Length" : "0",
"StatusCode" : "201",
"x-ms-request-id" : "38d70486-901e-0078-4d5c-9bf00c000000",
"Date" : "Mon, 05 Oct 2020 21:15:10 GMT",
"x-ms-client-request-id" : "9e008824-846e-402a-948d-0a1702ae1bf0"
},
"Exception" : null
}, {
"Method" : "HEAD",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368/javablobpercallpolicy397110eddf6bc4946745b584",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "37a6eaa7-9165-4408-8371-ffc04c761b58"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"Vary" : "Origin",
"x-ms-error-code" : "BlobNotFound",
"retry-after" : "0",
"StatusCode" : "404",
"x-ms-request-id" : "38d704f3-901e-0078-255c-9bf00c000000",
"Date" : "Mon, 05 Oct 2020 21:15:11 GMT",
"x-ms-client-request-id" : "37a6eaa7-9165-4408-8371-ffc04c761b58"
},
"Exception" : null
}, {
"Method" : "PUT",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368/javablobpercallpolicy397110eddf6bc4946745b584",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "60bf406e-d547-49bb-bcfa-96740f90baa1",
"Content-Type" : "application/octet-stream"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"x-ms-content-crc64" : "PMO3rkv7nrg=",
"Last-Modified" : "Mon, 05 Oct 2020 21:15:11 GMT",
"retry-after" : "0",
"StatusCode" : "201",
"x-ms-request-server-encrypted" : "true",
"Date" : "Mon, 05 Oct 2020 21:15:11 GMT",
"Content-MD5" : "+3amp8R+Cu1GeDNIXyekcA==",
"ETag" : "0x8D86973BEBCA889",
"Content-Length" : "0",
"x-ms-request-id" : "38d70516-901e-0078-415c-9bf00c000000",
"x-ms-client-request-id" : "60bf406e-d547-49bb-bcfa-96740f90baa1"
},
"Exception" : null
}, {
"Method" : "PUT",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368/javablobpercallpolicy20116850c9faea887848619a",
"Headers" : {
"x-ms-version" : "2017-11-09",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "ef701033-f168-4368-9427-afe6385d0e28",
"Content-Type" : "application/octet-stream"
},
"Response" : {
"x-ms-version" : "2017-11-09",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"ETag" : "0x8D86973BECE11EB",
"Last-Modified" : "Mon, 05 Oct 2020 21:15:11 GMT",
"retry-after" : "0",
"Content-Length" : "0",
"StatusCode" : "201",
"x-ms-request-id" : "38d7053b-901e-0078-615c-9bf00c000000",
"x-ms-request-server-encrypted" : "true",
"Date" : "Mon, 05 Oct 2020 21:15:11 GMT",
"Content-MD5" : "7+kl9/L/uprERn7zvYfaCA=="
},
"Exception" : null
}, {
"Method" : "HEAD",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368/javablobpercallpolicy20116850c9faea887848619a",
"Headers" : {
"x-ms-version" : "2017-11-09",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "d3eccdd6-4e4c-463a-bd88-43f4f5c7da45"
},
"Response" : {
"x-ms-version" : "2017-11-09",
"x-ms-lease-status" : "unlocked",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"x-ms-lease-state" : "available",
"Last-Modified" : "Mon, 05 Oct 2020 21:15:11 GMT",
"retry-after" : "0",
"StatusCode" : "200",
"Date" : "Mon, 05 Oct 2020 21:15:11 GMT",
"x-ms-blob-type" : "BlockBlob",
"Content-MD5" : "7+kl9/L/uprERn7zvYfaCA==",
"Accept-Ranges" : "bytes",
"x-ms-meta-encryptiondata" : "{\"EncryptionMode\":\"FullBlob\",\"WrappedContentKey\":{\"KeyId\":\"keyId\",\"EncryptedKey\":\"4sJ1Pc17dQ9lxVy21tLiM3g/hll0ruHT4vXa35w9fYk=\",\"Algorithm\":\"RSA-OAEP-256\"},\"EncryptionAgent\":{\"Protocol\":\"1.0\",\"EncryptionAlgorithm\":\"AES_CBC_256\"},\"ContentEncryptionIV\":\"+YIIeatW5pLWglx7bN1ctA==\",\"KeyWrappingMetadata\":{\"EncryptionLibrary\":\"JavaTrack212.9.0-beta.2\"}}",
"x-ms-server-encrypted" : "true",
"x-ms-access-tier-inferred" : "true",
"x-ms-access-tier" : "Hot",
"ETag" : "0x8D86973BECE11EB",
"Vary" : "Origin",
"x-ms-creation-time" : "Mon, 05 Oct 2020 21:15:11 GMT",
"Content-Length" : "16",
"x-ms-request-id" : "38d70550-901e-0078-715c-9bf00c000000",
"Content-Type" : "application/octet-stream"
},
"Exception" : null
}, {
"Method" : "DELETE",
"Uri" : "https://REDACTED.blob.core.windows.net/jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368?restype=container",
"Headers" : {
"x-ms-version" : "2020-02-10",
"User-Agent" : "azsdk-java-azure-storage-blob/12.9.0-beta.2 (11.0.7; Windows 10; 10.0)",
"x-ms-client-request-id" : "3a36796e-0ea1-4734-ab29-7598b9e811ba"
},
"Response" : {
"x-ms-version" : "2020-02-10",
"Server" : "Windows-Azure-Blob/1.0 Microsoft-HTTPAPI/2.0",
"retry-after" : "0",
"Content-Length" : "0",
"StatusCode" : "202",
"x-ms-request-id" : "38d7056c-901e-0078-075c-9bf00c000000",
"Date" : "Mon, 05 Oct 2020 21:15:11 GMT",
"x-ms-client-request-id" : "3a36796e-0ea1-4734-ab29-7598b9e811ba"
},
"Exception" : null
} ],
"variables" : [ "b20d1105-5782-4878-9ad3-ad04521c9973", "jtcpercallpolicy0encyptedblockblobapitestpercallpolicy4aa40368", "javablobpercallpolicy18682720e6c24fd5f54c109b", "javablobpercallpolicy20116850c9faea887848619a", "javablobpercallpolicy397110eddf6bc4946745b584" ]
}
2 changes: 1 addition & 1 deletion sdk/storage/azure-storage-blob/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Release History

## 12.9.0-beta.2 (Unreleased)

- Added support to specify whether or not a pipeline policy should be added per call or per retry.

## 12.9.0-beta.1 (2020-10-01)
- Added support for the 2020-02-10 service version.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.azure.core.credential.TokenCredential;
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpPipelinePosition;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.policy.HttpPipelinePolicy;
import com.azure.core.util.Configuration;
Expand Down Expand Up @@ -63,7 +64,8 @@ public final class BlobClientBuilder {
private SasTokenCredential sasTokenCredential;

private HttpClient httpClient;
private final List<HttpPipelinePolicy> additionalPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perCallPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perRetryPolicies = new ArrayList<>();
private HttpLogOptions logOptions;
private RequestRetryOptions retryOptions = new RequestRetryOptions();
private HttpPipeline httpPipeline;
Expand Down Expand Up @@ -129,7 +131,7 @@ public BlobAsyncClient buildAsyncClient() {

HttpPipeline pipeline = (httpPipeline != null) ? httpPipeline : BuilderHelper.buildPipeline(
storageSharedKeyCredential, tokenCredential, sasTokenCredential, endpoint, retryOptions, logOptions,
httpClient, additionalPolicies, configuration, logger);
httpClient, perCallPolicies, perRetryPolicies, configuration, logger);

return new BlobAsyncClient(pipeline, String.format("%s/%s/%s", endpoint, blobContainerName, blobName),
serviceVersion, accountName, blobContainerName, blobName, snapshot, customerProvidedKey, encryptionScope,
Expand Down Expand Up @@ -368,7 +370,12 @@ public BlobClientBuilder httpClient(HttpClient httpClient) {
* @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
*/
public BlobClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
this.additionalPolicies.add(Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null"));
Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null");
if (pipelinePolicy.getPipelinePosition() == HttpPipelinePosition.PER_CALL) {
perCallPolicies.add(pipelinePolicy);
} else {
perRetryPolicies.add(pipelinePolicy);
}
return this;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.azure.core.credential.TokenCredential;
import com.azure.core.http.HttpClient;
import com.azure.core.http.HttpPipeline;
import com.azure.core.http.HttpPipelinePosition;
import com.azure.core.http.policy.HttpLogOptions;
import com.azure.core.http.policy.HttpPipelinePolicy;
import com.azure.core.util.Configuration;
Expand Down Expand Up @@ -61,7 +62,8 @@ public final class BlobContainerClientBuilder {
private SasTokenCredential sasTokenCredential;

private HttpClient httpClient;
private final List<HttpPipelinePolicy> additionalPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perCallPolicies = new ArrayList<>();
private final List<HttpPipelinePolicy> perRetryPolicies = new ArrayList<>();
private HttpLogOptions logOptions;
private RequestRetryOptions retryOptions = new RequestRetryOptions();
private HttpPipeline httpPipeline;
Expand Down Expand Up @@ -119,7 +121,7 @@ public BlobContainerAsyncClient buildAsyncClient() {

HttpPipeline pipeline = (httpPipeline != null) ? httpPipeline : BuilderHelper.buildPipeline(
storageSharedKeyCredential, tokenCredential, sasTokenCredential, endpoint, retryOptions, logOptions,
httpClient, additionalPolicies, configuration, logger);
httpClient, perCallPolicies, perRetryPolicies, configuration, logger);

return new BlobContainerAsyncClient(pipeline, String.format("%s/%s", endpoint, blobContainerName),
serviceVersion, accountName, blobContainerName, customerProvidedKey, encryptionScope,
Expand Down Expand Up @@ -325,7 +327,12 @@ public BlobContainerClientBuilder httpClient(HttpClient httpClient) {
* @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
*/
public BlobContainerClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
this.additionalPolicies.add(Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null"));
Objects.requireNonNull(pipelinePolicy, "'pipelinePolicy' cannot be null");
if (pipelinePolicy.getPipelinePosition() == HttpPipelinePosition.PER_CALL) {
perCallPolicies.add(pipelinePolicy);
} else {
perRetryPolicies.add(pipelinePolicy);
}
return this;
}

Expand Down
Loading

0 comments on commit 0487306

Please sign in to comment.