mirror of https://github.com/apache/jclouds.git
Merge pull request #1215 from jclouds/aws-temporary-credentials
Aws temporary credentials
This commit is contained in:
commit
6ab1e06388
|
@ -43,6 +43,7 @@ import javax.inject.Singleton;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.aws.domain.TemporaryCredentials;
|
||||||
import org.jclouds.crypto.Crypto;
|
import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
|
@ -119,12 +120,20 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
|
||||||
|
|
||||||
public HttpRequest filter(HttpRequest request) throws HttpException {
|
public HttpRequest filter(HttpRequest request) throws HttpException {
|
||||||
request = replaceDateHeader(request);
|
request = replaceDateHeader(request);
|
||||||
|
Credentials current = creds.get();
|
||||||
|
if (current instanceof TemporaryCredentials) {
|
||||||
|
request = replaceSecurityTokenHeader(request, TemporaryCredentials.class.cast(current));
|
||||||
|
}
|
||||||
String signature = calculateSignature(createStringToSign(request));
|
String signature = calculateSignature(createStringToSign(request));
|
||||||
request = replaceAuthorizationHeader(request, signature);
|
request = replaceAuthorizationHeader(request, signature);
|
||||||
utils.logRequest(signatureLog, request, "<<");
|
utils.logRequest(signatureLog, request, "<<");
|
||||||
return 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) {
|
HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
|
||||||
request = request.toBuilder()
|
request = request.toBuilder()
|
||||||
.replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + creds.get().identity + ":" + signature).build();
|
.replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + creds.get().identity + ":" + signature).build();
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
/**
|
||||||
|
* 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.jclouds.reflect.Reflection2.method;
|
||||||
|
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.reflect.Invocation;
|
||||||
|
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.<Credentials> ofInstance(creds))
|
||||||
|
.modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule(), new TestS3RestClientModule())).buildInjector();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ConfiguresRestClient
|
||||||
|
private static final class TestS3RestClientModule extends S3RestClientModule<S3Client, S3AsyncClient> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String provideTimeStamp(@TimeStamp Supplier<String> 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();
|
||||||
|
|
||||||
|
Invocation invocation = Invocation.create(method(S3AsyncClient.class, "bucketExists", String.class),
|
||||||
|
ImmutableList.<Object> of("foo"));
|
||||||
|
|
||||||
|
HttpRequest bucketFooExists = GeneratedHttpRequest.builder().method("GET")
|
||||||
|
.invocation(invocation)
|
||||||
|
.endpoint("https://foo.s3.amazonaws.com/?max-keys=0")
|
||||||
|
.addHeader("Host", "foo.s3.amazonaws.com").build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAddsSecurityToken() {
|
||||||
|
HttpRequest filtered = filter(temporaryCredentials).filter(bucketFooExists);
|
||||||
|
assertEquals(filtered.getFirstHeaderOrNull("Authorization"),
|
||||||
|
"AWS AKIAIOSFODNN7EXAMPLE:0fUhWTaRBcIvIAndg2C+5eLfE24=");
|
||||||
|
assertEquals(filtered.getFirstHeaderOrNull("x-amz-security-token"), temporaryCredentials.getSessionToken());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
/**
|
||||||
|
* 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.aws.domain;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AWS credentials for API authentication.
|
||||||
|
*
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html"
|
||||||
|
* />
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public final class TemporaryCredentials extends Credentials {
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder toBuilder() {
|
||||||
|
return builder().from(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class Builder extends Credentials.Builder<TemporaryCredentials> {
|
||||||
|
private String accessKeyId;
|
||||||
|
private String secretAccessKey;
|
||||||
|
private String sessionToken;
|
||||||
|
private Date expiration;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder identity(String identity) {
|
||||||
|
return accessKeyId(identity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Builder credential(String credential) {
|
||||||
|
return secretAccessKey(credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemporaryCredentials#getAccessKeyId()
|
||||||
|
*/
|
||||||
|
public Builder accessKeyId(String accessKeyId) {
|
||||||
|
this.accessKeyId = accessKeyId;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemporaryCredentials#getSecretAccessKey()
|
||||||
|
*/
|
||||||
|
public Builder secretAccessKey(String secretAccessKey) {
|
||||||
|
this.secretAccessKey = secretAccessKey;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemporaryCredentials#getSessionToken()
|
||||||
|
*/
|
||||||
|
public Builder sessionToken(String sessionToken) {
|
||||||
|
this.sessionToken = sessionToken;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see TemporaryCredentials#getExpiration()
|
||||||
|
*/
|
||||||
|
public Builder expiration(Date expiration) {
|
||||||
|
this.expiration = expiration;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemporaryCredentials build() {
|
||||||
|
return new TemporaryCredentials(accessKeyId, secretAccessKey, sessionToken, expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder from(TemporaryCredentials in) {
|
||||||
|
return this.accessKeyId(in.identity).secretAccessKey(in.credential).sessionToken(in.sessionToken)
|
||||||
|
.expiration(in.expiration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String sessionToken;
|
||||||
|
private final Date expiration;
|
||||||
|
|
||||||
|
private TemporaryCredentials(String accessKeyId, String secretAccessKey, String sessionToken, Date expiration) {
|
||||||
|
super(checkNotNull(accessKeyId, "accessKeyId"), checkNotNull(secretAccessKey, "secretAccessKey for %s",
|
||||||
|
accessKeyId));
|
||||||
|
this.sessionToken = checkNotNull(sessionToken, "sessionToken for %s", accessKeyId);
|
||||||
|
this.expiration = checkNotNull(expiration, "expiration for %s", accessKeyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AccessKeyId ID that identifies the temporary credentials.
|
||||||
|
*/
|
||||||
|
public String getAccessKeyId() {
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Secret Access Key to sign requests.
|
||||||
|
*/
|
||||||
|
public String getSecretAccessKey() {
|
||||||
|
return credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The security token that users must pass to the service API to use the
|
||||||
|
* temporary credentials.
|
||||||
|
*/
|
||||||
|
public String getSessionToken() {
|
||||||
|
return sessionToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The date on which these credentials expire.
|
||||||
|
*/
|
||||||
|
public Date getExpiration() {
|
||||||
|
return expiration;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(identity, credential, sessionToken, expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
TemporaryCredentials other = (TemporaryCredentials) obj;
|
||||||
|
return Objects.equal(this.identity, other.identity) && Objects.equal(this.credential, other.credential)
|
||||||
|
&& Objects.equal(this.sessionToken, other.sessionToken) && Objects.equal(this.expiration, other.expiration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return Objects.toStringHelper(this).add("accessKeyId", identity).add("sessionToken", sessionToken)
|
||||||
|
.add("expiration", expiration).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -47,6 +47,7 @@ import javax.inject.Singleton;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.aws.domain.TemporaryCredentials;
|
||||||
import org.jclouds.crypto.Crypto;
|
import org.jclouds.crypto.Crypto;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
|
@ -114,9 +115,17 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
|
||||||
String signature = sign(stringToSign);
|
String signature = sign(stringToSign);
|
||||||
addSignature(decodedParams, signature);
|
addSignature(decodedParams, signature);
|
||||||
request = setPayload(request, decodedParams);
|
request = setPayload(request, decodedParams);
|
||||||
|
Credentials current = creds.get();
|
||||||
|
if (current instanceof TemporaryCredentials) {
|
||||||
|
request = replaceSecurityTokenHeader(request, TemporaryCredentials.class.cast(current));
|
||||||
|
}
|
||||||
utils.logRequest(signatureLog, request, "<<");
|
utils.logRequest(signatureLog, request, "<<");
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HttpRequest replaceSecurityTokenHeader(HttpRequest request, TemporaryCredentials current) {
|
||||||
|
return request.toBuilder().replaceHeader("SecurityToken", current.getSessionToken()).build();
|
||||||
|
}
|
||||||
|
|
||||||
HttpRequest setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
|
HttpRequest setPayload(HttpRequest request, Multimap<String, String> decodedParams) {
|
||||||
String queryLine = buildQueryLine(decodedParams);
|
String queryLine = buildQueryLine(decodedParams);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
/**
|
||||||
|
* 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.aws.xml;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import org.jclouds.aws.domain.TemporaryCredentials;
|
||||||
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.http.functions.ParseSax;
|
||||||
|
import org.jclouds.util.SaxUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see <a href=
|
||||||
|
* "http://docs.aws.amazon.com/STS/latest/APIReference/API_Credentials.html"
|
||||||
|
* />
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
public class TemporaryCredentialsHandler extends ParseSax.HandlerForGeneratedRequestWithResult<TemporaryCredentials> {
|
||||||
|
private final DateService dateService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
protected TemporaryCredentialsHandler(DateService dateService) {
|
||||||
|
this.dateService = dateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringBuilder currentText = new StringBuilder();
|
||||||
|
private TemporaryCredentials.Builder builder = TemporaryCredentials.builder();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TemporaryCredentials getResult() {
|
||||||
|
try {
|
||||||
|
return builder.build();
|
||||||
|
} finally {
|
||||||
|
builder = TemporaryCredentials.builder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void endElement(String uri, String name, String qName) {
|
||||||
|
if (qName.equals("AccessKeyId")) {
|
||||||
|
builder.accessKeyId(SaxUtils.currentOrNull(currentText));
|
||||||
|
} else if (qName.equals("SecretAccessKey")) {
|
||||||
|
builder.secretAccessKey(SaxUtils.currentOrNull(currentText));
|
||||||
|
} else if (qName.equals("SessionToken")) {
|
||||||
|
builder.sessionToken(SaxUtils.currentOrNull(currentText));
|
||||||
|
} else if (qName.equals("Expiration")) {
|
||||||
|
builder.expiration(dateService.iso8601DateParse(SaxUtils.currentOrNull(currentText)));
|
||||||
|
}
|
||||||
|
currentText = new StringBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void characters(char ch[], int start, int length) {
|
||||||
|
currentText.append(ch, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,13 +17,16 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.filters;
|
package org.jclouds.aws.filters;
|
||||||
|
|
||||||
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
|
|
||||||
import org.jclouds.ContextBuilder;
|
import org.jclouds.ContextBuilder;
|
||||||
|
import org.jclouds.aws.xml.TemporaryCredentialsHandlerTest;
|
||||||
import org.jclouds.date.TimeStamp;
|
import org.jclouds.date.TimeStamp;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.IntegrationTestAsyncClient;
|
import org.jclouds.http.IntegrationTestAsyncClient;
|
||||||
import org.jclouds.http.IntegrationTestClient;
|
import org.jclouds.http.IntegrationTestClient;
|
||||||
|
@ -33,6 +36,7 @@ import org.jclouds.rest.RequestSigner;
|
||||||
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
import org.jclouds.rest.internal.BaseRestApiTest.MockModule;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
@ -45,49 +49,63 @@ import com.google.inject.name.Names;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during
|
||||||
@Test(groups = "unit", testName = "FormSignerTest")
|
// surefire
|
||||||
|
@Test(groups = "unit", singleThreaded = true, testName = "FormSignerTest")
|
||||||
public class FormSignerTest {
|
public class FormSignerTest {
|
||||||
public static final Injector INJECTOR = ContextBuilder
|
public static Injector injector(Credentials creds) {
|
||||||
.newBuilder(
|
return ContextBuilder
|
||||||
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class, IntegrationTestAsyncClient.class,
|
.newBuilder(
|
||||||
"http://localhost"))
|
AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(IntegrationTestClient.class,
|
||||||
.credentials("identity", "credential")
|
IntegrationTestAsyncClient.class, "http://localhost"))
|
||||||
.apiVersion("apiVersion")
|
.credentialsSupplier(Suppliers.<Credentials> ofInstance(creds)).apiVersion("apiVersion")
|
||||||
.modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule(),
|
.modules(ImmutableList.<Module> of(new MockModule(), new NullLoggingModule(), new AbstractModule() {
|
||||||
new AbstractModule() {
|
@Override
|
||||||
@Override
|
protected void configure() {
|
||||||
protected void configure() {
|
bind(RequestSigner.class).to(FormSigner.class);
|
||||||
bind(RequestSigner.class).to(FormSigner.class);
|
bind(String.class).annotatedWith(Names.named(PROPERTY_HEADER_TAG)).toInstance("amz");
|
||||||
bind(String.class).annotatedWith(Names.named(PROPERTY_HEADER_TAG)).toInstance("amz");
|
bind(String.class).annotatedWith(TimeStamp.class).toInstance("2009-11-08T15:54:08.897Z");
|
||||||
bind(String.class).annotatedWith(TimeStamp.class).toInstance("2009-11-08T15:54:08.897Z");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
})).buildInjector();
|
})).buildInjector();
|
||||||
FormSigner filter = INJECTOR.getInstance(FormSigner.class);
|
}
|
||||||
|
|
||||||
|
public static FormSigner filter(Credentials creds) {
|
||||||
|
return injector(creds).getInstance(FormSigner.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FormSigner staticCredentialsFilter = filter(new Credentials("identity", "credential"));
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.builder().method("GET")
|
||||||
|
.endpoint("http://localhost")
|
||||||
|
.addHeader(HttpHeaders.HOST, "localhost")
|
||||||
|
.addFormParam("Action", "DescribeImages")
|
||||||
|
.addFormParam("ImageId.1", "ami-2bb65342").build();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testAddsSecurityToken() {
|
||||||
|
HttpRequest filtered = filter(new TemporaryCredentialsHandlerTest().expected()).filter(request);
|
||||||
|
assertEquals(
|
||||||
|
filtered.getPayload().getRawContent(),
|
||||||
|
"Action=DescribeImages&ImageId.1=ami-2bb65342&Signature=waV%2B%2BIdRwHRlnK2126CqgHHd4FZb%2B5wAeRueidjFc/M%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=apiVersion&AWSAccessKeyId=AKIAIOSFODNN7EXAMPLE");
|
||||||
|
assertEquals(filtered.getFirstHeaderOrNull("SecurityToken"), "AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testBuildCanonicalizedStringSetsVersion() {
|
void testBuildCanonicalizedStringSetsVersion() {
|
||||||
|
HttpRequest filtered = staticCredentialsFilter.filter(request);
|
||||||
assertEquals(
|
assertEquals(filtered.getPayload().getRawContent(),
|
||||||
filter.filter(
|
"Action=DescribeImages&ImageId.1=ami-2bb65342&Signature=ugnt4m2eHE7Ka/vXTr9EhKZq7bhxOfvW0y4pAEqF97w%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=apiVersion&AWSAccessKeyId=identity");
|
||||||
HttpRequest.builder()
|
|
||||||
.method("GET")
|
|
||||||
.endpoint("http://localhost")
|
|
||||||
.addHeader(HttpHeaders.HOST, "localhost")
|
|
||||||
.payload("Action=DescribeImages&ImageId.1=ami-2bb65342").build())
|
|
||||||
.getPayload().getRawContent(),
|
|
||||||
"Action=DescribeImages&ImageId.1=ami-2bb65342&Signature=ugnt4m2eHE7Ka/vXTr9EhKZq7bhxOfvW0y4pAEqF97w%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Version=apiVersion&AWSAccessKeyId=identity");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testBuildCanonicalizedString() {
|
void testBuildCanonicalizedString() {
|
||||||
assertEquals(
|
assertEquals(
|
||||||
filter.buildCanonicalizedString(new ImmutableMultimap.Builder<String, String>().put("AWSAccessKeyId",
|
staticCredentialsFilter.buildCanonicalizedString(new ImmutableMultimap.Builder<String, String>()
|
||||||
"foo").put("Action", "DescribeImages").put("Expires", "2008-02-10T12:00:00Z").put("ImageId.1",
|
.put("AWSAccessKeyId", "foo").put("Action", "DescribeImages").put("Expires", "2008-02-10T12:00:00Z")
|
||||||
"ami-2bb65342").put("SignatureMethod", "HmacSHA256").put("SignatureVersion", "2").put(
|
.put("ImageId.1", "ami-2bb65342").put("SignatureMethod", "HmacSHA256").put("SignatureVersion", "2")
|
||||||
"Version", "2010-06-15").build()),
|
.put("Version", "2010-06-15").build()),
|
||||||
"AWSAccessKeyId=foo&Action=DescribeImages&Expires=2008-02-10T12%3A00%3A00Z&ImageId.1=ami-2bb65342&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-06-15");
|
"AWSAccessKeyId=foo&Action=DescribeImages&Expires=2008-02-10T12%3A00%3A00Z&ImageId.1=ami-2bb65342&SignatureMethod=HmacSHA256&SignatureVersion=2&Version=2010-06-15");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||||
|
|
||||||
import org.jclouds.aws.domain.AWSError;
|
import org.jclouds.aws.domain.AWSError;
|
||||||
import org.jclouds.aws.filters.FormSignerTest;
|
import org.jclouds.aws.filters.FormSignerTest;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.http.HttpCommand;
|
import org.jclouds.http.HttpCommand;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
|
@ -49,7 +50,7 @@ public class AWSUtilsTest {
|
||||||
@BeforeTest
|
@BeforeTest
|
||||||
protected void setUpInjector() throws IOException {
|
protected void setUpInjector() throws IOException {
|
||||||
|
|
||||||
utils = FormSignerTest.INJECTOR.getInstance(AWSUtils.class);
|
utils = FormSignerTest.injector(new Credentials("identity", "credential")).getInstance(AWSUtils.class);
|
||||||
|
|
||||||
command = createMock(HttpCommand.class);
|
command = createMock(HttpCommand.class);
|
||||||
expect(command.getCurrentRequest()).andReturn(createMock(HttpRequest.class)).atLeastOnce();
|
expect(command.getCurrentRequest()).andReturn(createMock(HttpRequest.class)).atLeastOnce();
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* 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.aws.xml;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.jclouds.aws.domain.TemporaryCredentials;
|
||||||
|
import org.jclouds.aws.xml.TemporaryCredentialsHandler;
|
||||||
|
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||||
|
import org.jclouds.http.functions.BaseHandlerTest;
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
|
||||||
|
@Test(groups = "unit", testName = "TemporaryCredentialsHandlerTest")
|
||||||
|
public class TemporaryCredentialsHandlerTest extends BaseHandlerTest {
|
||||||
|
|
||||||
|
public void test() {
|
||||||
|
InputStream is = getClass().getResourceAsStream("/credentials.xml");
|
||||||
|
|
||||||
|
TemporaryCredentials expected = expected();
|
||||||
|
|
||||||
|
TemporaryCredentialsHandler handler = injector.getInstance(TemporaryCredentialsHandler.class);
|
||||||
|
TemporaryCredentials result = factory.create(handler).parse(is);
|
||||||
|
|
||||||
|
assertEquals(result, expected);
|
||||||
|
assertEquals(result.getAccessKeyId(), expected.getAccessKeyId());
|
||||||
|
assertEquals(result.getSecretAccessKey(), expected.getSecretAccessKey());
|
||||||
|
assertEquals(result.getSessionToken(), expected.getSessionToken());
|
||||||
|
assertEquals(result.getExpiration(), expected.getExpiration());
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemporaryCredentials expected() {
|
||||||
|
return TemporaryCredentials.builder()
|
||||||
|
.accessKeyId("AKIAIOSFODNN7EXAMPLE")
|
||||||
|
.secretAccessKey("wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY")
|
||||||
|
.sessionToken("AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT")
|
||||||
|
.expiration(new SimpleDateFormatDateService().iso8601DateParse("2011-07-11T19:55:29.611Z")).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<Credentials>
|
||||||
|
<SessionToken>AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT</SessionToken>
|
||||||
|
<SecretAccessKey>wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY</SecretAccessKey>
|
||||||
|
<Expiration>2011-07-11T19:55:29.611Z</Expiration>
|
||||||
|
<AccessKeyId>AKIAIOSFODNN7EXAMPLE</AccessKeyId>
|
||||||
|
</Credentials>
|
|
@ -297,11 +297,17 @@ public class ContextBuilder {
|
||||||
|
|
||||||
Properties unexpanded = currentStateToUnexpandedProperties();
|
Properties unexpanded = currentStateToUnexpandedProperties();
|
||||||
|
|
||||||
ImmutableSet<String> keysToResolve = ImmutableSet.of(PROPERTY_ENDPOINT, PROPERTY_IDENTITY, PROPERTY_CREDENTIAL,
|
Set<String> keysToResolve = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL, PROPERTY_ENDPOINT,
|
||||||
PROPERTY_API, PROPERTY_API_VERSION, PROPERTY_BUILD_VERSION);
|
PROPERTY_API, PROPERTY_API_VERSION, PROPERTY_BUILD_VERSION);
|
||||||
|
|
||||||
ImmutableSet<String> optionalKeys = apiMetadata.getCredentialName().isPresent() ? ImmutableSet.<String> of()
|
Set<String> optionalKeys;
|
||||||
: ImmutableSet.of(PROPERTY_CREDENTIAL);
|
if (credentialsSupplierOption.isPresent()) {
|
||||||
|
optionalKeys = ImmutableSet.of(PROPERTY_IDENTITY, PROPERTY_CREDENTIAL);
|
||||||
|
} else if (!apiMetadata.getCredentialName().isPresent()) {
|
||||||
|
optionalKeys = ImmutableSet.of(PROPERTY_CREDENTIAL);
|
||||||
|
} else {
|
||||||
|
optionalKeys = ImmutableSet.of();
|
||||||
|
}
|
||||||
|
|
||||||
Properties resolved = resolveProperties(unexpanded, providerId, keysToResolve, optionalKeys);
|
Properties resolved = resolveProperties(unexpanded, providerId, keysToResolve, optionalKeys);
|
||||||
|
|
||||||
|
@ -401,8 +407,8 @@ public class ContextBuilder {
|
||||||
String scopedProperty = ImmutableList.copyOf(Splitter.on('.').split(key)).get(1);
|
String scopedProperty = ImmutableList.copyOf(Splitter.on('.').split(key)).get(1);
|
||||||
mutable.setProperty(key, searchPropertiesForProviderScopedProperty(mutable, providerId,scopedProperty));
|
mutable.setProperty(key, searchPropertiesForProviderScopedProperty(mutable, providerId,scopedProperty));
|
||||||
} catch (NoSuchElementException e){
|
} catch (NoSuchElementException e){
|
||||||
if (!optionalKeys.contains(key))
|
if (!optionalKeys.contains(key))
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return mutable;
|
return mutable;
|
||||||
|
|
|
@ -64,10 +64,7 @@ public class ContextBuilderTest {
|
||||||
|
|
||||||
@ConfiguresHttpCommandExecutorService
|
@ConfiguresHttpCommandExecutorService
|
||||||
static class HttpModule extends AbstractModule {
|
static class HttpModule extends AbstractModule {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +121,6 @@ public class ContextBuilderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProviderMetadataWithCredentialsSetSupplier() {
|
public void testProviderMetadataWithCredentialsSetSupplier() {
|
||||||
Properties overrides = new Properties();
|
|
||||||
overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo");
|
|
||||||
overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR");
|
|
||||||
ContextBuilder withCredsSupplier = testContextBuilder().credentialsSupplier(
|
ContextBuilder withCredsSupplier = testContextBuilder().credentialsSupplier(
|
||||||
ofInstance(new Credentials("foo", "BAR")));
|
ofInstance(new Credentials("foo", "BAR")));
|
||||||
Credentials creds = withCredsSupplier.buildInjector()
|
Credentials creds = withCredsSupplier.buildInjector()
|
||||||
|
@ -239,14 +233,10 @@ public class ContextBuilderTest {
|
||||||
public void testBuilder() {
|
public void testBuilder() {
|
||||||
|
|
||||||
Module module1 = new AbstractModule() {
|
Module module1 = new AbstractModule() {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Module module2 = new AbstractModule() {
|
Module module2 = new AbstractModule() {
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue