From 3f48a2cf7948536ae9b67968707a3041210260e5 Mon Sep 17 00:00:00 2001 From: adriancole Date: Mon, 21 Jan 2013 10:08:38 -0800 Subject: [PATCH] integrated s3 request signing with temporary credentials --- .../s3/filters/RequestAuthorizeSignature.java | 9 ++ ...SignatureWithTemporaryCredentialsTest.java | 91 +++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureWithTemporaryCredentialsTest.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 1015845a97..61b0462ab0 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 @@ -39,6 +39,7 @@ import javax.inject.Singleton; import javax.ws.rs.core.HttpHeaders; import org.jclouds.Constants; +import org.jclouds.aws.domain.TemporaryCredentials; import org.jclouds.crypto.Crypto; import org.jclouds.crypto.CryptoStreams; import org.jclouds.date.TimeStamp; @@ -116,12 +117,20 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign public HttpRequest filter(HttpRequest request) throws HttpException { request = replaceDateHeader(request); + Credentials current = creds.get(); + if (current instanceof TemporaryCredentials) { + request = replaceSecurityTokenHeader(request, TemporaryCredentials.class.cast(current)); + } String signature = calculateSignature(createStringToSign(request)); request = replaceAuthorizationHeader(request, signature); utils.logRequest(signatureLog, request, "<<"); return request; } + HttpRequest replaceSecurityTokenHeader(HttpRequest request, TemporaryCredentials current) { + return request.toBuilder().replaceHeader("x-amz-security-token", current.getSessionToken()).build(); + } + HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { request = request.toBuilder() .replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + creds.get().identity + ":" + signature).build(); diff --git a/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureWithTemporaryCredentialsTest.java b/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureWithTemporaryCredentialsTest.java new file mode 100644 index 0000000000..da1179ec40 --- /dev/null +++ b/apis/s3/src/test/java/org/jclouds/s3/filters/RequestAuthorizeSignatureWithTemporaryCredentialsTest.java @@ -0,0 +1,91 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.s3.filters; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.ContextBuilder; +import org.jclouds.aws.domain.TemporaryCredentials; +import org.jclouds.date.TimeStamp; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.domain.Credentials; +import org.jclouds.http.HttpRequest; +import org.jclouds.logging.config.NullLoggingModule; +import org.jclouds.rest.ConfiguresRestClient; +import org.jclouds.rest.internal.BaseRestApiTest.MockModule; +import org.jclouds.rest.internal.GeneratedHttpRequest; +import org.jclouds.s3.S3AsyncClient; +import org.jclouds.s3.S3Client; +import org.jclouds.s3.config.S3RestClientModule; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableList; +import com.google.inject.Injector; +import com.google.inject.Module; + +/** + * Tests behavior of {@code RequestAuthorizeSignature} + * + * @author Adrian Cole + */ +// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire +@Test(groups = "unit", testName = "RequestAuthorizeSignatureWithTemporaryCredentialsTest") +public class RequestAuthorizeSignatureWithTemporaryCredentialsTest { + public static Injector injector(Credentials creds) { + return ContextBuilder.newBuilder("s3") + .credentialsSupplier(Suppliers. ofInstance(creds)) + .modules(ImmutableList. of(new MockModule(), new NullLoggingModule(), new TestS3RestClientModule())).buildInjector(); + } + + @ConfiguresRestClient + private static final class TestS3RestClientModule extends S3RestClientModule { + + @Override + protected String provideTimeStamp(@TimeStamp Supplier cache) { + return "2009-11-08T15:54:08.897Z"; + } + } + + public static RequestAuthorizeSignature filter(Credentials creds) { + return injector(creds).getInstance(RequestAuthorizeSignature.class); + } + + TemporaryCredentials temporaryCredentials = TemporaryCredentials.builder() + .accessKeyId("AKIAIOSFODNN7EXAMPLE") + .secretAccessKey("wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY") + .sessionToken("AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT") + .expiration(new SimpleDateFormatDateService().iso8601DateParse("2011-07-11T19:55:29.611Z")).build(); + + @Test + void testAddsSecurityToken() throws Exception { + HttpRequest bucketFooExists = GeneratedHttpRequest.builder().method("GET") + .declaring(S3AsyncClient.class) + .javaMethod(S3AsyncClient.class.getMethod("bucketExists", String.class)) + .arg("foo") + .endpoint("https://foo.s3.amazonaws.com/?max-keys=0") + .addHeader("Host", "foo.s3.amazonaws.com").build(); + + HttpRequest filtered = filter(temporaryCredentials).filter(bucketFooExists); + assertEquals(filtered.getFirstHeaderOrNull("Authorization"), + "AWS AKIAIOSFODNN7EXAMPLE:0fUhWTaRBcIvIAndg2C+5eLfE24="); + assertEquals(filtered.getFirstHeaderOrNull("x-amz-security-token"), temporaryCredentials.getSessionToken()); + } +}