Updated Branches: refs/heads/move-tempurl=to-aws [created] 9deeac4d8
JCLOUDS-200: Consolidate all feature-specific in the AWS provider Follow-up to c64c7423 Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/9deeac4d Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/9deeac4d Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/9deeac4d Branch: refs/heads/move-tempurl=to-aws Commit: 9deeac4d81431497d478bba65766ea7e417d6ed2 Parents: c64c742 Author: Andrew Phillips <[email protected]> Authored: Thu Jul 25 15:24:24 2013 -0400 Committer: Andrew Phillips <[email protected]> Committed: Thu Jul 25 15:24:24 2013 -0400 ---------------------------------------------------------------------- .../jclouds/s3/config/S3RestClientModule.java | 6 +- .../s3/filters/RequestAuthorizeSignature.java | 10 +-- .../s3/blobstore/AWSS3BlobRequestSigner.java | 4 +- .../aws/s3/config/AWSS3RestClientModule.java | 10 ++- .../filters/AWSRequestAuthorizeSignature.java | 75 ++++++++++++++++++++ .../jclouds/aws/s3/filters/package-info.java | 22 ++++++ .../jclouds/aws/s3/AWSS3AsyncClientTest.java | 9 +++ 7 files changed, 124 insertions(+), 12 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java ---------------------------------------------------------------------- diff --git a/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java b/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java index 33ac2ef..cd71828 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java +++ b/apis/s3/src/main/java/org/jclouds/s3/config/S3RestClientModule.java @@ -162,7 +162,7 @@ public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> ext super.configure(); install(new S3ObjectModule()); install(new S3ParserModule()); - bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON); + bindRequestSigner(); bind(new TypeLiteral<Function<String, Optional<String>>>() { }).annotatedWith(Bucket.class).to(GetRegionForBucket.class); bind(new TypeLiteral<Function<Set<BucketMetadata>, PageSet<? extends StorageMetadata>>>() { @@ -176,6 +176,10 @@ public class S3RestClientModule<S extends S3Client, A extends S3AsyncClient> ext bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseS3ErrorFromXmlContent.class); } + protected void bindRequestSigner() { + bind(RequestAuthorizeSignature.class).in(Scopes.SINGLETON); + } + @Provides @Singleton protected RequestSigner provideRequestSigner(RequestAuthorizeSignature in) { http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java ---------------------------------------------------------------------- diff --git a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java index ca85401..26e06b0 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java +++ b/apis/s3/src/main/java/org/jclouds/s3/filters/RequestAuthorizeSignature.java @@ -50,7 +50,6 @@ import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpUtils; import org.jclouds.http.internal.SignatureWire; -import org.jclouds.http.utils.Queries; import org.jclouds.logging.Logger; import org.jclouds.rest.RequestSigner; import org.jclouds.s3.util.S3Utils; @@ -133,14 +132,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign return request.toBuilder().replaceHeader("x-amz-security-token", current.getSessionToken()).build(); } - HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { - // Only add the Authorization header if the query string doesn't already contain - // the 'Signature' parameter, otherwise S3 will fail the request complaining about - // duplicate authentication methods. The 'Signature' parameter will be added for signed URLs - // with expiration. - if (Queries.queryParser().apply(request.getEndpoint().getQuery()).containsKey("Signature")) { - return request; - } + protected HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { request = request.toBuilder() .replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + creds.get().identity + ":" + signature).build(); return request; http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java ---------------------------------------------------------------------- diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java index b0b9824..775cdf5 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/blobstore/AWSS3BlobRequestSigner.java @@ -45,6 +45,8 @@ import com.google.inject.Provider; * @author Diwaker Gupta */ public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3AsyncClient> { + public static final String TEMPORARY_SIGNATURE_PARAM = "Signature"; + private final RequestAuthorizeSignature authSigner; private final String identity; private final DateService dateService; @@ -90,7 +92,7 @@ public class AWSS3BlobRequestSigner extends S3BlobRequestSigner<AWSS3AsyncClient String expiration = String.valueOf(TimeUnit.MILLISECONDS.toSeconds(date.getTime()) + timeInSeconds); HttpRequest.Builder<?> builder = request.toBuilder().replaceHeader(HttpHeaders.DATE, expiration); final String signature = authSigner.sign(authSigner.createStringToSign(builder.build())); - return builder.addQueryParam("Signature", signature) + return builder.addQueryParam(TEMPORARY_SIGNATURE_PARAM, signature) .addQueryParam(HttpHeaders.EXPIRES, expiration) .addQueryParam("AWSAccessKeyId", identity) .build(); http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java ---------------------------------------------------------------------- diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java index 6e8da5b..3001a0e 100644 --- a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/config/AWSS3RestClientModule.java @@ -23,17 +23,20 @@ import javax.inject.Singleton; import org.jclouds.aws.s3.AWSS3AsyncClient; import org.jclouds.aws.s3.AWSS3Client; +import org.jclouds.aws.s3.filters.AWSRequestAuthorizeSignature; import org.jclouds.aws.s3.predicates.validators.AWSS3BucketNameValidator; import org.jclouds.location.Region; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.s3.S3AsyncClient; import org.jclouds.s3.S3Client; import org.jclouds.s3.config.S3RestClientModule; +import org.jclouds.s3.filters.RequestAuthorizeSignature; import org.jclouds.s3.predicates.validators.BucketNameValidator; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; import com.google.inject.Provides; +import com.google.inject.Scopes; /** * Configures the S3 connection. @@ -57,7 +60,12 @@ public class AWSS3RestClientModule extends S3RestClientModule<AWSS3Client, AWSS3 bind(BucketNameValidator.class).to(AWSS3BucketNameValidator.class); super.configure(); } - + + @Override + protected void bindRequestSigner() { + bind(RequestAuthorizeSignature.class).to(AWSRequestAuthorizeSignature.class).in(Scopes.SINGLETON); + } + @Singleton @Provides S3Client provide(AWSS3Client in) { http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignature.java ---------------------------------------------------------------------- diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignature.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignature.java new file mode 100644 index 0000000..1d079fa --- /dev/null +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/AWSRequestAuthorizeSignature.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jclouds.aws.s3.filters; + +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_AUTH_TAG; +import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG; +import static org.jclouds.aws.s3.blobstore.AWSS3BlobRequestSigner.TEMPORARY_SIGNATURE_PARAM; +import static org.jclouds.http.utils.Queries.queryParser; +import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_SERVICE_PATH; +import static org.jclouds.s3.reference.S3Constants.PROPERTY_S3_VIRTUAL_HOST_BUCKETS; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Provider; +import javax.inject.Singleton; + +import org.jclouds.crypto.Crypto; +import org.jclouds.date.TimeStamp; +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpUtils; +import org.jclouds.http.internal.SignatureWire; +import org.jclouds.s3.filters.RequestAuthorizeSignature; + +import com.google.common.base.Supplier; + +/** + * Signs the AWS S3 request, supporting temporary signatures. + * + * @see <a href= + * "http://docs.amazonwebservices.com/AmazonS3/2006-03-01/dev/index.html?RESTAuthentication.html" + * /> + * + */ +@Singleton +public class AWSRequestAuthorizeSignature extends RequestAuthorizeSignature { + + @Inject + public AWSRequestAuthorizeSignature(SignatureWire signatureWire, @Named(PROPERTY_AUTH_TAG) String authTag, + @Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle, + @Named(PROPERTY_S3_SERVICE_PATH) String servicePath, @Named(PROPERTY_HEADER_TAG) String headerTag, + @org.jclouds.location.Provider Supplier<Credentials> creds, + @TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) { + super(signatureWire, authTag, isVhostStyle, servicePath, headerTag, creds, timeStampProvider, crypto, + utils); + } + + @Override + protected HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { + /* + * Only add the Authorization header if the query string doesn't already contain + * the 'Signature' parameter, otherwise S3 will fail the request complaining about + * duplicate authentication methods. The 'Signature' parameter will be added for signed URLs + * with expiration. + */ + if (queryParser().apply(request.getEndpoint().getQuery()).containsKey(TEMPORARY_SIGNATURE_PARAM)) { + return request; + } + return super.replaceAuthorizationHeader(request, signature); + } +} http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/package-info.java ---------------------------------------------------------------------- diff --git a/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/package-info.java b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/package-info.java new file mode 100644 index 0000000..18c08cc --- /dev/null +++ b/providers/aws-s3/src/main/java/org/jclouds/aws/s3/filters/package-info.java @@ -0,0 +1,22 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * This package contains HttpRequestFilters needed to operate the REST api. + * @see <a href="http://docs.amazonwebservices.com/AmazonS3/latest/RESTAuthentication.html" /> + * @author Adrian Cole + */ +package org.jclouds.aws.s3.filters; http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/9deeac4d/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java ---------------------------------------------------------------------- diff --git a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java index e3f8793..5e940dd 100644 --- a/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java +++ b/providers/aws-s3/src/test/java/org/jclouds/aws/s3/AWSS3AsyncClientTest.java @@ -17,6 +17,7 @@ package org.jclouds.aws.s3; import static org.jclouds.reflect.Reflection2.method; +import static org.testng.Assert.assertEquals; import java.io.IOException; import java.util.Map; @@ -24,11 +25,13 @@ import java.util.Set; import org.jclouds.Fallbacks.VoidOnNotFoundOr404; import org.jclouds.aws.s3.config.AWSS3RestClientModule; +import org.jclouds.aws.s3.filters.AWSRequestAuthorizeSignature; import org.jclouds.aws.s3.functions.ETagFromHttpResponseViaRegex; import org.jclouds.aws.s3.functions.UploadIdFromHttpResponseViaRegex; import org.jclouds.blobstore.binders.BindBlobToMultipartFormTest; import org.jclouds.date.TimeStamp; import org.jclouds.fallbacks.MapHttp4xxCodesToExceptions; +import org.jclouds.http.HttpRequest; import org.jclouds.http.functions.ParseETagHeader; import org.jclouds.http.functions.ParseSax; import org.jclouds.http.functions.ReleasePayloadAndReturn; @@ -69,6 +72,12 @@ import com.google.inject.Module; public class AWSS3AsyncClientTest extends S3AsyncClientTest<AWSS3AsyncClient> { @Override + protected void checkFilters(HttpRequest request) { + assertEquals(request.getFilters().size(), 1); + assertEquals(request.getFilters().get(0).getClass(), AWSRequestAuthorizeSignature.class); + } + + @Override public void testCopyObjectInvalidName() throws ArrayIndexOutOfBoundsException, SecurityException, IllegalArgumentException, NoSuchMethodException, IOException { // For AWS S3, S3AsyncClientTest#testCopyObjectInvalidName() will not throw an exception
