Merge pull request #1181 from jclouds/dynamic-credentials

Dynamic credentials
This commit is contained in:
Adrian Cole 2013-01-16 06:44:00 -08:00
commit 4fbb70be7b
60 changed files with 1005 additions and 1070 deletions

View File

@ -37,11 +37,10 @@ import javax.inject.Singleton;
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.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -58,8 +57,7 @@ import com.google.common.io.ByteProcessor;
@Singleton @Singleton
public class ShareUrl implements Function<String, URI> { public class ShareUrl implements Function<String, URI> {
private final String uid; private final Supplier<Credentials> creds;
private final byte[] key;
private final Supplier<URI> provider; private final Supplier<URI> provider;
private final javax.inject.Provider<Long> timeStampProvider; private final javax.inject.Provider<Long> timeStampProvider;
private final Crypto crypto; private final Crypto crypto;
@ -72,10 +70,9 @@ public class ShareUrl implements Function<String, URI> {
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
public ShareUrl(@Identity String uid, @Credential String encodedKey, public ShareUrl(@Provider Supplier<Credentials> creds, @Provider Supplier<URI> provider,
@Provider Supplier<URI> provider, @TimeStamp javax.inject.Provider<Long> timeStampProvider, Crypto crypto) { @TimeStamp javax.inject.Provider<Long> timeStampProvider, Crypto crypto) {
this.uid = uid; this.creds = creds;
this.key = base64().decode(encodedKey);
this.provider = provider; this.provider = provider;
this.timeStampProvider = timeStampProvider; this.timeStampProvider = timeStampProvider;
this.crypto = crypto; this.crypto = crypto;
@ -87,7 +84,7 @@ public class ShareUrl implements Function<String, URI> {
String expires = timeStampProvider.get().toString(); String expires = timeStampProvider.get().toString();
String signature = signString(createStringToSign(requestedResource, expires)); String signature = signString(createStringToSign(requestedResource, expires));
return uriBuilder(provider.get()) return uriBuilder(provider.get())
.replaceQuery(ImmutableMap.of("uid", uid, "expires", expires, "signature", signature)) .replaceQuery(ImmutableMap.of("uid", creds.get().identity, "expires", expires, "signature", signature))
.appendPath(requestedResource).build(); .appendPath(requestedResource).build();
} }
@ -95,14 +92,14 @@ public class ShareUrl implements Function<String, URI> {
StringBuilder toSign = new StringBuilder(); StringBuilder toSign = new StringBuilder();
toSign.append("GET\n"); toSign.append("GET\n");
toSign.append(requestedResource.toLowerCase()).append("\n"); toSign.append(requestedResource.toLowerCase()).append("\n");
toSign.append(uid).append("\n"); toSign.append(creds.get().identity).append("\n");
toSign.append(expires); toSign.append(expires);
return toSign.toString(); return toSign.toString();
} }
public String signString(String toSign) { public String signString(String toSign) {
try { try {
ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(key)); ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(base64().decode(creds.get().credential)));
return base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); return base64().encode(readBytes(toInputStream(toSign), hmacSHA1));
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
throw propagate(e); throw propagate(e);

View File

@ -38,18 +38,18 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.atmos.reference.AtmosHeaders; import org.jclouds.atmos.reference.AtmosHeaders;
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.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire; import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Multimaps; import com.google.common.collect.Multimaps;
@ -67,8 +67,7 @@ import com.google.common.io.ByteProcessor;
public class SignRequest implements HttpRequestFilter { public class SignRequest implements HttpRequestFilter {
private final SignatureWire signatureWire; private final SignatureWire signatureWire;
private final String uid; private final Supplier<Credentials> creds;
private final byte[] key;
private final Provider<String> timeStampProvider; private final Provider<String> timeStampProvider;
private final Crypto crypto; private final Crypto crypto;
private final HttpUtils utils; private final HttpUtils utils;
@ -81,12 +80,10 @@ public class SignRequest implements HttpRequestFilter {
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
public SignRequest(SignatureWire signatureWire, @Identity String uid, public SignRequest(SignatureWire signatureWire, @org.jclouds.location.Provider Supplier<Credentials> creds,
@Credential String encodedKey, @TimeStamp Provider<String> timeStampProvider, Crypto crypto, @TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) {
HttpUtils utils) {
this.signatureWire = signatureWire; this.signatureWire = signatureWire;
this.uid = uid; this.creds = creds;
this.key = base64().decode(encodedKey);
this.timeStampProvider = timeStampProvider; this.timeStampProvider = timeStampProvider;
this.crypto = crypto; this.crypto = crypto;
this.utils = utils; this.utils = utils;
@ -95,7 +92,7 @@ public class SignRequest implements HttpRequestFilter {
@Override @Override
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
Builder<String, String> builder = ImmutableMap.builder(); Builder<String, String> builder = ImmutableMap.builder();
builder.put(AtmosHeaders.UID, uid); builder.put(AtmosHeaders.UID, creds.get().identity);
String date = timeStampProvider.get(); String date = timeStampProvider.get();
builder.put(HttpHeaders.DATE, date); builder.put(HttpHeaders.DATE, date);
if (request.getHeaders().containsKey(AtmosHeaders.DATE)) if (request.getHeaders().containsKey(AtmosHeaders.DATE))
@ -130,7 +127,7 @@ public class SignRequest implements HttpRequestFilter {
public String signString(String toSign) { public String signString(String toSign) {
try { try {
ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(key)); ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(base64().decode(creds.get().credential)));
return base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); return base64().encode(readBytes(toInputStream(toSign), hmacSHA1));
} catch (Exception e) { } catch (Exception e) {
throw new HttpException("error signing request", e); throw new HttpException("error signing request", e);

View File

@ -18,11 +18,9 @@
*/ */
package org.jclouds.cloudstack.config; package org.jclouds.cloudstack.config;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi; import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.Constants; import org.jclouds.Constants;
@ -280,15 +278,11 @@ public class CloudStackRestClientModule extends RestClientModule<CloudStackClien
@Provides @Provides
@Singleton @Singleton
protected Supplier<LoginResponse> provideLoginResponseSupplier(final LoadingCache<Credentials, LoginResponse> cache, protected Supplier<LoginResponse> provideLoginResponseSupplier(final LoadingCache<Credentials, LoginResponse> cache,
@Provider final Credentials creds) { @Provider final Supplier<Credentials> creds) {
return new Supplier<LoginResponse>() { return new Supplier<LoginResponse>() {
@Override @Override
public LoginResponse get() { public LoginResponse get() {
try { return cache.getUnchecked(creds.get());
return cache.get(creds);
} catch (ExecutionException e) {
throw propagate(e.getCause());
}
} }
}; };
} }

View File

@ -38,16 +38,17 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire; import org.jclouds.http.internal.SignatureWire;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner; import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap; import com.google.common.collect.TreeMultimap;
@ -63,8 +64,7 @@ import com.google.common.io.ByteProcessor;
public class QuerySigner implements AuthenticationFilter, RequestSigner { public class QuerySigner implements AuthenticationFilter, RequestSigner {
private final SignatureWire signatureWire; private final SignatureWire signatureWire;
private final String accessKey; private final Supplier<Credentials> creds;
private final String secretKey;
private final Crypto crypto; private final Crypto crypto;
private final HttpUtils utils; private final HttpUtils utils;
@ -73,11 +73,9 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner {
private Logger signatureLog = Logger.NULL; private Logger signatureLog = Logger.NULL;
@Inject @Inject
public QuerySigner(SignatureWire signatureWire, @Identity String accessKey, @Credential String secretKey, public QuerySigner(SignatureWire signatureWire, @Provider Supplier<Credentials> creds, Crypto crypto, HttpUtils utils) {
Crypto crypto, HttpUtils utils) {
this.signatureWire = signatureWire; this.signatureWire = signatureWire;
this.accessKey = accessKey; this.creds = creds;
this.secretKey = secretKey;
this.crypto = crypto; this.crypto = crypto;
this.utils = utils; this.utils = utils;
} }
@ -103,7 +101,7 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner {
public String sign(String toSign) { public String sign(String toSign) {
String signature; String signature;
try { try {
ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(secretKey.getBytes())); ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(creds.get().credential.getBytes()));
signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA1));
if (signatureWire.enabled()) if (signatureWire.enabled())
signatureWire.input(toInputStream(signature)); signatureWire.input(toInputStream(signature));
@ -130,7 +128,7 @@ public class QuerySigner implements AuthenticationFilter, RequestSigner {
@VisibleForTesting @VisibleForTesting
void addSigningParams(Multimap<String, String> params) { void addSigningParams(Multimap<String, String> params) {
params.replaceValues("apiKey", ImmutableList.of(accessKey)); params.replaceValues("apiKey", ImmutableList.of(creds.get().identity));
params.removeAll("signature"); params.removeAll("signature");
} }

View File

@ -28,8 +28,9 @@ import javax.inject.Inject;
import org.jclouds.cloudstack.CloudStackClient; import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.User; import org.jclouds.cloudstack.domain.User;
import org.jclouds.cloudstack.predicates.UserPredicates; import org.jclouds.cloudstack.predicates.UserPredicates;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -45,18 +46,18 @@ public class GetCurrentUser implements Supplier<User> {
protected Logger logger = Logger.NULL; protected Logger logger = Logger.NULL;
private final CloudStackClient client; private final CloudStackClient client;
private final String identity; private final Supplier<Credentials> creds;
@Inject @Inject
public GetCurrentUser(CloudStackClient client, @Identity String identity) { public GetCurrentUser(CloudStackClient client, @Provider Supplier<Credentials> creds) {
this.client = checkNotNull(client, "client"); this.client = checkNotNull(client, "client");
this.identity = checkNotNull(identity, "identity"); this.creds = checkNotNull(creds, "creds");
} }
@Override @Override
public User get() { public User get() {
Iterable<User> users = Iterables.concat(client.getAccountClient().listAccounts()); Iterable<User> users = Iterables.concat(client.getAccountClient().listAccounts());
Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(identity); Predicate<User> apiKeyMatches = UserPredicates.apiKeyEquals(creds.get().identity);
User currentUser = null; User currentUser = null;
try { try {
currentUser = Iterables.find(users, apiKeyMatches); currentUser = Iterables.find(users, apiKeyMatches);

View File

@ -62,13 +62,13 @@ import org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCred
import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate; import org.jclouds.compute.strategy.PrioritizeCredentialsFromTemplate;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.rest.annotations.Identity;
import org.testng.annotations.AfterGroups; import org.testng.annotations.AfterGroups;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -103,7 +103,6 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
@Override @Override
protected void configure() { protected void configure() {
bindProperties(binder(), setupProperties()); bindProperties(binder(), setupProperties());
bind(String.class).annotatedWith(Identity.class).toInstance(identity);
bind(new TypeLiteral<Supplier<User>>() { bind(new TypeLiteral<Supplier<User>>() {
}).annotatedWith(Memoized.class).to(GetCurrentUser.class).in(Scopes.SINGLETON); }).annotatedWith(Memoized.class).to(GetCurrentUser.class).in(Scopes.SINGLETON);
bind(new TypeLiteral<Supplier<Map<String, Network>>>() { bind(new TypeLiteral<Supplier<Map<String, Network>>>() {
@ -124,6 +123,12 @@ public class CloudStackComputeServiceAdapterLiveTest extends BaseCloudStackClien
to(ZoneIdToZoneSupplier.class); to(ZoneIdToZoneSupplier.class);
install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class)); install(new FactoryModuleBuilder().build(StaticNATVirtualMachineInNetwork.Factory.class));
} }
@Provides
@Singleton
Supplier<Credentials> supplyCredentials(){
return Suppliers.ofInstance(new Credentials(identity, credential));
}
@Provides @Provides
@Singleton @Singleton

View File

@ -21,9 +21,12 @@ package org.jclouds.ec2.options;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.options.internal.BaseEC2RequestOptions; import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
import org.jclouds.rest.annotations.Identity; import org.jclouds.location.Provider;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.inject.Inject; import com.google.inject.Inject;
@ -49,15 +52,16 @@ import com.google.inject.Inject;
*/ */
public class BundleInstanceS3StorageOptions extends BaseEC2RequestOptions { public class BundleInstanceS3StorageOptions extends BaseEC2RequestOptions {
@Inject(optional = true) @Inject
@Identity @VisibleForTesting
String currentAwsAccessKeyId; @Provider
Supplier<Credentials> creds;
@Override @Override
public Multimap<String, String> buildFormParameters() { public Multimap<String, String> buildFormParameters() {
if (getAwsAccessKeyId() == null) { if (getAwsAccessKeyId() == null) {
checkState(currentAwsAccessKeyId != null, "currentAwsAccessKeyId should have been injected"); checkState(creds != null, "creds should have been injected");
bucketOwnedBy(currentAwsAccessKeyId); bucketOwnedBy(creds.get().identity);
} }
return super.buildFormParameters(); return super.buildFormParameters();
} }
@ -82,11 +86,11 @@ public class BundleInstanceS3StorageOptions extends BaseEC2RequestOptions {
public static class Builder { public static class Builder {
/** /**
* @see BundleInstanceS3StorageOptions#bucketOwnedBy(ccessKeyId) * @see BundleInstanceS3StorageOptions#bucketOwnedBy(accessKeyId)
*/ */
public static BundleInstanceS3StorageOptions bucketOwnedBy(String ccessKeyId) { public static BundleInstanceS3StorageOptions bucketOwnedBy(String accessKeyId) {
BundleInstanceS3StorageOptions options = new BundleInstanceS3StorageOptions(); BundleInstanceS3StorageOptions options = new BundleInstanceS3StorageOptions();
return options.bucketOwnedBy(ccessKeyId); return options.bucketOwnedBy(accessKeyId);
} }
} }

View File

@ -21,11 +21,13 @@ package org.jclouds.ec2.options;
import static org.jclouds.ec2.options.BundleInstanceS3StorageOptions.Builder.bucketOwnedBy; import static org.jclouds.ec2.options.BundleInstanceS3StorageOptions.Builder.bucketOwnedBy;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import com.google.common.collect.ImmutableList; import org.jclouds.domain.Credentials;
import org.jclouds.http.options.HttpRequestOptions; import org.jclouds.http.options.HttpRequestOptions;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
/** /**
* Tests possible uses of BundleInstanceS3StorageOptions and * Tests possible uses of BundleInstanceS3StorageOptions and
* BundleInstanceS3StorageOptions.Builder.* * BundleInstanceS3StorageOptions.Builder.*
@ -56,7 +58,7 @@ public class BundleInstanceS3StorageOptionsTest {
@Test @Test
public void testNullBucketOwnedBy() { public void testNullBucketOwnedBy() {
BundleInstanceS3StorageOptions options = new BundleInstanceS3StorageOptions(); BundleInstanceS3StorageOptions options = new BundleInstanceS3StorageOptions();
options.currentAwsAccessKeyId = "foo"; options.creds = Suppliers.ofInstance(new Credentials("foo", null));
assertEquals(options.buildFormParameters().get("Storage.S3.AWSAccessKeyId"), ImmutableList.of("foo")); assertEquals(options.buildFormParameters().get("Storage.S3.AWSAccessKeyId"), ImmutableList.of("foo"));
} }

View File

@ -19,7 +19,6 @@
package org.jclouds.openstack.keystone.v2_0.config; package org.jclouds.openstack.keystone.v2_0.config;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi; import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.util.Map; import java.util.Map;
@ -194,15 +193,11 @@ public class KeystoneAuthenticationModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Supplier<Access> provideAccessSupplier(final LoadingCache<Credentials, Access> cache, protected Supplier<Access> provideAccessSupplier(final LoadingCache<Credentials, Access> cache,
@Provider final Credentials creds) { @Provider final Supplier<Credentials> creds) {
return new Supplier<Access>() { return new Supplier<Access>() {
@Override @Override
public Access get() { public Access get() {
try { return cache.getUnchecked(creds.get());
return cache.get(creds);
} catch (ExecutionException e) {
throw propagate(e.getCause());
}
} }
}; };
} }

View File

@ -45,6 +45,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants; import org.jclouds.Constants;
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.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
@ -52,12 +53,11 @@ import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire; import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner; import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.s3.util.S3Utils; import org.jclouds.s3.util.S3Utils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -86,8 +86,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
"response-cache-control", "response-content-disposition", "response-content-encoding", "delete"); "response-cache-control", "response-content-disposition", "response-content-encoding", "delete");
private final SignatureWire signatureWire; private final SignatureWire signatureWire;
private final String accessKey; private final Supplier<Credentials> creds;
private final String secretKey;
private final Provider<String> timeStampProvider; private final Provider<String> timeStampProvider;
private final Crypto crypto; private final Crypto crypto;
private final HttpUtils utils; private final HttpUtils utils;
@ -105,15 +104,14 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
public RequestAuthorizeSignature(SignatureWire signatureWire, @Named(PROPERTY_AUTH_TAG) String authTag, public RequestAuthorizeSignature(SignatureWire signatureWire, @Named(PROPERTY_AUTH_TAG) String authTag,
@Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle, @Named(PROPERTY_S3_VIRTUAL_HOST_BUCKETS) boolean isVhostStyle,
@Named(PROPERTY_S3_SERVICE_PATH) String servicePath, @Named(PROPERTY_HEADER_TAG) String headerTag, @Named(PROPERTY_S3_SERVICE_PATH) String servicePath, @Named(PROPERTY_HEADER_TAG) String headerTag,
@Identity String accessKey, @Credential String secretKey, @org.jclouds.location.Provider Supplier<Credentials> creds,
@TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) { @TimeStamp Provider<String> timeStampProvider, Crypto crypto, HttpUtils utils) {
this.isVhostStyle = isVhostStyle; this.isVhostStyle = isVhostStyle;
this.servicePath = servicePath; this.servicePath = servicePath;
this.headerTag = headerTag; this.headerTag = headerTag;
this.authTag = authTag; this.authTag = authTag;
this.signatureWire = signatureWire; this.signatureWire = signatureWire;
this.accessKey = accessKey; this.creds = creds;
this.secretKey = secretKey;
this.timeStampProvider = timeStampProvider; this.timeStampProvider = timeStampProvider;
this.crypto = crypto; this.crypto = crypto;
this.utils = utils; this.utils = utils;
@ -128,7 +126,8 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
} }
HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
request = request.toBuilder().replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + accessKey + ":" + signature).build(); request = request.toBuilder()
.replaceHeader(HttpHeaders.AUTHORIZATION, authTag + " " + creds.get().identity + ":" + signature).build();
return request; return request;
} }
@ -168,7 +167,7 @@ public class RequestAuthorizeSignature implements HttpRequestFilter, RequestSign
public String sign(String toSign) { public String sign(String toSign) {
try { try {
ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(secretKey.getBytes(UTF_8))); ByteProcessor<byte[]> hmacSHA1 = asByteProcessor(crypto.hmacSHA1(creds.get().credential.getBytes(UTF_8)));
return base64().encode(readBytes(toInputStream(toSign), hmacSHA1)); return base64().encode(readBytes(toInputStream(toSign), hmacSHA1));
} catch (Exception e) { } catch (Exception e) {
throw new HttpException("error signing request", e); throw new HttpException("error signing request", e);

View File

@ -19,7 +19,6 @@
package org.jclouds.vcloud.config; package org.jclouds.vcloud.config;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_ORG; import static org.jclouds.vcloud.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_ORG;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,41 +30,31 @@ import org.jclouds.vcloud.domain.VCloudSession;
import org.jclouds.vcloud.endpoints.Org; import org.jclouds.vcloud.endpoints.Org;
import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; import org.jclouds.vcloud.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class DefaultOrgForUser implements Function<String, Supplier<ReferenceType>> { public class DefaultOrgForUser implements Supplier<ReferenceType> {
private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector;
private final Supplier<VCloudSession> sessionSupplier; private final Supplier<VCloudSession> session;
@Inject @Inject
public DefaultOrgForUser(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, public DefaultOrgForUser(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull,
@Org Predicate<ReferenceType> defaultSelector, Supplier<VCloudSession> sessionSupplier) { @Org Predicate<ReferenceType> defaultSelector, Supplier<VCloudSession> session) {
this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull(
valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_ORG, checkNotNull( valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_ORG, checkNotNull(
defaultSelector, "defaultSelector")); defaultSelector, "defaultSelector"));
this.sessionSupplier = checkNotNull(sessionSupplier, "sessionSupplier"); this.session = checkNotNull(session, "session");
} }
@Override @Override
public Supplier<ReferenceType> apply(final String user) { public ReferenceType get() {
return Suppliers.compose(new Function<VCloudSession, ReferenceType>() { return selector.apply(session.get().getOrgs().values());
@Override
public ReferenceType apply(VCloudSession session) {
checkState(session != null, "could not retrieve Session at %s", user);
return selector.apply(session.getOrgs().values());
}
}, sessionSupplier);
} }
} }

View File

@ -26,10 +26,9 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.util.Suppliers2;
import org.jclouds.vcloud.domain.Catalog; import org.jclouds.vcloud.domain.Catalog;
import org.jclouds.vcloud.domain.ReferenceType; import org.jclouds.vcloud.domain.ReferenceType;
import org.jclouds.vcloud.endpoints.Org;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -41,24 +40,18 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
public class DefaultVCloudReferencesModule extends AbstractModule { public class DefaultVCloudReferencesModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(new TypeLiteral<Supplier<ReferenceType>>() {
} }).annotatedWith(Org.class).to(DefaultOrgForUser.class);
@Provides
@org.jclouds.vcloud.endpoints.Org
@Singleton
protected Supplier<ReferenceType> provideDefaultOrg(DefaultOrgForUser defaultOrgURIForUser,
@Identity String user) {
return defaultOrgURIForUser.apply(user);
} }
@Provides @Provides

View File

@ -49,6 +49,7 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants; import org.jclouds.Constants;
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.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
@ -57,10 +58,9 @@ import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner; import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
@ -83,8 +83,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
private final SignatureWire signatureWire; private final SignatureWire signatureWire;
private final String apiVersion; private final String apiVersion;
private final String accessKey; private final Supplier<Credentials> creds;
private final String secretKey;
private final Provider<String> dateService; private final Provider<String> dateService;
private final Crypto crypto; private final Crypto crypto;
private final HttpUtils utils; private final HttpUtils utils;
@ -94,13 +93,12 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
private Logger signatureLog = Logger.NULL; private Logger signatureLog = Logger.NULL;
@Inject @Inject
public FormSigner(SignatureWire signatureWire, @ApiVersion String apiVersion, @Identity String accessKey, public FormSigner(SignatureWire signatureWire, @ApiVersion String apiVersion,
@Credential String secretKey, @TimeStamp Provider<String> dateService, @org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> dateService,
Crypto crypto, HttpUtils utils) { Crypto crypto, HttpUtils utils) {
this.signatureWire = signatureWire; this.signatureWire = signatureWire;
this.apiVersion = apiVersion; this.apiVersion = apiVersion;
this.accessKey = accessKey; this.creds = creds;
this.secretKey = secretKey;
this.dateService = dateService; this.dateService = dateService;
this.crypto = crypto; this.crypto = crypto;
this.utils = utils; this.utils = utils;
@ -168,7 +166,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
public String sign(String toSign) { public String sign(String toSign) {
String signature; String signature;
try { try {
ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(secretKey.getBytes(UTF_8))); ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(creds.get().credential.getBytes(UTF_8)));
signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA256)); signature = base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
if (signatureWire.enabled()) if (signatureWire.enabled())
signatureWire.input(toInputStream(signature)); signatureWire.input(toInputStream(signature));
@ -207,7 +205,7 @@ public class FormSigner implements HttpRequestFilter, RequestSigner {
params.replaceValues(SIGNATURE_METHOD, ImmutableList.of("HmacSHA256")); params.replaceValues(SIGNATURE_METHOD, ImmutableList.of("HmacSHA256"));
params.replaceValues(SIGNATURE_VERSION, ImmutableList.of("2")); params.replaceValues(SIGNATURE_VERSION, ImmutableList.of("2"));
params.replaceValues(TIMESTAMP, ImmutableList.of(dateService.get())); params.replaceValues(TIMESTAMP, ImmutableList.of(dateService.get()));
params.replaceValues(AWS_ACCESS_KEY_ID, ImmutableList.of(accessKey)); params.replaceValues(AWS_ACCESS_KEY_ID, ImmutableList.of(creds.get().identity));
params.removeAll(SIGNATURE); params.removeAll(SIGNATURE);
} }

View File

@ -37,18 +37,18 @@ import javax.ws.rs.core.HttpHeaders;
import org.jclouds.Constants; import org.jclouds.Constants;
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.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.internal.SignatureWire; import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.util.Strings2; import org.jclouds.util.Strings2;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder; import com.google.common.collect.ImmutableMap.Builder;
@ -68,8 +68,7 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
private static final Collection<String> FIRST_HEADERS_TO_SIGN = ImmutableList.of(HttpHeaders.DATE); private static final Collection<String> FIRST_HEADERS_TO_SIGN = ImmutableList.of(HttpHeaders.DATE);
private final SignatureWire signatureWire; private final SignatureWire signatureWire;
private final String identity; private final Supplier<Credentials> creds;
private final byte[] key;
private final Provider<String> timeStampProvider; private final Provider<String> timeStampProvider;
private final Crypto crypto; private final Crypto crypto;
private final HttpUtils utils; private final HttpUtils utils;
@ -79,14 +78,13 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
public SharedKeyLiteAuthentication(SignatureWire signatureWire, @Identity String identity, public SharedKeyLiteAuthentication(SignatureWire signatureWire,
@Credential String encodedKey, @TimeStamp Provider<String> timeStampProvider, @org.jclouds.location.Provider Supplier<Credentials> creds, @TimeStamp Provider<String> timeStampProvider,
Crypto crypto, HttpUtils utils) { Crypto crypto, HttpUtils utils) {
this.crypto = crypto; this.crypto = crypto;
this.utils = utils; this.utils = utils;
this.signatureWire = signatureWire; this.signatureWire = signatureWire;
this.identity = identity; this.creds = creds;
this.key = base64().decode(encodedKey);
this.timeStampProvider = timeStampProvider; this.timeStampProvider = timeStampProvider;
} }
@ -99,8 +97,9 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
} }
HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) { HttpRequest replaceAuthorizationHeader(HttpRequest request, String signature) {
return request.toBuilder().replaceHeader(HttpHeaders.AUTHORIZATION, "SharedKeyLite " + identity + ":" return request.toBuilder()
+ signature).build(); .replaceHeader(HttpHeaders.AUTHORIZATION, "SharedKeyLite " + creds.get().identity + ":" + signature)
.build();
} }
HttpRequest replaceDateHeader(HttpRequest request) { HttpRequest replaceDateHeader(HttpRequest request) {
@ -143,7 +142,7 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
public String signString(String toSign) { public String signString(String toSign) {
try { try {
ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(key)); ByteProcessor<byte[]> hmacSHA256 = asByteProcessor(crypto.hmacSHA256(base64().decode(creds.get().credential)));
return base64().encode(readBytes(toInputStream(toSign), hmacSHA256)); return base64().encode(readBytes(toInputStream(toSign), hmacSHA256));
} catch (Exception e) { } catch (Exception e) {
throw new HttpException("error signing request", e); throw new HttpException("error signing request", e);
@ -176,10 +175,9 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
@VisibleForTesting @VisibleForTesting
void appendCanonicalizedResource(HttpRequest request, StringBuilder toSign) { void appendCanonicalizedResource(HttpRequest request, StringBuilder toSign) {
// 1. Beginning with an empty string (""), append a forward slash (/), followed by the name of // 1. Beginning with an empty string (""), append a forward slash (/), followed by the name of
// the identity that owns the resource being accessed. // the identity that owns the resource being accessed.
toSign.append("/").append(identity); toSign.append("/").append(creds.get().identity);
appendUriPath(request, toSign); appendUriPath(request, toSign);
} }

View File

@ -110,11 +110,11 @@ public class OpenStackAuthenticationModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Supplier<AuthenticationResponse> provideAuthenticationResponseSupplier( protected Supplier<AuthenticationResponse> provideAuthenticationResponseSupplier(
final LoadingCache<Credentials, AuthenticationResponse> cache, @Provider final Credentials creds) { final LoadingCache<Credentials, AuthenticationResponse> cache, @Provider final Supplier<Credentials> creds) {
return new Supplier<AuthenticationResponse>() { return new Supplier<AuthenticationResponse>() {
@Override @Override
public AuthenticationResponse get() { public AuthenticationResponse get() {
return cache.getUnchecked(creds); return cache.getUnchecked(creds.get());
} }
}; };
} }

View File

@ -18,7 +18,6 @@
*/ */
package org.jclouds.openstack.keystone.v1_1.config; package org.jclouds.openstack.keystone.v1_1.config;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi; import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -112,15 +111,11 @@ public class AuthenticationServiceModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected Supplier<Auth> provideAuthSupplier(final LoadingCache<Credentials, Auth> cache, protected Supplier<Auth> provideAuthSupplier(final LoadingCache<Credentials, Auth> cache,
@Provider final Credentials creds) { @Provider final Supplier<Credentials> creds) {
return new Supplier<Auth>() { return new Supplier<Auth>() {
@Override @Override
public Auth get() { public Auth get() {
try { return cache.getUnchecked(creds.get());
return cache.get(creds);
} catch (ExecutionException e) {
throw propagate(e.getCause());
}
} }
}; };
} }

View File

@ -19,7 +19,6 @@
package org.jclouds.trmk.vcloud_0_8.config; package org.jclouds.trmk.vcloud_0_8.config;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_ORG; import static org.jclouds.trmk.vcloud_0_8.reference.VCloudConstants.PROPERTY_VCLOUD_DEFAULT_ORG;
import javax.inject.Inject; import javax.inject.Inject;
@ -31,41 +30,31 @@ import org.jclouds.trmk.vcloud_0_8.domain.VCloudSession;
import org.jclouds.trmk.vcloud_0_8.endpoints.Org; import org.jclouds.trmk.vcloud_0_8.endpoints.Org;
import org.jclouds.trmk.vcloud_0_8.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault; import org.jclouds.trmk.vcloud_0_8.suppliers.OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault;
import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Singleton @Singleton
public class DefaultOrgForUser implements Function<String, Supplier<ReferenceType>> { public class DefaultOrgForUser implements Supplier<ReferenceType> {
private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector; private final OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault selector;
private final Supplier<VCloudSession> sessionSupplier; private final Supplier<VCloudSession> session;
@Inject @Inject
public DefaultOrgForUser(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull, public DefaultOrgForUser(ValueOfConfigurationKeyOrNull valueOfConfigurationKeyOrNull,
@Org Predicate<ReferenceType> defaultSelector, Supplier<VCloudSession> sessionSupplier) { @Org Predicate<ReferenceType> defaultSelector, Supplier<VCloudSession> session) {
this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull( this.selector = new OnlyReferenceTypeFirstWithNameMatchingConfigurationKeyOrDefault(checkNotNull(
valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_ORG, checkNotNull( valueOfConfigurationKeyOrNull, "valueOfConfigurationKeyOrNull"), PROPERTY_VCLOUD_DEFAULT_ORG, checkNotNull(
defaultSelector, "defaultSelector")); defaultSelector, "defaultSelector"));
this.sessionSupplier = checkNotNull(sessionSupplier, "sessionSupplier"); this.session = checkNotNull(session, "session");
} }
@Override @Override
public Supplier<ReferenceType> apply(final String user) { public ReferenceType get() {
return Suppliers.compose(new Function<VCloudSession, ReferenceType>() { return selector.apply(session.get().getOrgs().values());
@Override
public ReferenceType apply(VCloudSession session) {
checkState(session != null, "could not retrieve Session at %s", user);
return selector.apply(session.getOrgs().values());
}
}, sessionSupplier);
} }
} }

View File

@ -23,10 +23,9 @@ import java.util.Map;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.trmk.vcloud_0_8.domain.Catalog; import org.jclouds.trmk.vcloud_0_8.domain.Catalog;
import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType; import org.jclouds.trmk.vcloud_0_8.domain.ReferenceType;
import org.jclouds.util.Suppliers2; import org.jclouds.trmk.vcloud_0_8.endpoints.Org;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
@ -38,6 +37,7 @@ import com.google.common.collect.ImmutableMap.Builder;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Provides; import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* *
@ -47,15 +47,8 @@ public class DefaultVCloudReferencesModule extends AbstractModule {
@Override @Override
protected void configure() { protected void configure() {
bind(new TypeLiteral<Supplier<ReferenceType>>() {
} }).annotatedWith(Org.class).to(DefaultOrgForUser.class);
@Provides
@org.jclouds.trmk.vcloud_0_8.endpoints.Org
@Singleton
protected Supplier<ReferenceType> provideDefaultOrg(DefaultOrgForUser defaultOrgURIForUser,
@Identity String user) {
return defaultOrgURIForUser.apply(user);
} }
@Provides @Provides

View File

@ -29,13 +29,15 @@ import javax.inject.Singleton;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.Processor; import org.jclouds.compute.domain.Processor;
import org.jclouds.compute.domain.Volume; import org.jclouds.compute.domain.Volume;
import org.jclouds.compute.domain.NodeMetadata.Status;
import org.jclouds.compute.domain.internal.VolumeImpl; import org.jclouds.compute.domain.internal.VolumeImpl;
import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;
import org.jclouds.predicates.SocketOpen; import org.jclouds.predicates.SocketOpen;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache; import com.google.common.cache.LoadingCache;
@ -68,9 +70,9 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected ConcurrentMap<String, NodeMetadata> provideNodesForIdentity(@Identity String identity) protected ConcurrentMap<String, NodeMetadata> provideNodesForIdentity(@Provider Supplier<Credentials> creds)
throws ExecutionException { throws ExecutionException {
return backing.get(identity); return backing.get(creds.get().identity);
} }
protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build( protected static final LoadingCache<String, AtomicInteger> nodeIds = CacheBuilder.newBuilder().build(
@ -85,8 +87,8 @@ public class StubComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Named("NODE_ID") @Named("NODE_ID")
protected Integer provideNodeIdForIdentity(@Identity String identity) throws ExecutionException { protected Integer provideNodeIdForIdentity(@Provider Supplier<Credentials> creds) throws ExecutionException {
return nodeIds.get(identity).incrementAndGet(); return nodeIds.get(creds.get().identity).incrementAndGet();
} }
@Singleton @Singleton

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds; package org.jclouds;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.containsPattern; import static com.google.common.base.Predicates.containsPattern;
import static com.google.common.base.Predicates.instanceOf; import static com.google.common.base.Predicates.instanceOf;
@ -30,6 +31,8 @@ import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.find; import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.newArrayListWithCapacity;
import static com.google.common.collect.Maps.filterKeys;
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor; import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
import static org.jclouds.Constants.PROPERTY_API; import static org.jclouds.Constants.PROPERTY_API;
import static org.jclouds.Constants.PROPERTY_API_VERSION; import static org.jclouds.Constants.PROPERTY_API_VERSION;
@ -84,12 +87,12 @@ import com.google.common.base.Objects;
import com.google.common.base.Optional; import com.google.common.base.Optional;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Splitter; import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
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.common.collect.ImmutableMultimap.Builder; import com.google.common.collect.ImmutableMultimap.Builder;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.common.util.concurrent.ExecutionList; import com.google.common.util.concurrent.ExecutionList;
import com.google.inject.Guice; import com.google.inject.Guice;
@ -189,18 +192,18 @@ public class ContextBuilder {
protected final String providerId; protected final String providerId;
protected Optional<String> endpoint = Optional.absent(); protected Optional<String> endpoint = Optional.absent();
protected Optional<String> identity = Optional.absent(); protected Optional<String> identity = Optional.absent();
protected Optional<Supplier<Credentials>> credentialsSupplierOption = Optional.absent();
@Nullable @Nullable
protected String credential; protected String credential;
protected ApiMetadata apiMetadata; protected ApiMetadata apiMetadata;
protected String apiVersion; protected String apiVersion;
protected String buildVersion; protected String buildVersion;
protected Optional<Properties> overrides = Optional.absent(); protected Optional<Properties> overrides = Optional.absent();
protected List<Module> modules = Lists.newArrayListWithCapacity(3); protected List<Module> modules = newArrayListWithCapacity(3);
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata) return toStringHelper("").add("providerMetadata", providerMetadata).add("apiMetadata", apiMetadata).toString();
.toString();
} }
protected ContextBuilder(ProviderMetadata providerMetadata) { protected ContextBuilder(ProviderMetadata providerMetadata) {
@ -232,6 +235,20 @@ public class ContextBuilder {
return this; return this;
} }
/**
* returns the current login credentials. jclouds will not cache this value. Use this when you need to change
* credentials at runtime.
*/
public ContextBuilder credentialsSupplier(Supplier<Credentials> credentialsSupplier) {
this.credentialsSupplierOption = Optional.of(checkNotNull(credentialsSupplier, "credentialsSupplier"));
return this;
}
/**
* constant value of the cloud identity and credential.
*
* @param credential (optional depending on {@link ApiMetadata#getCredentialName()}
*/
public ContextBuilder credentials(String identity, @Nullable String credential) { public ContextBuilder credentials(String identity, @Nullable String credential) {
this.identity = Optional.of(checkNotNull(identity, "identity")); this.identity = Optional.of(checkNotNull(identity, "identity"));
this.credential = credential; this.credential = credential;
@ -289,14 +306,29 @@ public class ContextBuilder {
Properties expanded = expandProperties(resolved); Properties expanded = expandProperties(resolved);
Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded, Supplier<Credentials> credentialsSupplier = buildCredentialsSupplier(expanded);
PROPERTY_CREDENTIAL));
ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata).apply(expanded); ProviderMetadata providerMetadata = new UpdateProviderMetadataFromProperties(apiMetadata, this.providerMetadata)
.apply(expanded);
//We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash is used to be something readable. // We use either the specified name (optional) or a hash of provider/api, endpoint, api version & identity. Hash
// is used to be something readable.
return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(), return buildInjector(name.or(String.valueOf(Objects.hashCode(providerMetadata.getId(),
providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), creds.identity))), providerMetadata, creds, modules); providerMetadata.getEndpoint(), providerMetadata.getApiMetadata().getVersion(), credentialsSupplier))),
providerMetadata, credentialsSupplier, modules);
}
protected Supplier<Credentials> buildCredentialsSupplier(Properties expanded) {
Credentials creds = new Credentials(getAndRemove(expanded, PROPERTY_IDENTITY), getAndRemove(expanded,
PROPERTY_CREDENTIAL));
Supplier<Credentials> credentialsSupplier;
if (credentialsSupplierOption.isPresent()) {
credentialsSupplier = credentialsSupplierOption.get();
} else {
credentialsSupplier = Suppliers.ofInstance(creds);
}
return credentialsSupplier;
} }
private static String getAndRemove(Properties expanded, String key) { private static String getAndRemove(Properties expanded, String key) {
@ -340,7 +372,7 @@ public class ContextBuilder {
return Guice.createInjector(new BindPropertiesToExpandedValues(resolved)).getInstance(Properties.class); return Guice.createInjector(new BindPropertiesToExpandedValues(resolved)).getInstance(Properties.class);
} }
public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Credentials creds, List<Module> inputModules) { public static Injector buildInjector(String name, ProviderMetadata providerMetadata, Supplier<Credentials> creds, List<Module> inputModules) {
List<Module> modules = newArrayList(); List<Module> modules = newArrayList();
modules.addAll(inputModules); modules.addAll(inputModules);
boolean restModuleSpecifiedByUser = restClientModulePresent(inputModules); boolean restModuleSpecifiedByUser = restClientModulePresent(inputModules);
@ -411,8 +443,7 @@ public class ContextBuilder {
@SuppressWarnings( { "unchecked" }) @SuppressWarnings( { "unchecked" })
static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId, static Map<String, Object> propertiesPrefixedWithJcloudsApiOrProviderId(Properties properties, String apiId,
String providerId) { String providerId) {
return Maps.filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId return filterKeys(Map.class.cast(properties), containsPattern("^(jclouds|" + providerId + "|" + apiId + ").*"));
+ ").*"));
} }
@VisibleForTesting @VisibleForTesting

View File

@ -26,12 +26,13 @@ import static java.lang.String.format;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.crypto.Crypto; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.annotations.Credential; import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
/** /**
* Uses Basic Authentication to sign the request. * Uses Basic Authentication to sign the request.
@ -43,22 +44,24 @@ import org.jclouds.rest.annotations.Identity;
@Singleton @Singleton
public class BasicAuthentication implements HttpRequestFilter { public class BasicAuthentication implements HttpRequestFilter {
private final String header; private final Supplier<Credentials> creds;
@Inject @Inject
public BasicAuthentication(@Identity String user, @Credential String password, Crypto crypto) { public BasicAuthentication(@Provider Supplier<Credentials> creds) {
checkNotNull(user, "user"); this.creds = checkNotNull(creds, "creds");
checkNotNull(password, "password");
this.header = basic(user, password);
} }
public static String basic(String user, String password) { public static String basic(String user, String password) {
return new StringBuilder("Basic ").append(base64().encode(format("%s:%s", user, password).getBytes(UTF_8))) return new StringBuilder("Basic ").append(
base64().encode(
format("%s:%s", checkNotNull(user, "user"), checkNotNull(password, "password")).getBytes(UTF_8)))
.toString(); .toString();
} }
@Override @Override
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
return request.toBuilder().replaceHeader(AUTHORIZATION, header).build(); Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
return request.toBuilder().replaceHeader(AUTHORIZATION, basic(currentCreds.identity, currentCreds.credential))
.build();
} }
} }

View File

@ -18,26 +18,31 @@
*/ */
package org.jclouds.internal; package org.jclouds.internal;
import com.google.common.base.Objects; import static com.google.common.base.Objects.equal;
import com.google.common.collect.ImmutableMap; import static com.google.common.base.Objects.toStringHelper;
import com.google.common.io.Closeables; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Singleton; import static com.google.common.io.Closeables.closeQuietly;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.jclouds.Context; import org.jclouds.Context;
import org.jclouds.annotations.Name; import org.jclouds.annotations.Name;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.domain.LocationScope; import org.jclouds.domain.LocationScope;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.location.Provider;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.Identity;
import javax.inject.Inject; import com.google.common.base.Objects;
import java.net.URI; import com.google.common.base.Supplier;
import java.util.Map; import com.google.common.collect.ImmutableMap;
import java.util.Set; import com.google.inject.Singleton;
import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -46,15 +51,16 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class ContextImpl implements Context { public class ContextImpl implements Context {
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final String identity; private final Supplier<Credentials> creds;
private final Utils utils; private final Utils utils;
private final Closer closer; private final Closer closer;
private final String name; private final String name;
@Inject @Inject
protected ContextImpl(@Name String name, ProviderMetadata providerMetadata, @Identity String identity, Utils utils, Closer closer) { protected ContextImpl(@Name String name, ProviderMetadata providerMetadata, @Provider Supplier<Credentials> creds,
Utils utils, Closer closer) {
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata"); this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
this.identity = checkNotNull(identity, "identity"); this.creds = checkNotNull(creds, "creds");
this.utils = checkNotNull(utils, "utils"); this.utils = checkNotNull(utils, "utils");
this.closer = checkNotNull(closer, "closer"); this.closer = checkNotNull(closer, "closer");
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
@ -65,7 +71,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public void close() { public void close() {
Closeables.closeQuietly(closer); closeQuietly(closer);
} }
/** /**
@ -89,7 +95,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public String getIdentity() { public String getIdentity() {
return identity; return creds.get().identity;
} }
/** /**
@ -134,7 +140,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hashCode(providerMetadata, identity); return Objects.hashCode(providerMetadata, creds);
} }
/** /**
@ -149,7 +155,7 @@ public class ContextImpl implements Context {
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
ContextImpl that = ContextImpl.class.cast(obj); ContextImpl that = ContextImpl.class.cast(obj);
return Objects.equal(this.providerMetadata, that.providerMetadata) && Objects.equal(this.identity, that.identity); return equal(this.providerMetadata, that.providerMetadata) && equal(this.creds, that.creds);
} }
/** /**
@ -157,7 +163,7 @@ public class ContextImpl implements Context {
*/ */
@Override @Override
public String toString() { public String toString() {
return Objects.toStringHelper("").add("providerMetadata", providerMetadata).add("identity", identity).toString(); return toStringHelper("").add("providerMetadata", providerMetadata).add("identity", getIdentity()).toString();
} }
/** /**
@ -191,7 +197,7 @@ public class ContextImpl implements Context {
public Map<String, Object> getMetadata() { public Map<String, Object> getMetadata() {
return ImmutableMap.<String, Object> of("endpoint", URI.create(providerMetadata.getEndpoint()), "apiVersion", return ImmutableMap.<String, Object> of("endpoint", URI.create(providerMetadata.getEndpoint()), "apiVersion",
providerMetadata.getApiMetadata().getVersion(), "buildVersion", providerMetadata.getApiMetadata() providerMetadata.getApiMetadata().getVersion(), "buildVersion", providerMetadata.getApiMetadata()
.getBuildVersion().or(""), "identity", identity); .getBuildVersion().or(""), "identity", getIdentity());
} }
/** /**

View File

@ -33,9 +33,8 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.annotations.Api; import org.jclouds.rest.annotations.Api;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.AbstractModule; import com.google.inject.AbstractModule;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -56,9 +55,9 @@ import com.google.inject.name.Names;
public class BindProviderMetadataContextAndCredentials extends AbstractModule { public class BindProviderMetadataContextAndCredentials extends AbstractModule {
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final Credentials creds; private final Supplier<Credentials> creds;
public BindProviderMetadataContextAndCredentials(ProviderMetadata providerMetadata, Credentials creds) { public BindProviderMetadataContextAndCredentials(ProviderMetadata providerMetadata, Supplier<Credentials> creds) {
this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata"); this.providerMetadata = checkNotNull(providerMetadata, "providerMetadata");
this.creds = checkNotNull(creds, "creds"); this.creds = checkNotNull(creds, "creds");
} }
@ -70,11 +69,7 @@ public class BindProviderMetadataContextAndCredentials extends AbstractModule {
toBind.putAll(providerMetadata.getApiMetadata().getDefaultProperties()); toBind.putAll(providerMetadata.getApiMetadata().getDefaultProperties());
toBind.putAll(providerMetadata.getDefaultProperties()); toBind.putAll(providerMetadata.getDefaultProperties());
Names.bindProperties(binder(), toBind); Names.bindProperties(binder(), toBind);
bind(Credentials.class).annotatedWith(Provider.class).toInstance(creds); bind(new TypeLiteral<Supplier<Credentials>>(){}).annotatedWith(Provider.class).toInstance(creds);
bindConstant().annotatedWith(Identity.class).to(creds.identity);
// nullable
bind(String.class).annotatedWith(Credential.class).toProvider(
com.google.inject.util.Providers.of(creds.credential));
bindConstant().annotatedWith(Provider.class).to(providerMetadata.getId()); bindConstant().annotatedWith(Provider.class).to(providerMetadata.getId());
bind(new TypeLiteral<Set<String>>() { bind(new TypeLiteral<Set<String>>() {
}).annotatedWith(Iso3166.class).toInstance(providerMetadata.getIso3166Codes()); }).annotatedWith(Iso3166.class).toInstance(providerMetadata.getIso3166Codes());

View File

@ -1,42 +0,0 @@
/**
* 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.rest.annotations;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Designates that this Resource qualifies an object to a key on a provider.
*
* @author Adrian Cole
*/
@Target( { ANNOTATION_TYPE, FIELD, METHOD, PARAMETER })
@Retention(RUNTIME)
@Qualifier
public @interface Credential {
}

View File

@ -1,42 +0,0 @@
/**
* 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.rest.annotations;
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* Designates that this Resource qualifies an object to an identity on a provider.
*
* @author Adrian Cole
*/
@Target( { ANNOTATION_TYPE, FIELD, METHOD, PARAMETER })
@Retention(RUNTIME)
@Qualifier
public @interface Identity {
}

View File

@ -23,13 +23,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.annotations.Name; import org.jclouds.annotations.Name;
import org.jclouds.domain.Credentials;
import org.jclouds.internal.ContextImpl; import org.jclouds.internal.ContextImpl;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.location.Provider;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@ -45,9 +47,10 @@ public class RestContextImpl<S, A> extends ContextImpl implements RestContext<S,
private final S syncApi; private final S syncApi;
@Inject @Inject
protected RestContextImpl(@Name String name, ProviderMetadata providerMetadata, @Identity String identity, Utils utils, Closer closer, protected RestContextImpl(@Name String name, ProviderMetadata providerMetadata,
Injector injector, TypeLiteral<S> syncApi, TypeLiteral<A> asyncApi) { @Provider Supplier<Credentials> creds, Utils utils, Closer closer, Injector injector, TypeLiteral<S> syncApi,
super(name, providerMetadata, identity, utils, closer); TypeLiteral<A> asyncApi) {
super(name, providerMetadata, creds, utils, closer);
checkNotNull(injector, "injector"); checkNotNull(injector, "injector");
this.asyncApi = injector.getInstance(Key.get(checkNotNull(asyncApi, "asyncApi"))); this.asyncApi = injector.getInstance(Key.get(checkNotNull(asyncApi, "asyncApi")));
this.syncApi = injector.getInstance(Key.get(checkNotNull(syncApi, "syncApi"))); this.syncApi = injector.getInstance(Key.get(checkNotNull(syncApi, "syncApi")));

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds; package org.jclouds;
import static com.google.common.base.Suppliers.ofInstance;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.net.URI; import java.net.URI;
@ -27,6 +28,7 @@ import java.util.Properties;
import java.util.Set; import java.util.Set;
import org.jclouds.concurrent.config.ExecutorServiceModule; import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.domain.Credentials;
import org.jclouds.events.config.EventBusModule; import org.jclouds.events.config.EventBusModule;
import org.jclouds.http.IntegrationTestAsyncClient; import org.jclouds.http.IntegrationTestAsyncClient;
import org.jclouds.http.IntegrationTestClient; import org.jclouds.http.IntegrationTestClient;
@ -40,7 +42,6 @@ import org.jclouds.providers.AnonymousProviderMetadata;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.CredentialStoreModule; import org.jclouds.rest.config.CredentialStoreModule;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -115,8 +116,23 @@ public class ContextBuilderTest {
overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo"); overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo");
overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR"); overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR");
ContextBuilder withCredsInProps = testContextBuilder().overrides(overrides); ContextBuilder withCredsInProps = testContextBuilder().overrides(overrides);
String identity = withCredsInProps.buildInjector().getInstance(Key.get(String.class, Identity.class)); Credentials creds = withCredsInProps.buildInjector()
assertEquals(identity, "foo"); .getInstance(Key.get(new TypeLiteral<Supplier<Credentials>>() {
}, Provider.class)).get();
assertEquals(creds, new Credentials("foo", "BAR"));
}
@Test
public void testProviderMetadataWithCredentialsSetSupplier() {
Properties overrides = new Properties();
overrides.setProperty(Constants.PROPERTY_IDENTITY, "foo");
overrides.setProperty(Constants.PROPERTY_CREDENTIAL, "BAR");
ContextBuilder withCredsSupplier = testContextBuilder().credentialsSupplier(
ofInstance(new Credentials("foo", "BAR")));
Credentials creds = withCredsSupplier.buildInjector()
.getInstance(Key.get(new TypeLiteral<Supplier<Credentials>>() {
}, Provider.class)).get();
assertEquals(creds, new Credentials("foo", "BAR"));
} }
@Test @Test

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.config; package org.jclouds.config;
import static com.google.common.base.Suppliers.ofInstance;
import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.createMock;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
@ -74,7 +75,7 @@ public class BindRestContextWithWildcardExtendsExplicitAndRawTypeTest {
private Injector injectorFor(ProviderMetadata md) { private Injector injectorFor(ProviderMetadata md) {
return Guice.createInjector( return Guice.createInjector(
new BindNameToContext("test"), new BindNameToContext("test"),
new BindProviderMetadataContextAndCredentials(md, new Credentials("user", "pass")), new BindProviderMetadataContextAndCredentials(md, ofInstance(new Credentials("user", "pass"))),
new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class.cast(md new BindRestContextWithWildcardExtendsExplicitAndRawType(RestApiMetadata.class.cast(md
.getApiMetadata())), .getApiMetadata())),

View File

@ -18,31 +18,50 @@
*/ */
package org.jclouds.http.filters; package org.jclouds.http.filters;
import static com.google.common.base.Suppliers.ofInstance;
import static com.google.common.collect.Queues.newArrayDeque;
import static com.google.common.net.HttpHeaders.AUTHORIZATION; import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static java.util.Arrays.asList;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import java.security.NoSuchAlgorithmException; import java.util.Deque;
import java.security.cert.CertificateException;
import org.jclouds.encryption.internal.JCECrypto; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
/** /**
* *
* @author Adrian Cole * @author Adrian Cole
*/ */
@Test(groups = "unit") @Test(groups = "unit")
public class BasicAuthenticationTest { public class BasicAuthenticationTest {
private static final Credentials credential1 = new Credentials("Aladdin", "open sesame");
private static final Credentials credential2 = new Credentials("Little", "Mermaid");
private static final String USER = "Aladdin"; public void testAuth() {
private static final String PASSWORD = "open sesame"; HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build();
request = new BasicAuthentication(ofInstance(credential1)).filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
request = new BasicAuthentication(ofInstance(credential2)).filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic TGl0dGxlOk1lcm1haWQ=");
}
public void testAuth() throws NoSuchAlgorithmException, CertificateException { public void testAuthWithRuntimePasswordChange() {
BasicAuthentication filter = new BasicAuthentication(USER, PASSWORD, new JCECrypto(null)); Supplier<Credentials> credentialRotation = new Supplier<Credentials>() {
Deque<Credentials> rotation = newArrayDeque(asList(credential1, credential2));
public Credentials get() {
return rotation.poll();
}
};
BasicAuthentication filter = new BasicAuthentication(credentialRotation);
HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://localhost").build();
request = filter.filter(request); request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=="); assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==");
request = filter.filter(request);
assertEquals(request.getFirstHeaderOrNull(AUTHORIZATION), "Basic TGl0dGxlOk1lcm1haWQ=");
} }
} }

View File

@ -23,11 +23,14 @@ import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals; import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.fail; import static org.testng.Assert.fail;
import org.jclouds.domain.Credentials;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
/** /**
@ -36,10 +39,12 @@ import com.google.common.reflect.TypeToken;
@Test(groups = "unit", testName = "BaseViewTest") @Test(groups = "unit", testName = "BaseViewTest")
public class BaseViewTest { public class BaseViewTest {
static Supplier<Credentials> creds = Suppliers.ofInstance(new Credentials("identity", null));
private static class Water extends ContextImpl { private static class Water extends ContextImpl {
protected Water() { protected Water() {
super("water", createMock(ProviderMetadata.class), "identity", createMock(Utils.class), createMock(Closer.class)); super("water", createMock(ProviderMetadata.class), creds, createMock(Utils.class), createMock(Closer.class));
} }
public void close() { public void close() {
@ -49,7 +54,7 @@ public class BaseViewTest {
private static class PeanutButter extends ContextImpl { private static class PeanutButter extends ContextImpl {
protected PeanutButter() { protected PeanutButter() {
super("peanutbutter", createMock(ProviderMetadata.class), "identity", createMock(Utils.class), createMock(Closer.class)); super("peanutbutter", createMock(ProviderMetadata.class), creds, createMock(Utils.class), createMock(Closer.class));
} }
public void close() { public void close() {

View File

@ -41,11 +41,11 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.annotations.Api; import org.jclouds.rest.annotations.Api;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.BuildVersion; import org.jclouds.rest.annotations.BuildVersion;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Key; import com.google.inject.Key;
@ -63,8 +63,6 @@ public class BindProviderMetadataContextAndCredentialsTest {
private final javax.inject.Provider<Context> backend; private final javax.inject.Provider<Context> backend;
private final ProviderMetadata providerMetadata; private final ProviderMetadata providerMetadata;
private final Credentials creds; private final Credentials creds;
private final String identity;
private final String credential;
private final String providerId; private final String providerId;
private final Set<String> iso3166Codes; private final Set<String> iso3166Codes;
private final String apiId; private final String apiId;
@ -73,10 +71,9 @@ public class BindProviderMetadataContextAndCredentialsTest {
@Inject @Inject
private ExpectedBindings(@Provider javax.inject.Provider<Context> backend, ProviderMetadata providerMetadata, private ExpectedBindings(@Provider javax.inject.Provider<Context> backend, ProviderMetadata providerMetadata,
@Provider Credentials creds, @Identity String identity, @Nullable @Credential String credential, @Provider Supplier<Credentials> creds, @Provider String providerId, @Iso3166 Set<String> iso3166Codes,
@Provider String providerId, @Iso3166 Set<String> iso3166Codes, @Api String apiId, @Api String apiId, @ApiVersion String apiVersion, @Nullable @BuildVersion String buildVersion,
@ApiVersion String apiVersion, @Nullable @BuildVersion String buildVersion, @Provider TypeToken<? extends Context> backendToken, FilterStringsBoundToInjectorByName filter) {
@Provider TypeToken<? extends Context> backendToken, FilterStringsBoundToInjectorByName filter) {
this.backend = backend; this.backend = backend;
assertEquals(backendToken, providerMetadata.getApiMetadata().getContext()); assertEquals(backendToken, providerMetadata.getApiMetadata().getContext());
this.providerMetadata = providerMetadata; this.providerMetadata = providerMetadata;
@ -86,11 +83,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
expected.putAll(providerMetadata.getApiMetadata().getDefaultProperties()); expected.putAll(providerMetadata.getApiMetadata().getDefaultProperties());
expected.putAll(providerMetadata.getDefaultProperties()); expected.putAll(providerMetadata.getDefaultProperties());
assertEquals(props, expected); assertEquals(props, expected);
this.creds = creds; this.creds = creds.get();
this.identity = identity;
assertEquals(identity, creds.identity);
this.credential = credential;
assertEquals(credential, creds.credential);
this.providerId = providerId; this.providerId = providerId;
assertEquals(providerId, providerMetadata.getId()); assertEquals(providerId, providerMetadata.getId());
this.iso3166Codes = iso3166Codes; this.iso3166Codes = iso3166Codes;
@ -110,12 +103,13 @@ public class BindProviderMetadataContextAndCredentialsTest {
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint( ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
Credentials creds = LoginCredentials.builder().user("user").password("password").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user")
.password("password").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
assertEquals(bindings.identity, "user"); assertEquals(bindings.creds.identity, "user");
assertEquals(bindings.credential, "password"); assertEquals(bindings.creds.credential, "password");
} }
@Test @Test
@ -123,12 +117,12 @@ public class BindProviderMetadataContextAndCredentialsTest {
ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint( ProviderMetadata md = AnonymousProviderMetadata.forClientMappedToAsyncClientOnEndpoint(
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
assertEquals(bindings.identity, "user"); assertEquals(bindings.creds.identity, "user");
assertEquals(bindings.credential, null); assertEquals(bindings.creds.credential, null);
} }
@Test @Test
@ -138,7 +132,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost"); IntegrationTestClient.class, IntegrationTestAsyncClient.class, "http://localhost");
ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build(); ApiMetadata apiMd = md.getApiMetadata().toBuilder().buildVersion(null).build();
md = md.toBuilder().apiMetadata(apiMd).build(); md = md.toBuilder().apiMetadata(apiMd).build();
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)) ExpectedBindings bindings = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds))
.getInstance(ExpectedBindings.class); .getInstance(ExpectedBindings.class);
@ -154,7 +148,7 @@ public class BindProviderMetadataContextAndCredentialsTest {
defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + ""); defaultProps.setProperty(Constants.PROPERTY_SESSION_INTERVAL, Integer.MAX_VALUE + "");
md = md.toBuilder().defaultProperties(defaultProps).build(); md = md.toBuilder().defaultProperties(defaultProps).build();
Credentials creds = LoginCredentials.builder().user("user").build(); Supplier<Credentials> creds = Suppliers.<Credentials> ofInstance(LoginCredentials.builder().user("user").build());
int session = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)).getInstance( int session = Guice.createInjector(new BindProviderMetadataContextAndCredentials(md, creds)).getInstance(
Key.get(int.class, Names.named(Constants.PROPERTY_SESSION_INTERVAL))); Key.get(int.class, Names.named(Constants.PROPERTY_SESSION_INTERVAL)));

View File

@ -28,17 +28,17 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.rest.annotations.Credential; import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Identity;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
/** /**
* Authenticates using Basic Authentication or a generated token from previous * Authenticates using Basic Authentication or a generated token from previous API sessions.
* API sessions.
* *
* @author Ignasi Barrera * @author Ignasi Barrera
*/ */
@ -47,23 +47,21 @@ public class AbiquoAuthentication implements HttpRequestFilter {
/** The name of the authentication token. */ /** The name of the authentication token. */
public static final String AUTH_TOKEN_NAME = "auth"; public static final String AUTH_TOKEN_NAME = "auth";
protected String identity; protected Supplier<Credentials> creds;
protected String credential;
protected boolean credentialIsToken; protected boolean credentialIsToken;
@Inject @Inject
public AbiquoAuthentication(@Identity final String identity, @Credential final String credential, public AbiquoAuthentication(@Provider Supplier<Credentials> creds,
@Named(CREDENTIAL_IS_TOKEN) final String credentialIsToken) { @Named(CREDENTIAL_IS_TOKEN) boolean credentialIsToken) {
this.identity = checkNotNull(identity, "identity"); this.creds = checkNotNull(creds, "creds");
this.credential = checkNotNull(credential, "credential"); this.credentialIsToken = credentialIsToken;
this.credentialIsToken = Boolean.valueOf(credentialIsToken);
} }
@Override @Override
public HttpRequest filter(final HttpRequest request) throws HttpException { public HttpRequest filter(final HttpRequest request) throws HttpException {
String header = credentialIsToken ? tokenAuth(credential) : basic(identity, credential); Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String header = credentialIsToken ? tokenAuth(currentCreds.credential) : basic(currentCreds.identity,
currentCreds.credential);
return request.toBuilder() return request.toBuilder()
.replaceHeader(credentialIsToken ? HttpHeaders.COOKIE : HttpHeaders.AUTHORIZATION, header).build(); .replaceHeader(credentialIsToken ? HttpHeaders.COOKIE : HttpHeaders.AUTHORIZATION, header).build();
} }

View File

@ -19,6 +19,7 @@
package org.jclouds.abiquo.http.filters; package org.jclouds.abiquo.http.filters;
import static com.google.common.base.Suppliers.ofInstance;
import static org.jclouds.http.filters.BasicAuthentication.basic; import static org.jclouds.http.filters.BasicAuthentication.basic;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertFalse;
@ -29,6 +30,7 @@ import java.security.cert.CertificateException;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -43,7 +45,7 @@ public class AbiquoAuthenticationTest {
public void testBasicAuthentication() throws NoSuchAlgorithmException, CertificateException { public void testBasicAuthentication() throws NoSuchAlgorithmException, CertificateException {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build();
AbiquoAuthentication filter = new AbiquoAuthentication("identity", "credential", "false"); AbiquoAuthentication filter = new AbiquoAuthentication(ofInstance(new Credentials("identity", "credential")), false);
HttpRequest filtered = filter.filter(request); HttpRequest filtered = filter.filter(request);
HttpRequest expected = request.toBuilder() HttpRequest expected = request.toBuilder()
.replaceHeader(HttpHeaders.AUTHORIZATION, basic("identity", "credential")).build(); .replaceHeader(HttpHeaders.AUTHORIZATION, basic("identity", "credential")).build();
@ -56,7 +58,7 @@ public class AbiquoAuthenticationTest {
public void testBasicAuthenticationWithoutIdentity() throws NoSuchAlgorithmException, CertificateException { public void testBasicAuthenticationWithoutIdentity() throws NoSuchAlgorithmException, CertificateException {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build();
AbiquoAuthentication filter = new AbiquoAuthentication(null, "credential", "false"); AbiquoAuthentication filter = new AbiquoAuthentication(ofInstance(new Credentials(null, "credential")), false);
filter.filter(request); filter.filter(request);
} }
@ -64,14 +66,15 @@ public class AbiquoAuthenticationTest {
public void testBasicAuthenticationWithoutCredential() throws NoSuchAlgorithmException, CertificateException { public void testBasicAuthenticationWithoutCredential() throws NoSuchAlgorithmException, CertificateException {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build();
AbiquoAuthentication filter = new AbiquoAuthentication("identity", null, "false"); AbiquoAuthentication filter = new AbiquoAuthentication(ofInstance(new Credentials("identity", null)), false);
filter.filter(request); filter.filter(request);
} }
public void testTokenAuthentication() throws NoSuchAlgorithmException, CertificateException { public void testTokenAuthentication() throws NoSuchAlgorithmException, CertificateException {
HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build(); HttpRequest request = HttpRequest.builder().method("GET").endpoint(URI.create("http://foo")).build();
AbiquoAuthentication filter = new AbiquoAuthentication("token-identity", "token", "true"); AbiquoAuthentication filter = new AbiquoAuthentication(ofInstance(new Credentials("token-identity", "token")),
true);
HttpRequest filtered = filter.filter(request); HttpRequest filtered = filter.filter(request);
HttpRequest expected = request.toBuilder() HttpRequest expected = request.toBuilder()
.replaceHeader(HttpHeaders.COOKIE, AbiquoAuthentication.tokenAuth("token")).build(); .replaceHeader(HttpHeaders.COOKIE, AbiquoAuthentication.tokenAuth("token")).build();

View File

@ -18,25 +18,9 @@
*/ */
package org.jclouds.azure.management.config; package org.jclouds.azure.management.config;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.inject.Singleton;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.jclouds.azure.management.AzureManagementApi; import org.jclouds.azure.management.AzureManagementApi;
@ -53,19 +37,13 @@ import org.jclouds.azure.management.features.OperationApi;
import org.jclouds.azure.management.features.OperationAsyncApi; import org.jclouds.azure.management.features.OperationAsyncApi;
import org.jclouds.azure.management.features.RoleApi; import org.jclouds.azure.management.features.RoleApi;
import org.jclouds.azure.management.features.RoleAsyncApi; import org.jclouds.azure.management.features.RoleAsyncApi;
import org.jclouds.azure.management.suppliers.KeyStoreSupplier;
import org.jclouds.azure.management.suppliers.SSLContextWithKeysSupplier; import org.jclouds.azure.management.suppliers.SSLContextWithKeysSupplier;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.io.InputSuppliers;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import com.google.common.base.Charsets;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
/** /**
@ -76,13 +54,12 @@ import com.google.inject.TypeLiteral;
@ConfiguresRestClient @ConfiguresRestClient
public class AzureManagementRestClientModule extends RestClientModule<AzureManagementApi, AzureManagementAsyncApi> { public class AzureManagementRestClientModule extends RestClientModule<AzureManagementApi, AzureManagementAsyncApi> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder() public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
.put(LocationApi.class, LocationAsyncApi.class) .put(LocationApi.class, LocationAsyncApi.class)
.put(RoleApi.class, RoleAsyncApi.class) .put(RoleApi.class, RoleAsyncApi.class)
.put(HostedServiceApi.class, HostedServiceAsyncApi.class) .put(HostedServiceApi.class, HostedServiceAsyncApi.class)
.put(OSImageApi.class, OSImageAsyncApi.class) .put(OSImageApi.class, OSImageAsyncApi.class)
.put(OperationApi.class, OperationAsyncApi.class) .put(OperationApi.class, OperationAsyncApi.class)
.put(DiskApi.class, DiskAsyncApi.class) .put(DiskApi.class, DiskAsyncApi.class).build();
.build();
public AzureManagementRestClientModule() { public AzureManagementRestClientModule() {
super(DELEGATE_MAP); super(DELEGATE_MAP);
@ -94,59 +71,9 @@ public class AzureManagementRestClientModule extends RestClientModule<AzureManag
bind(new TypeLiteral<Supplier<SSLContext>>() { bind(new TypeLiteral<Supplier<SSLContext>>() {
}).to(new TypeLiteral<SSLContextWithKeysSupplier>() { }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
}); });
bind(new TypeLiteral<Supplier<KeyStore>>() {
}).to(new TypeLiteral<KeyStoreSupplier>() {
});
} }
/**
* TODO copied from FGCP, should be put in a common place
*
* @author Dies Koper
*/
@Provides
@Singleton
protected KeyStore provideKeyStore(Crypto crypto, @Identity String cert, @Credential String keyStorePassword)
throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException,
InvalidKeySpecException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
File certFile = new File(checkNotNull(cert));
if (certFile.isFile()) { // cert is path to pkcs12 file
keyStore.load(new FileInputStream(certFile), keyStorePassword.toCharArray());
} else { // cert is PEM encoded, containing private key and certs
// split in private key and certs
int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
String pemCerts = "";
int certsBeginIdx = 0;
do {
certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
if (certsBeginIdx >= 0) {
int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
certsBeginIdx = certsEndIdx;
}
} while (certsBeginIdx != -1);
// parse private key
KeySpec keySpec = Pems.privateKeySpec(InputSuppliers.of(pemPrivateKey));
PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
// populate keystore with private key and certs
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@SuppressWarnings("unchecked")
Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
pemCerts.getBytes(Charsets.UTF_8)));
keyStore.load(null);
keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
certs.toArray(new java.security.cert.Certificate[0]));
}
return keyStore;
}
} }

View File

@ -0,0 +1,130 @@
/**
* 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.azure.management.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Collection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.domain.Credentials;
import org.jclouds.io.InputSuppliers;
import org.jclouds.location.Provider;
import com.google.common.base.Charsets;
import com.google.common.base.Supplier;
/**
* TODO this code needs to be completely refactored. It needs to stop using KeyStore of at all possible and definitely
* the local filesystem. Please look at oauth for examples on how to do this via PEMs.
*/
@Deprecated
@Singleton
public class KeyStoreSupplier implements Supplier<KeyStore> {
private final Crypto crypto;
private final Supplier<Credentials> creds;
@Inject
KeyStoreSupplier(Crypto crypto, @Provider Supplier<Credentials> creds) {
this.crypto = crypto;
this.creds = creds;
}
@Override
public KeyStore get() {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String cert = checkNotNull(currentCreds.identity, "credential supplier returned null identity (should be cert)");
String keyStorePassword = checkNotNull(currentCreds.credential,
"credential supplier returned null credential (should be keyStorePassword)");
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
File certFile = new File(checkNotNull(cert));
if (certFile.isFile()) { // cert is path to pkcs12 file
keyStore.load(new FileInputStream(certFile), keyStorePassword.toCharArray());
} else { // cert is PEM encoded, containing private key and certs
// split in private key and certs
int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
String pemCerts = "";
int certsBeginIdx = 0;
do {
certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
if (certsBeginIdx >= 0) {
int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
certsBeginIdx = certsEndIdx;
}
} while (certsBeginIdx != -1);
// parse private key
KeySpec keySpec = Pems.privateKeySpec(InputSuppliers.of(pemPrivateKey));
PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
// populate keystore with private key and certs
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@SuppressWarnings("unchecked")
Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
pemCerts.getBytes(Charsets.UTF_8)));
keyStore.load(null);
keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
certs.toArray(new java.security.cert.Certificate[0]));
}
return keyStore;
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (KeyStoreException e) {
throw propagate(e);
} catch (CertificateException e) {
throw propagate(e);
} catch (FileNotFoundException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
} catch (InvalidKeySpecException e) {
throw propagate(e);
}
}
}

View File

@ -18,6 +18,9 @@
*/ */
package org.jclouds.azure.management.suppliers; package org.jclouds.azure.management.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
@ -31,42 +34,52 @@ import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManager;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.SSLModule.TrustAllCerts; import org.jclouds.http.config.SSLModule.TrustAllCerts;
import org.jclouds.rest.annotations.Credential; import org.jclouds.location.Provider;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
/** /**
* * TODO this code needs to be completely refactored. It needs to stop using KeyStore of at all possible and definitely
* TODO copied from FGCP, should be put in a common place * the local filesystem. Please look at oauth for examples on how to do this via PEMs.
*
* SSLContext supplier with a configured key manager to enable client authentication with
* certificates.
*
* @author Dies Koper
*/ */
@Deprecated
@Singleton @Singleton
public class SSLContextWithKeysSupplier implements Supplier<SSLContext> { public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
private SSLContext sc; private final Supplier<KeyStore> keyStore;
private final TrustManager[] trustManager;
private final Supplier<Credentials> creds;
@Inject @Inject
SSLContextWithKeysSupplier(KeyStore keyStore, @Credential String keyStorePassword, HttpUtils utils, SSLContextWithKeysSupplier(Supplier<KeyStore> keyStore, @Provider Supplier<Credentials> creds, HttpUtils utils,
TrustAllCerts trustAllCerts) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, TrustAllCerts trustAllCerts) {
KeyManagementException { this.keyStore = keyStore;
this.trustManager = utils.trustAllCerts() ? new TrustManager[] { trustAllCerts } : null;
TrustManager[] trustManager = null; this.creds = creds;
if (utils.trustAllCerts()) {
trustManager = new TrustManager[] { trustAllCerts };
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, keyStorePassword.toCharArray());
sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
} }
@Override @Override
public SSLContext get() { public SSLContext get() {
return sc; Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String keyStorePassword = checkNotNull(currentCreds.credential,
"credential supplier returned null credential (should be keyStorePassword)");
KeyManagerFactory kmf;
try {
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore.get(), keyStorePassword.toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
return sc;
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (UnrecoverableKeyException e) {
throw propagate(e);
} catch (KeyStoreException e) {
throw propagate(e);
} catch (KeyManagementException e) {
throw propagate(e);
}
} }
} }

View File

@ -18,17 +18,21 @@
*/ */
package org.jclouds.snia.cdmi.v1.filters; package org.jclouds.snia.cdmi.v1.filters;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static org.jclouds.http.filters.BasicAuthentication.basic;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.crypto.Crypto; import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.location.Provider;
import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity; import com.google.common.base.Supplier;
/** /**
* Uses Basic Authentication to sign the request, and adds the {@code TID} header. * Uses Basic Authentication to sign the request, and adds the {@code TID} header.
@ -39,23 +43,23 @@ import org.jclouds.rest.annotations.Identity;
*/ */
@Singleton @Singleton
public class BasicAuthenticationAndTenantId implements HttpRequestFilter { public class BasicAuthenticationAndTenantId implements HttpRequestFilter {
private final String tenantId; private final Supplier<Credentials> creds;
private final BasicAuthentication basicAuthentication;
@Inject @Inject
public BasicAuthenticationAndTenantId(@Identity String tenantIdAndUsername, @Credential String password, public BasicAuthenticationAndTenantId(@Provider Supplier<Credentials> creds) {
Crypto crypto) { this.creds = checkNotNull(creds, "creds");
if (tenantIdAndUsername.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username",
tenantIdAndUsername), null);
}
this.tenantId = tenantIdAndUsername.substring(0, tenantIdAndUsername.indexOf(':'));
String username = tenantIdAndUsername.substring(tenantIdAndUsername.indexOf(':') + 1);
this.basicAuthentication = new BasicAuthentication(username, password, crypto);
} }
@Override @Override
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
return basicAuthentication.filter(request.toBuilder().replaceHeader("TID", tenantId).build()); Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
if (currentCreds.identity.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username",
currentCreds.identity), null);
}
String tenantId = currentCreds.identity.substring(0, currentCreds.identity.indexOf(':'));
String username = currentCreds.identity.substring(currentCreds.identity.indexOf(':') + 1);
return request.toBuilder().replaceHeader("TID", tenantId)
.replaceHeader(AUTHORIZATION, basic(username, currentCreds.credential)).build();
} }
} }

View File

@ -18,31 +18,17 @@
*/ */
package org.jclouds.fujitsu.fgcp.compute; package org.jclouds.fujitsu.fgcp.compute;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.KeySpec;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collection;
import java.util.Map; import java.util.Map;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Singleton;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.date.TimeStamp; import org.jclouds.date.TimeStamp;
import org.jclouds.fujitsu.fgcp.FGCPApi; import org.jclouds.fujitsu.fgcp.FGCPApi;
import org.jclouds.fujitsu.fgcp.FGCPAsyncApi; import org.jclouds.fujitsu.fgcp.FGCPAsyncApi;
import org.jclouds.fujitsu.fgcp.handlers.FGCPRetryIfNotProxyAuthenticationFailureHandler; import org.jclouds.fujitsu.fgcp.handlers.FGCPRetryIfNotProxyAuthenticationFailureHandler;
import org.jclouds.fujitsu.fgcp.http.SSLContextWithKeysSupplier;
import org.jclouds.fujitsu.fgcp.location.SystemAndNetworkSegmentToLocationSupplier; import org.jclouds.fujitsu.fgcp.location.SystemAndNetworkSegmentToLocationSupplier;
import org.jclouds.fujitsu.fgcp.services.AdditionalDiskApi; import org.jclouds.fujitsu.fgcp.services.AdditionalDiskApi;
import org.jclouds.fujitsu.fgcp.services.AdditionalDiskAsyncApi; import org.jclouds.fujitsu.fgcp.services.AdditionalDiskAsyncApi;
@ -64,22 +50,19 @@ import org.jclouds.fujitsu.fgcp.services.VirtualServerApi;
import org.jclouds.fujitsu.fgcp.services.VirtualServerAsyncApi; import org.jclouds.fujitsu.fgcp.services.VirtualServerAsyncApi;
import org.jclouds.fujitsu.fgcp.services.VirtualSystemApi; import org.jclouds.fujitsu.fgcp.services.VirtualSystemApi;
import org.jclouds.fujitsu.fgcp.services.VirtualSystemAsyncApi; import org.jclouds.fujitsu.fgcp.services.VirtualSystemAsyncApi;
import org.jclouds.fujitsu.fgcp.suppliers.KeyStoreSupplier;
import org.jclouds.fujitsu.fgcp.suppliers.SSLContextWithKeysSupplier;
import org.jclouds.fujitsu.fgcp.xml.FGCPJAXBParser; import org.jclouds.fujitsu.fgcp.xml.FGCPJAXBParser;
import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.io.InputSuppliers;
import org.jclouds.location.suppliers.ImplicitLocationSupplier; import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.location.suppliers.LocationsSupplier; import org.jclouds.location.suppliers.LocationsSupplier;
import org.jclouds.location.suppliers.implicit.FirstNetwork; import org.jclouds.location.suppliers.implicit.FirstNetwork;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import org.jclouds.xml.XMLParser; import org.jclouds.xml.XMLParser;
import com.google.common.base.Charsets;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides; import com.google.inject.Provides;
@ -100,7 +83,6 @@ public class FGCPRestClientModule extends
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap
.<Class<?>, Class<?>> builder() .<Class<?>, Class<?>> builder()
//
.put(VirtualDCApi.class, VirtualDCAsyncApi.class) .put(VirtualDCApi.class, VirtualDCAsyncApi.class)
.put(VirtualSystemApi.class, VirtualSystemAsyncApi.class) .put(VirtualSystemApi.class, VirtualSystemAsyncApi.class)
.put(VirtualServerApi.class, VirtualServerAsyncApi.class) .put(VirtualServerApi.class, VirtualServerAsyncApi.class)
@ -117,21 +99,11 @@ public class FGCPRestClientModule extends
super(DELEGATE_MAP); super(DELEGATE_MAP);
} }
@Override
protected void bindErrorHandlers() {
// bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseAWSErrorFromXmlContent.class);
// bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(ParseAWSErrorFromXmlContent.class);
// bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseAWSErrorFromXmlContent.class);
}
@Override @Override
protected void installLocations() { protected void installLocations() {
super.installLocations(); super.installLocations();
bind(ImplicitLocationSupplier.class).to(FirstNetwork.class).in( bind(ImplicitLocationSupplier.class).to(FirstNetwork.class).in(Scopes.SINGLETON);
Scopes.SINGLETON); bind(LocationsSupplier.class).to(SystemAndNetworkSegmentToLocationSupplier.class).in(Scopes.SINGLETON);
bind(LocationsSupplier.class).to(
SystemAndNetworkSegmentToLocationSupplier.class).in(
Scopes.SINGLETON);
} }
@Override @Override
@ -147,6 +119,9 @@ public class FGCPRestClientModule extends
bind(new TypeLiteral<Supplier<SSLContext>>() { bind(new TypeLiteral<Supplier<SSLContext>>() {
}).to(new TypeLiteral<SSLContextWithKeysSupplier>() { }).to(new TypeLiteral<SSLContextWithKeysSupplier>() {
}); });
bind(new TypeLiteral<Supplier<KeyStore>>() {
}).to(new TypeLiteral<KeyStoreSupplier>() {
});
} }
@Provides @Provides
@ -154,223 +129,4 @@ public class FGCPRestClientModule extends
protected Calendar provideCalendar() { protected Calendar provideCalendar() {
return Calendar.getInstance(); return Calendar.getInstance();
} }
/*
*
* @Provides
*
* @Singleton protected KeyStore
* provideKeyStore(@Named(Constants.PROPERTY_IDENTITY) String
* keyStoreFilename, @Named(Constants.PROPERTY_CREDENTIAL) String
* keyStorePassword) throws KeyStoreException { KeyStore keyStore =
* KeyStore.getInstance("pkcs12");
*
* try { FileInputStream is = new
* FileInputStream(checkNotNull(keyStoreFilename,
* Constants.PROPERTY_IDENTITY)); keyStore.load(is,
* checkNotNull(keyStorePassword,
* Constants.PROPERTY_CREDENTIAL).toCharArray()); } catch (Exception e) { //
* expecting IOException, NoSuchAlgorithmException, CertificateException
* logger.error(e, "Keystore could not be opened: %s", keyStoreFilename); }
* return keyStore; }
*
* @Provides
*
* @Singleton protected PrivateKey provideKey(Provider<KeyStore>
* keyStoreProvider, @Named(Constants.PROPERTY_CREDENTIAL) String
* keyPassword) throws KeyStoreException, NoSuchAlgorithmException,
* UnrecoverableKeyException { KeyStore keyStore = keyStoreProvider.get();
* if (keyStore == null) return null;
*
* // retrieving 1st alias in keystore as expecting only one String alias =
* checkNotNull(keyStore.aliases().nextElement(),
* "first alias in keystore"); return (PrivateKey) keyStore.getKey(alias,
* checkNotNull(keyPassword, Constants.PROPERTY_CREDENTIAL).toCharArray());
* }
*/
/*
* maybe we can provide two authentication methods:
*
* 1. same as DeltaCloud: User passes a folder name as identity and cert
* password as credential Note: pass relative path (e.g. cert's path:
* c:\jclouds\certs\dkoper\UserCert.p12: user passes 'dkoper': provider
* impl. finds it under e.g. $USER_DIR or $CURRENT_DIR or pass absolute path
* 2. no file access for GAE: User passes cert in PEM format (converted from
* UserCert.p12 using openssl?) as identity and cert password as credential
*/
@Provides
@Singleton
protected KeyStore provideKeyStore(Crypto crypto, @Identity String cert,
@Credential String keyStorePassword) {
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("PKCS12");
// System.out.println("cert: " + cert);
// System.out.println("pwd : " + keyStorePassword);
File certFile = new File(checkNotNull(cert));
if (certFile.isFile()) { // cert is path to pkcs12 file
keyStore.load(new FileInputStream(certFile),
keyStorePassword.toCharArray());
} else { // cert is PEM encoded, containing private key and certs
// System.out.println("cert:\n" + cert);
// split in private key and certs
int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
String pemPrivateKey = cert.substring(privateKeyBeginIdx,
privateKeyEndIdx + 26);
// System.out.println("***************");
// System.out.println("pemPrivateKey:\n" + pemPrivateKey);
// System.out.println("***************");
String pemCerts = "";
int certsBeginIdx = 0;
do {
certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE",
certsBeginIdx);
// System.out.println("begin:" + certsBeginIdx);
if (certsBeginIdx >= 0) {
int certsEndIdx = cert.indexOf("-----END CERTIFICATE",
certsBeginIdx) + 26;
// System.out.println("end :" + certsEndIdx);
pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
certsBeginIdx = certsEndIdx;
}
} while (certsBeginIdx != -1);
// System.out.println("***************");
// System.out.println("pemCerts:\n" + pemCerts);
// System.out.println("***************");
/*
* String pemCerts = "-----BEGIN "; Splitter pemSplitter =
* Splitter.on("-----BEGIN ");
*
* for (String part : pemSplitter.split(cert)) {
* System.out.println("***************");
* System.out.println("Part:\n" + part);
* System.out.println("***************");
*
* if (part.startsWith("PRIVATE KEY")
*/
/* || part.startsWith("RSA PRIVATE KEY)" *//*
* ) {
*
* int certEndIdx =
* part.lastIndexOf
* ("-----END");
* pemPrivateKey +=
* part.substring(0,
* certEndIdx + 26);
* // take up to next
* "-----" (i.e.
* "-----END") //
* Splitter
* keySplitter =
* Splitter
* .on("-----").
* omitEmptyStrings
* ().trimResults();
* //
* Iterator<String>
* iter =
* keySplitter.
* split(part
* ).iterator(); //
* String keyName =
* iter.next() +
* "-----\n"; //
* pemPrivateKey +=
* keyName; ////
* System.out
* .println
* ("Skipping: '" +
* iter.next() +
* "'"); //
* pemPrivateKey +=
* iter.next(); //
* pemPrivateKey +=
* "\n-----END " +
* keyName;
* System.out.println
* (
* "/////////////////"
* );
* System.out.println
* (
* "pemPrivateKey:\n"
* + pemPrivateKey);
* System
* .out.println(
* "/////////////////"
* ); } else if
* (part.startsWith
* ("CERTIFICATE")) {
*
* // take up to next
* "-----" (i.e.
* "-----END") // or
* take up to last
* END CERTIFICATE?
* int certEndIdx =
* part.lastIndexOf (
* "----- END CERTIFICATE"
* ); // pemCerts +=
* part. // Splitter
* keySplitter =
* Splitter
* .on("-----").
* omitEmptyStrings
* (); // pemCerts +=
* keySplitter
* .split(part)
* .iterator
* ().next(); //
* pemCerts +=
* "-----BEGIN "; }
* else { // ignore
* the fluff in
* between (Bag
* Attributes, etc.)
* } }
*/
// parse private key
KeySpec keySpec = Pems.privateKeySpec(InputSuppliers
.of(pemPrivateKey));
PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(
keySpec);
// populate keystore with private key and certs
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@SuppressWarnings("unchecked")
Collection<Certificate> certs = (Collection<Certificate>) cf
.generateCertificates(new ByteArrayInputStream(pemCerts
.getBytes(Charsets.UTF_8)));
keyStore.load(null);
keyStore.setKeyEntry("dummy", privateKey,
keyStorePassword.toCharArray(),
certs.toArray(new java.security.cert.Certificate[0]));
// System.out.println("private key: " + privateKey.getFormat() +
// "; "
// + privateKey.getAlgorithm() + "; class: " +
// privateKey.getClass().getName());// + "; " + new
// String(privateKey.getEncoded()));
}
} catch (Exception e) {
/*
* KeyStoreException, IOException, NoSuchAlgorithmException,
* CertificateException, InvalidKeySpecException
*/
throw new AuthorizationException("Error loading certificate", e);
}
return keyStore;
}
} }

View File

@ -20,6 +20,7 @@ package org.jclouds.fujitsu.fgcp.filters;
import static com.google.common.base.Charsets.UTF_8; import static com.google.common.base.Charsets.UTF_8;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.io.BaseEncoding.base64; import static com.google.common.io.BaseEncoding.base64;
import static org.jclouds.http.utils.Queries.queryParser; import static org.jclouds.http.utils.Queries.queryParser;
@ -33,6 +34,7 @@ import java.security.SignatureException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.util.Calendar; import java.util.Calendar;
import java.util.Locale; import java.util.Locale;
import java.util.concurrent.ExecutionException;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
@ -45,6 +47,7 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.Constants; import org.jclouds.Constants;
import org.jclouds.date.TimeStamp; import org.jclouds.date.TimeStamp;
import org.jclouds.domain.Credentials;
import org.jclouds.fujitsu.fgcp.reference.RequestParameters; import org.jclouds.fujitsu.fgcp.reference.RequestParameters;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
@ -54,14 +57,16 @@ import org.jclouds.http.internal.SignatureWire;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.RequestSigner; import org.jclouds.rest.RequestSigner;
import org.jclouds.rest.annotations.ApiVersion; import org.jclouds.rest.annotations.ApiVersion;
import org.jclouds.rest.annotations.Credential;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
/** /**
* Generates and signs the access key id and adds the mandatory http header and * Generates and signs the access key id and adds the mandatory http header and request parameters to the request.
* request parameters to the request.
* *
* @author Dies Koper * @author Dies Koper
*/ */
@ -71,37 +76,65 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
@Resource @Resource
@Named(Constants.LOGGER_SIGNATURE) @Named(Constants.LOGGER_SIGNATURE)
private Logger signatureLog = Logger.NULL; private Logger signatureLog = Logger.NULL;
private final Supplier<Credentials> creds;
private final LoadingCache<Credentials, Signature> signerCache;
private final Provider<Calendar> calendarProvider;
private final HttpUtils utils;
private final String apiVersion;
final Provider<Calendar> calendarProvider; private final static String signatureVersion = "1.0";
final Signature signer; private final static String signatureMethod = "SHA1withRSA";
final String apiVersion;
public String signatureVersion = "1.0";
public String signatureMethod = "SHA1withRSA";
private HttpUtils utils;
@Inject @Inject
public RequestAuthenticator(@TimeStamp Provider<Calendar> calendarProvider, Provider<KeyStore> keyStoreProvider, public RequestAuthenticator(@TimeStamp Provider<Calendar> calendarProvider, SignatureForCredentials loader,
@Credential String keyPassword, HttpUtils utils, SignatureWire signatureWire, @ApiVersion String apiVersion) @org.jclouds.location.Provider Supplier<Credentials> creds, HttpUtils utils, SignatureWire signatureWire,
throws NoSuchAlgorithmException, InvalidKeyException, KeyStoreException, UnrecoverableKeyException { @ApiVersion String apiVersion) {
this.calendarProvider = checkNotNull(calendarProvider); this.calendarProvider = checkNotNull(calendarProvider);
this.creds = checkNotNull(creds, "creds");
// throw out the signature related to old keys
this.signerCache = CacheBuilder.newBuilder().maximumSize(2).build(checkNotNull(loader, "loader"));
this.utils = checkNotNull(utils, "utils"); this.utils = checkNotNull(utils, "utils");
this.apiVersion = checkNotNull(apiVersion, "apiVersion"); this.apiVersion = checkNotNull(apiVersion, "apiVersion");
}
signer = Signature.getInstance(signatureMethod); /**
* it is relatively expensive to create a new signing key. cache the relationship between current credentials so that
* the signer is only recalculated once.
*/
private static class SignatureForCredentials extends CacheLoader<Credentials, Signature> {
private final Supplier<KeyStore> keyStore;
KeyStore keyStore = checkNotNull(keyStoreProvider).get(); @Inject
String alias = keyStore.aliases().nextElement(); // there should be only one private key public SignatureForCredentials(Supplier<KeyStore> keyStore) {
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, this.keyStore = checkNotNull(keyStore, "keyStore");
keyPassword.toCharArray()); }
signer.initSign(privateKey); @Override
public Signature load(Credentials in) {
String keyPassword = checkNotNull(in.credential,
"credential supplier returned null for credential (keyPassword)");
try {
Signature signer = Signature.getInstance(signatureMethod);
KeyStore keyStore = checkNotNull(this.keyStore.get(), "keyStore");
String alias = keyStore.aliases().nextElement(); // there should be only one private key
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keyPassword.toCharArray());
signer.initSign(privateKey);
return signer;
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (KeyStoreException e) {
throw propagate(e);
} catch (UnrecoverableKeyException e) {
throw propagate(e);
} catch (InvalidKeyException e) {
throw propagate(e);
}
}
} }
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
checkNotNull(request, "request must be present"); checkNotNull(request, "request must be present");
utils.logRequest(signatureLog, request, ">>"); utils.logRequest(signatureLog, request, ">>");
// create accesskeyid // create accesskeyid
@ -109,8 +142,7 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
String signature = sign(accessKeyId); String signature = sign(accessKeyId);
// only "en" and "ja" are allowed // only "en" and "ja" are allowed
String lang = Locale.JAPANESE.getLanguage().equals( String lang = Locale.JAPANESE.getLanguage().equals(Locale.getDefault().getLanguage()) ? Locale.JAPANESE
Locale.getDefault().getLanguage()) ? Locale.JAPANESE
.getLanguage() : Locale.ENGLISH.getLanguage(); .getLanguage() : Locale.ENGLISH.getLanguage();
if (HttpMethod.GET.equals(request.getMethod())) { if (HttpMethod.GET.equals(request.getMethod())) {
@ -126,24 +158,18 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
} else { } else {
String payload = request.getPayload().getRawContent().toString(); String payload = request.getPayload().getRawContent().toString();
payload = createXmlElementWithValue(payload, payload = createXmlElementWithValue(payload, RequestParameters.VERSION, apiVersion);
RequestParameters.VERSION, apiVersion); payload = createXmlElementWithValue(payload, RequestParameters.LOCALE, lang);
payload = createXmlElementWithValue(payload, payload = createXmlElementWithValue(payload, RequestParameters.ACCESS_KEY_ID, accessKeyId);
RequestParameters.LOCALE, lang); payload = createXmlElementWithValue(payload, RequestParameters.SIGNATURE, signature);
payload = createXmlElementWithValue(payload,
RequestParameters.ACCESS_KEY_ID, accessKeyId);
payload = createXmlElementWithValue(payload,
RequestParameters.SIGNATURE, signature);
// ensure there are no other query params left // ensure there are no other query params left
request.setPayload(payload); request.setPayload(payload);
request.getPayload().getContentMetadata() request.getPayload().getContentMetadata().setContentType(MediaType.TEXT_XML);
.setContentType(MediaType.TEXT_XML);
} }
// may need to do this elsewhere (see ConvertToGaeRequest) // may need to do this elsewhere (see ConvertToGaeRequest)
HttpRequest filteredRequest = request.toBuilder() HttpRequest filteredRequest = request.toBuilder().replaceHeader(HttpHeaders.USER_AGENT, "OViSS-API-CLIENT")
.replaceHeader(HttpHeaders.USER_AGENT, "OViSS-API-CLIENT")
.build(); .build();
utils.logRequest(signatureLog, filteredRequest, ">>->"); utils.logRequest(signatureLog, filteredRequest, ">>->");
@ -158,27 +184,18 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
return payload.replace(startTag + endTag, startTag + value + endTag); return payload.replace(startTag + endTag, startTag + value + endTag);
} }
/*
* HttpRequest setPayload(HttpRequest request, Multimap<String, String>
* decodedParams) {
* request.setPayload(ModifyRequest.makeQueryLine(decodedParams, null)); //
* request.getPayload().getContentMetadata().setContentType(
* "application/x-www-form-urlencoded"); return request; }
*/
@VisibleForTesting @VisibleForTesting
public String sign(String stringToSign) { public String sign(String stringToSign) {
String signed; String signed;
try { try {
Signature signer = signerCache.get(checkNotNull(creds.get(), "credential supplier returned null"));
signer.update(stringToSign.getBytes(UTF_8)); signer.update(stringToSign.getBytes(UTF_8));
signed = base64().encode(signer.sign()); signed = base64().encode(signer.sign());
} catch (SignatureException e) { } catch (SignatureException e) {
throw new HttpException("error signing request", e); throw new HttpException("error signing request", e);
} catch (ExecutionException e) {
throw new HttpException("couldn't load key for signing request", e);
} }
// if (signatureWire.enabled())
// signatureWire.input(Strings2.toInputStream(signed));
return signed; return signed;
} }
@ -188,8 +205,7 @@ public class RequestAuthenticator implements HttpRequestFilter, RequestSigner {
String timezone = cal.getTimeZone().getDisplayName(Locale.ENGLISH); String timezone = cal.getTimeZone().getDisplayName(Locale.ENGLISH);
String expires = String.valueOf(cal.getTime().getTime()); String expires = String.valueOf(cal.getTime().getTime());
String signatureData = String.format("%s&%s&%s&%s", timezone, expires, String signatureData = String.format("%s&%s&%s&%s", timezone, expires, signatureVersion, signatureMethod);
signatureVersion, signatureMethod);
String accessKeyId = base64().encode(signatureData.getBytes(UTF_8)); String accessKeyId = base64().encode(signatureData.getBytes(UTF_8));
return accessKeyId.replace("\n", "\r\n"); return accessKeyId.replace("\n", "\r\n");
} }

View File

@ -1,71 +0,0 @@
/**
* 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.fujitsu.fgcp.http;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.SSLModule.TrustAllCerts;
import org.jclouds.rest.annotations.Credential;
import com.google.common.base.Supplier;
/**
* SSLContext supplier with a configured key manager to enable client
* authentication with certificates.
*
* @author Dies Koper
*/
@Singleton
public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
private SSLContext sc;
@Inject
SSLContextWithKeysSupplier(KeyStore keyStore,
@Credential String keyStorePassword, HttpUtils utils,
TrustAllCerts trustAllCerts) throws NoSuchAlgorithmException,
KeyStoreException, UnrecoverableKeyException,
KeyManagementException {
TrustManager[] trustManager = null;
if (utils.trustAllCerts()) {
trustManager = new TrustManager[] { trustAllCerts };
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore, keyStorePassword.toCharArray());
sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
}
@Override
public SSLContext get() {
return sc;
}
}

View File

@ -0,0 +1,130 @@
/**
* 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.fujitsu.fgcp.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.util.Collection;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.crypto.Crypto;
import org.jclouds.crypto.Pems;
import org.jclouds.domain.Credentials;
import org.jclouds.io.InputSuppliers;
import org.jclouds.location.Provider;
import com.google.common.base.Charsets;
import com.google.common.base.Supplier;
/**
* TODO this code needs to be completely refactored. It needs to stop using KeyStore of at all possible and definitely
* the local filesystem. Please look at oauth for examples on how to do this via PEMs.
*/
@Deprecated
@Singleton
public class KeyStoreSupplier implements Supplier<KeyStore> {
private final Crypto crypto;
private final Supplier<Credentials> creds;
@Inject
public KeyStoreSupplier(Crypto crypto, @Provider Supplier<Credentials> creds) {
this.crypto = crypto;
this.creds = creds;
}
@Override
public KeyStore get() {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String cert = checkNotNull(currentCreds.identity, "credential supplier returned null identity (should be cert)");
String keyStorePassword = checkNotNull(currentCreds.credential,
"credential supplier returned null credential (should be keyStorePassword)");
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
File certFile = new File(checkNotNull(cert));
if (certFile.isFile()) { // cert is path to pkcs12 file
keyStore.load(new FileInputStream(certFile), keyStorePassword.toCharArray());
} else { // cert is PEM encoded, containing private key and certs
// split in private key and certs
int privateKeyBeginIdx = cert.indexOf("-----BEGIN PRIVATE KEY");
int privateKeyEndIdx = cert.indexOf("-----END PRIVATE KEY");
String pemPrivateKey = cert.substring(privateKeyBeginIdx, privateKeyEndIdx + 26);
String pemCerts = "";
int certsBeginIdx = 0;
do {
certsBeginIdx = cert.indexOf("-----BEGIN CERTIFICATE", certsBeginIdx);
if (certsBeginIdx >= 0) {
int certsEndIdx = cert.indexOf("-----END CERTIFICATE", certsBeginIdx) + 26;
pemCerts += cert.substring(certsBeginIdx, certsEndIdx);
certsBeginIdx = certsEndIdx;
}
} while (certsBeginIdx != -1);
// parse private key
KeySpec keySpec = Pems.privateKeySpec(InputSuppliers.of(pemPrivateKey));
PrivateKey privateKey = crypto.rsaKeyFactory().generatePrivate(keySpec);
// populate keystore with private key and certs
CertificateFactory cf = CertificateFactory.getInstance("X.509");
@SuppressWarnings("unchecked")
Collection<Certificate> certs = (Collection<Certificate>) cf.generateCertificates(new ByteArrayInputStream(
pemCerts.getBytes(Charsets.UTF_8)));
keyStore.load(null);
keyStore.setKeyEntry("dummy", privateKey, keyStorePassword.toCharArray(),
certs.toArray(new java.security.cert.Certificate[0]));
}
return keyStore;
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (KeyStoreException e) {
throw propagate(e);
} catch (CertificateException e) {
throw propagate(e);
} catch (FileNotFoundException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
} catch (InvalidKeySpecException e) {
throw propagate(e);
}
}
}

View File

@ -0,0 +1,85 @@
/**
* 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.fujitsu.fgcp.suppliers;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Throwables.propagate;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpUtils;
import org.jclouds.http.config.SSLModule.TrustAllCerts;
import org.jclouds.location.Provider;
import com.google.common.base.Supplier;
/**
* TODO this code needs to be completely refactored. It needs to stop using KeyStore of at all possible and definitely
* the local filesystem. Please look at oauth for examples on how to do this via PEMs.
*/
@Deprecated
@Singleton
public class SSLContextWithKeysSupplier implements Supplier<SSLContext> {
private final Supplier<KeyStore> keyStore;
private final TrustManager[] trustManager;
private final Supplier<Credentials> creds;
@Inject
SSLContextWithKeysSupplier(Supplier<KeyStore> keyStore, @Provider Supplier<Credentials> creds, HttpUtils utils,
TrustAllCerts trustAllCerts) {
this.keyStore = keyStore;
this.trustManager = utils.trustAllCerts() ? new TrustManager[] { trustAllCerts } : null;
this.creds = creds;
}
@Override
public SSLContext get() {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String keyStorePassword = checkNotNull(currentCreds.credential,
"credential supplier returned null credential (should be keyStorePassword)");
KeyManagerFactory kmf;
try {
kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(keyStore.get(), keyStorePassword.toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), trustManager, new SecureRandom());
return sc;
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (UnrecoverableKeyException e) {
throw propagate(e);
} catch (KeyStoreException e) {
throw propagate(e);
} catch (KeyManagementException e) {
throw propagate(e);
}
}
}

View File

@ -29,9 +29,12 @@ import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import org.jclouds.crypto.Crypto; import org.jclouds.crypto.Crypto;
import org.jclouds.domain.Credentials;
import org.jclouds.fujitsu.fgcp.suppliers.KeyStoreSupplier;
import org.testng.annotations.BeforeTest; import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Suppliers;
import com.google.inject.Guice; import com.google.inject.Guice;
import com.google.inject.Injector; import com.google.inject.Injector;
@ -56,40 +59,37 @@ public class FGCPRestClientModuleTest {
module = i.getInstance(FGCPRestClientModule.class); module = i.getInstance(FGCPRestClientModule.class);
} }
public void testKeyStoreAsPkcs12() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, CertificateException { public void testKeyStoreAsPkcs12() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException,
KeyStoreException, CertificateException {
assertNotNull(crypto); assertNotNull(crypto);
assertNotNull(module); assertNotNull(module);
// self-signed dummy cert: // self-signed dummy cert:
// keytool -genkey -alias test-fgcp -keyalg RSA -keysize 1024 -validity 5475 -dname "CN=localhost" -keystore jclouds-test-fgcp.p12 -storepass jcloudsjclouds -storetype pkcs12 // keytool -genkey -alias test-fgcp -keyalg RSA -keysize 1024 -validity 5475 -dname "CN=localhost" -keystore
// jclouds-test-fgcp.p12 -storepass jcloudsjclouds -storetype pkcs12
String cert = "/certs/jclouds-test-fgcp.p12"; String cert = "/certs/jclouds-test-fgcp.p12";
String keyPassword = "jcloudsjclouds";
URL url = this.getClass().getResource(cert); URL url = this.getClass().getResource(cert);
String certPath = url.getFile(); String certPath = url.getFile();
KeyStore ks = module.provideKeyStore(crypto, certPath, keyPassword); KeyStore ks = new KeyStoreSupplier(crypto, Suppliers.ofInstance(new Credentials(certPath, "jcloudsjclouds")))
.get();
assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias"); assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias");
} }
/* public void testKeyStoreAsPEM() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, KeyStoreException, CertificateException { /*
assertNotNull(crypto); * public void testKeyStoreAsPEM() throws IOException, InvalidKeySpecException, NoSuchAlgorithmException,
assertNotNull(module); * KeyStoreException, CertificateException { assertNotNull(crypto); assertNotNull(module);
*
//openssl pkcs12 -nodes -in jclouds-test-fgcp.p12 -out jclouds-test-fgcp.pem * //openssl pkcs12 -nodes -in jclouds-test-fgcp.p12 -out jclouds-test-fgcp.pem // String privKeyFilename =
// String privKeyFilename = "D:\\UserCert.pem.pkcs12-nodes";//_nobags"; * "D:\\UserCert.pem.pkcs12-nodes";//_nobags"; String cert = "/certs/jclouds-test-fgcp.pem"; String keyPassword =
String cert = "/certs/jclouds-test-fgcp.pem"; * "jcloudsjclouds";
String keyPassword = "jcloudsjclouds"; *
* URL url = this.getClass().getResource(cert); String certPath = url.getFile(); Scanner scanner = new Scanner(new
URL url = this.getClass().getResource(cert); * File(certPath)); String content = scanner.useDelimiter("\\A").next();
String certPath = url.getFile(); *
Scanner scanner = new Scanner(new File(certPath)); * KeyStore ks = module.provideKeyStore(crypto, content, keyPassword);
String content = scanner.useDelimiter("\\A").next(); *
* assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias"); }
KeyStore ks = module.provideKeyStore(crypto, content, keyPassword); */
assertNotNull(ks.getCertificate("test-fgcp"), "cert with alias");
}
*/
} }

View File

@ -18,12 +18,15 @@
*/ */
package org.jclouds.googlecompute.config; package org.jclouds.googlecompute.config;
import com.google.common.base.Predicate; import static com.google.common.base.Preconditions.checkState;
import com.google.common.base.Splitter; import static com.google.common.base.Suppliers.compose;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables; import java.util.Map;
import com.google.inject.Provides; import java.util.concurrent.atomic.AtomicReference;
import com.google.inject.TypeLiteral;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.googlecompute.GoogleComputeApi; import org.jclouds.googlecompute.GoogleComputeApi;
import org.jclouds.googlecompute.GoogleComputeAsyncApi; import org.jclouds.googlecompute.GoogleComputeAsyncApi;
import org.jclouds.googlecompute.domain.Operation; import org.jclouds.googlecompute.domain.Operation;
@ -52,13 +55,16 @@ import org.jclouds.http.annotation.ServerError;
import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.DateAdapter;
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import java.util.Map; import com.google.common.base.Function;
import java.util.concurrent.atomic.AtomicReference; import com.google.common.base.Predicate;
import com.google.common.base.Splitter;
import static com.google.common.base.Preconditions.checkState; import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
/** /**
* Configures the GoogleCompute connection. * Configures the GoogleCompute connection.
@ -97,10 +103,15 @@ public class GoogleComputeRestClientModule extends RestClientModule<GoogleComput
} }
@Provides @Provides
@Singleton
@UserProject @UserProject
public String provideProject(@Identity String identity) { public Supplier<String> supplyProject(
checkState(identity.indexOf("@") != 1, "identity should be in project_id@developer.gserviceaccount.com format"); @org.jclouds.location.Provider final Supplier<Credentials> creds) {
return Iterables.get(Splitter.on("@").split(identity), 0); return compose(new Function<Credentials, String>() {
public String apply(Credentials in) {
checkState(in.identity.indexOf("@") != 1, "identity should be in project_id@developer.gserviceaccount.com format");
return Iterables.get(Splitter.on("@").split(in.identity), 0);
}
}, creds);
} }
} }

View File

@ -19,16 +19,17 @@
package org.jclouds.googlecompute.predicates; package org.jclouds.googlecompute.predicates;
import com.google.common.base.Predicate; import static com.google.common.base.Preconditions.checkNotNull;
import com.google.inject.Inject;
import org.jclouds.googlecompute.GoogleComputeApi;
import org.jclouds.googlecompute.config.UserProject;
import org.jclouds.googlecompute.domain.Operation;
import org.jclouds.googlecompute.features.OperationApi;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static com.google.common.base.Preconditions.checkNotNull; import org.jclouds.googlecompute.GoogleComputeApi;
import org.jclouds.googlecompute.config.UserProject;
import org.jclouds.googlecompute.domain.Operation;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.inject.Inject;
/** /**
* Tests that an Operation is done, returning the completed Operation when it is. * Tests that an Operation is done, returning the completed Operation when it is.
@ -37,17 +38,19 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/ */
public class OperationDonePredicate implements Predicate<AtomicReference<Operation>> { public class OperationDonePredicate implements Predicate<AtomicReference<Operation>> {
private OperationApi api; private final GoogleComputeApi api;
private final Supplier<String> project;
@Inject @Inject
OperationDonePredicate(GoogleComputeApi api, @UserProject String project) { OperationDonePredicate(GoogleComputeApi api, @UserProject Supplier<String> project) {
this.api = api.getOperationApiForProject(project); this.api = api;
this.project = project;
} }
@Override @Override
public boolean apply(AtomicReference<Operation> input) { public boolean apply(AtomicReference<Operation> input) {
checkNotNull(input, "input"); checkNotNull(input, "input");
Operation current = api.get(input.get().getName()); Operation current = api.getOperationApiForProject(project.get()).get(input.get().getName());
switch (current.getStatus()) { switch (current.getStatus()) {
case DONE: case DONE:
input.set(current); input.set(current);

View File

@ -37,6 +37,7 @@ import org.jclouds.oauth.v2.OAuthTestUtils;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.reflect.TypeToken; import com.google.common.reflect.TypeToken;
import com.google.inject.Key; import com.google.inject.Key;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -78,7 +79,8 @@ public class BaseGoogleComputeApiLiveTest extends BaseContextLiveTest<RestContex
} }
protected String getUserProject() { protected String getUserProject() {
return context.utils().injector().getInstance(Key.get(String.class, UserProject.class)); return context.utils().injector().getInstance(Key.get(new TypeLiteral<Supplier<String>>() {
}, UserProject.class)).get();
} }
protected Predicate<AtomicReference<Operation>> getOperationDonePredicate() { protected Predicate<AtomicReference<Operation>> getOperationDonePredicate() {

View File

@ -19,18 +19,19 @@
package org.jclouds.jenkins.v1.filters; package org.jclouds.jenkins.v1.filters;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static org.jclouds.jenkins.v1.JenkinsApiMetadata.ANONYMOUS_IDENTITY;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpException; import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.filters.BasicAuthentication; import org.jclouds.http.filters.BasicAuthentication;
import org.jclouds.jenkins.v1.JenkinsApiMetadata; import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Optional; import com.google.common.base.Supplier;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -39,18 +40,19 @@ import com.google.common.base.Optional;
@Singleton @Singleton
public class BasicAuthenticationUnlessAnonymous implements HttpRequestFilter { public class BasicAuthenticationUnlessAnonymous implements HttpRequestFilter {
private final Optional<BasicAuthentication> auth; private final Supplier<Credentials> creds;
private final BasicAuthentication auth;
@Inject @Inject
public BasicAuthenticationUnlessAnonymous(@Identity String user, BasicAuthentication auth) { public BasicAuthenticationUnlessAnonymous(@Provider Supplier<Credentials> creds, BasicAuthentication auth) {
this.auth = JenkinsApiMetadata.ANONYMOUS_IDENTITY.equals(checkNotNull(user, "user")) ? Optional this.creds = checkNotNull(creds, "creds");
.<BasicAuthentication> absent() : Optional.of(checkNotNull(auth, "auth")); this.auth = checkNotNull(auth, "auth");
} }
@Override @Override
public HttpRequest filter(HttpRequest request) throws HttpException { public HttpRequest filter(HttpRequest request) throws HttpException {
if (auth.isPresent()) if (ANONYMOUS_IDENTITY.equals(checkNotNull(creds.get().identity, "user")))
return auth.get().filter(request); return request;
return request; return auth.filter(request);
} }
} }

View File

@ -18,6 +18,7 @@
*/ */
package org.jclouds.nodepool.config; package org.jclouds.nodepool.config;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static org.jclouds.nodepool.config.NodePoolProperties.BACKEND_GROUP; import static org.jclouds.nodepool.config.NodePoolProperties.BACKEND_GROUP;
@ -82,15 +83,16 @@ public class BindBackendComputeService extends BindJcloudsModules {
@Backend @Backend
@Exposed @Exposed
protected Supplier<ComputeService> makeBackendComputeService(@Backend final String provider, protected Supplier<ComputeService> makeBackendComputeService(@Backend final String provider,
@Backend final Set<Module> modules, @Provider final Credentials creds, @Backend final Set<Module> modules, @Provider final Supplier<Credentials> creds,
@Backend final Supplier<Properties> overrides, final Closer closer) { @Backend final Supplier<Properties> overrides, final Closer closer) {
return Suppliers.memoize(new Supplier<ComputeService>() { return Suppliers.memoize(new Supplier<ComputeService>() {
@Override @Override
public ComputeService get() { public ComputeService get() {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
ComputeServiceContext ctx = ContextBuilder.newBuilder(provider) ComputeServiceContext ctx = ContextBuilder.newBuilder(provider)
.credentials(creds.identity, creds.credential).overrides(overrides.get()).modules(modules) .credentials(currentCreds.identity, currentCreds.credential).overrides(overrides.get())
.buildView(ComputeServiceContext.class); .modules(modules).buildView(ComputeServiceContext.class);
closer.addToClose(ctx); closer.addToClose(ctx);
return ctx.getComputeService(); return ctx.getComputeService();
} }

View File

@ -27,9 +27,7 @@ import java.util.Properties;
import org.jclouds.ContextBuilder; import org.jclouds.ContextBuilder;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.nodepool.Backend;
import org.jclouds.nodepool.config.NodePoolProperties; import org.jclouds.nodepool.config.NodePoolProperties;
import org.jclouds.rest.annotations.Credential;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -58,8 +56,6 @@ public class NodePoolComputeServiceContextTest {
.getInstance(Key.get(new TypeLiteral<Supplier<ComputeService>>() { .getInstance(Key.get(new TypeLiteral<Supplier<ComputeService>>() {
}, Backend.class)).get(); }, Backend.class)).get();
assertEquals(stub.getContext().unwrap().getIdentity(), "foo");
assertEquals(stub.getContext().utils().injector().getInstance(Key.get(String.class, Credential.class)), "bar");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getEndpoint(), "gooend"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getEndpoint(), "gooend");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getVersion(), "1.1"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getVersion(), "1.1");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getBuildVersion().get(), "1.1-2"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getBuildVersion().get(), "1.1-2");

View File

@ -31,7 +31,6 @@ import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule; import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.nodepool.Backend; import org.jclouds.nodepool.Backend;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.ssh.SshClient; import org.jclouds.ssh.SshClient;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -65,8 +64,6 @@ public class BindBackendComputeServiceTest {
.getInstance(Key.get(new TypeLiteral<Supplier<ComputeService>>() { .getInstance(Key.get(new TypeLiteral<Supplier<ComputeService>>() {
}, Backend.class)).get(); }, Backend.class)).get();
assertEquals(stub.getContext().unwrap().getIdentity(), "foo");
assertEquals(stub.getContext().utils().injector().getInstance(Key.get(String.class, Credential.class)), "bar");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getEndpoint(), "gooend"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getEndpoint(), "gooend");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getVersion(), "1.1"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getVersion(), "1.1");
assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getBuildVersion().get(), "1.1-2"); assertEquals(stub.getContext().unwrap().getProviderMetadata().getApiMetadata().getBuildVersion().get(), "1.1-2");

View File

@ -69,7 +69,6 @@ public class OAuthCredentials extends Credentials {
return this; return this;
} }
@SuppressWarnings("unchecked")
public OAuthCredentials build() { public OAuthCredentials build() {
return new OAuthCredentials(checkNotNull(identity), credential, privateKey); return new OAuthCredentials(checkNotNull(identity), credential, privateKey);
} }

View File

@ -18,74 +18,98 @@
*/ */
package org.jclouds.oauth.v2.functions; package org.jclouds.oauth.v2.functions;
import com.google.common.base.Supplier; import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.crypto.Pems; import static com.google.common.base.Preconditions.checkState;
import org.jclouds.io.Payloads; import static com.google.common.base.Throwables.propagate;
import org.jclouds.oauth.v2.domain.OAuthCredentials; import static java.lang.String.format;
import org.jclouds.rest.annotations.Credential; import static org.jclouds.crypto.Pems.privateKeySpec;
import org.jclouds.rest.annotations.Identity; import static org.jclouds.io.Payloads.newStringPayload;
import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM;
import static org.jclouds.oauth.v2.OAuthConstants.OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import java.io.IOException; import java.io.IOException;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import static com.google.common.base.Preconditions.checkState; import javax.inject.Inject;
import static java.lang.String.format; import javax.inject.Named;
import static org.jclouds.oauth.v2.OAuthConstants.NO_ALGORITHM; import javax.inject.Singleton;
import static org.jclouds.oauth.v2.OAuthConstants.OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES;
import static org.jclouds.oauth.v2.config.OAuthProperties.SIGNATURE_OR_MAC_ALGORITHM; import org.jclouds.domain.Credentials;
import org.jclouds.location.Provider;
import org.jclouds.oauth.v2.domain.OAuthCredentials;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Supplier;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
/** /**
* Loads {@link OAuthCredentials} from a pem private key using the KeyFactory obtained from the * Loads {@link OAuthCredentials} from a pem private key using the KeyFactory obtained from the JWT Algorithm
* JWT Algorithm Name<->KeyFactory name mapping in OAuthConstants. The pem pk algorithm must match the KeyFactory * Name<->KeyFactory name mapping in OAuthConstants. The pem pk algorithm must match the KeyFactory algorithm.
* algorithm. *
*
* @author David Alves * @author David Alves
* @see org.jclouds.oauth.v2.OAuthConstants#OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES * @see org.jclouds.oauth.v2.OAuthConstants#OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES
*/ */
@Singleton @Singleton
public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> { public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> {
private final Supplier<Credentials> creds;
private final String identity; private final LoadingCache<Credentials, OAuthCredentials> keyCache;
private final String privateKeyInPemFormat;
private final String keyFactoryAlgorithm;
private OAuthCredentials credentials;
@Inject @Inject
public OAuthCredentialsSupplier(@Identity String identity, public OAuthCredentialsSupplier(@Provider Supplier<Credentials> creds, OAuthCredentialsForCredentials loader,
@Credential String privateKeyInPemFormat, @Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) { this.creds = creds;
this.identity = identity;
this.privateKeyInPemFormat = privateKeyInPemFormat;
checkState(OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm), checkState(OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm),
format("No mapping for key factory for algorithm: %s", signatureOrMacAlgorithm)); format("No mapping for key factory for algorithm: %s", signatureOrMacAlgorithm));
this.keyFactoryAlgorithm = OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.get(signatureOrMacAlgorithm); // throw out the private key related to old credentials
this.keyCache = CacheBuilder.newBuilder().maximumSize(2).build(checkNotNull(loader, "loader"));
} }
@PostConstruct /**
public void loadPrivateKey() throws NoSuchAlgorithmException, IOException, InvalidKeySpecException { * it is relatively expensive to extract a private key from a PEM. cache the relationship between current credentials
if (keyFactoryAlgorithm.equals(NO_ALGORITHM)) { * so that the private key is only recalculated once.
this.credentials = new OAuthCredentials.Builder().identity(identity).credential */
(privateKeyInPemFormat).build(); @VisibleForTesting
return; static class OAuthCredentialsForCredentials extends CacheLoader<Credentials, OAuthCredentials> {
private final String keyFactoryAlgorithm;
@Inject
public OAuthCredentialsForCredentials(@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
this.keyFactoryAlgorithm = OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.get(checkNotNull(
signatureOrMacAlgorithm, "signatureOrMacAlgorithm"));
}
@Override
public OAuthCredentials load(Credentials in) {
try {
String identity = in.identity;
String privateKeyInPemFormat = in.credential;
if (keyFactoryAlgorithm.equals(NO_ALGORITHM)) {
return new OAuthCredentials.Builder().identity(identity).credential(privateKeyInPemFormat).build();
}
KeyFactory keyFactory = KeyFactory.getInstance(keyFactoryAlgorithm);
PrivateKey privateKey = keyFactory.generatePrivate(privateKeySpec(newStringPayload(privateKeyInPemFormat)));
return new OAuthCredentials.Builder().identity(identity).credential(privateKeyInPemFormat)
.privateKey(privateKey).build();
} catch (NoSuchAlgorithmException e) {
throw propagate(e);
} catch (InvalidKeySpecException e) {
throw propagate(e);
} catch (IOException e) {
throw propagate(e);
}
} }
KeyFactory keyFactory = KeyFactory.getInstance(keyFactoryAlgorithm);
PrivateKey privateKey = keyFactory.generatePrivate(Pems.privateKeySpec(Payloads.newStringPayload
(privateKeyInPemFormat)));
this.credentials = new OAuthCredentials.Builder().identity(identity).credential
(privateKeyInPemFormat).privateKey(privateKey).build();
} }
@Override @Override
public OAuthCredentials get() { public OAuthCredentials get() {
return this.credentials; return keyCache.getUnchecked(checkNotNull(creds.get(), "credential supplier returned null"));
} }
} }

View File

@ -18,9 +18,10 @@
*/ */
package org.jclouds.oauth.v2.functions; package org.jclouds.oauth.v2.functions;
import org.jclouds.oauth.v2.domain.OAuthCredentials; import static com.google.common.base.Suppliers.ofInstance;
import org.jclouds.util.Strings2; import static org.jclouds.util.Strings2.toStringAndClose;
import org.testng.annotations.Test; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
@ -30,8 +31,10 @@ import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import static org.testng.Assert.assertEquals; import org.jclouds.domain.Credentials;
import static org.testng.Assert.assertNotNull; import org.jclouds.oauth.v2.domain.OAuthCredentials;
import org.jclouds.oauth.v2.functions.OAuthCredentialsSupplier.OAuthCredentialsForCredentials;
import org.testng.annotations.Test;
/** /**
* Test loading the credentials by extracting a pk from a PKCS12 keystore. * Test loading the credentials by extracting a pk from a PKCS12 keystore.
@ -40,10 +43,9 @@ import static org.testng.Assert.assertNotNull;
public class OAuthCredentialsFromPKTest { public class OAuthCredentialsFromPKTest {
public static OAuthCredentials loadOAuthCredentials() throws IOException, NoSuchAlgorithmException, public static OAuthCredentials loadOAuthCredentials() throws IOException, NoSuchAlgorithmException,
CertificateException, InvalidKeySpecException { CertificateException, InvalidKeySpecException {
OAuthCredentialsSupplier loader = new OAuthCredentialsSupplier("foo", OAuthCredentialsSupplier loader = new OAuthCredentialsSupplier(ofInstance(new Credentials("foo",
Strings2.toStringAndClose(new FileInputStream("src/test/resources/testpk.pem")), "RS256"); toStringAndClose(new FileInputStream("src/test/resources/testpk.pem")))), new OAuthCredentialsForCredentials("RS256"), "RS256");
loader.loadPrivateKey();
return loader.get(); return loader.get();
} }

View File

@ -34,6 +34,7 @@ import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.CIMOperatingSystem; import org.jclouds.compute.domain.CIMOperatingSystem;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError; import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.Redirection;
@ -42,7 +43,6 @@ import org.jclouds.json.Json;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.ImplicitLocationSupplier; import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.ConfiguresRestClient;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.config.RestClientModule; import org.jclouds.rest.config.RestClientModule;
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier; import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
import org.jclouds.savvis.vpdc.VPDCApi; import org.jclouds.savvis.vpdc.VPDCApi;
@ -107,12 +107,12 @@ public class VPDCRestClientModule extends RestClientModule<VPDCApi, VPDCAsyncApi
@org.jclouds.savvis.vpdc.internal.Org @org.jclouds.savvis.vpdc.internal.Org
@Singleton @Singleton
protected Supplier<Set<org.jclouds.savvis.vpdc.domain.Resource>> provideOrgs(Supplier<VCloudSession> cache, protected Supplier<Set<org.jclouds.savvis.vpdc.domain.Resource>> provideOrgs(Supplier<VCloudSession> cache,
@Identity final String user) { @org.jclouds.location.Provider final Supplier<Credentials> creds) {
return Suppliers.compose(new Function<VCloudSession, Set<org.jclouds.savvis.vpdc.domain.Resource>>() { return Suppliers.compose(new Function<VCloudSession, Set<org.jclouds.savvis.vpdc.domain.Resource>>() {
@Override @Override
public Set<org.jclouds.savvis.vpdc.domain.Resource> apply(VCloudSession input) { public Set<org.jclouds.savvis.vpdc.domain.Resource> apply(VCloudSession input) {
checkState(input.getOrgs().size() > 0, "No orgs present for user: " + user); checkState(input.getOrgs().size() > 0, "No orgs present for user: " + creds.get());
return input.getOrgs(); return input.getOrgs();
} }

View File

@ -1,5 +1,7 @@
package org.jclouds.smartos; package org.jclouds.smartos;
import static com.google.common.base.Preconditions.checkNotNull;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
@ -11,12 +13,10 @@ import java.util.regex.Pattern;
import javax.inject.Inject; import javax.inject.Inject;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.Json; import org.jclouds.json.Json;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.smartos.compute.domain.DataSet; import org.jclouds.smartos.compute.domain.DataSet;
import org.jclouds.smartos.compute.domain.VM; import org.jclouds.smartos.compute.domain.VM;
import org.jclouds.smartos.compute.domain.VmSpecification; import org.jclouds.smartos.compute.domain.VmSpecification;
@ -34,8 +34,7 @@ import com.google.common.util.concurrent.RateLimiter;
*/ */
public class SmartOSHostController { public class SmartOSHostController {
protected final String hostname; protected final String hostname;
protected final String username; protected final Supplier<Credentials> creds;
protected final String password;
protected final SshClient.Factory sshClientFactory; protected final SshClient.Factory sshClientFactory;
protected final Json json; protected final Json json;
@ -59,11 +58,10 @@ public class SmartOSHostController {
} }
@Inject @Inject
protected SmartOSHostController(@Provider Supplier<URI> provider, @Nullable @Identity String identity, protected SmartOSHostController(@Provider Supplier<URI> provider,
@Nullable @Credential String credential, SshClient.Factory sshFactory, Json json) { @org.jclouds.location.Provider final Supplier<Credentials> creds, SshClient.Factory sshFactory, Json json) {
this.hostname = provider.get().getHost(); this.hostname = provider.get().getHost();
this.username = identity; this.creds = creds;
this.password = credential;
this.sshClientFactory = sshFactory; this.sshClientFactory = sshFactory;
this.json = json; this.json = json;
} }
@ -76,22 +74,16 @@ public class SmartOSHostController {
return hostname; return hostname;
} }
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public SshClient.Factory getSshClientFactory() { public SshClient.Factory getSshClientFactory() {
return sshClientFactory; return sshClientFactory;
} }
protected SshClient getConnection() { protected SshClient getConnection() {
if (_connection == null) { if (_connection == null) {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
LoginCredentials credentials = new LoginCredentials.Builder().user(username).password(password).build(); LoginCredentials credentials = new LoginCredentials.Builder().user(currentCreds.identity)
.password(currentCreds.credential).build();
_connection = getSshClientFactory().create(HostAndPort.fromParts(hostname, 22), credentials); _connection = getSshClientFactory().create(HostAndPort.fromParts(hostname, 22), credentials);

View File

@ -18,13 +18,11 @@
*/ */
package org.jclouds.vcloud.director.v1_5.config; package org.jclouds.vcloud.director.v1_5.config;
import static com.google.common.base.Throwables.propagate;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL; import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi; import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
@ -227,15 +225,11 @@ public class VCloudDirectorRestClientModule extends RestClientModule<VCloudDirec
@Provides @Provides
@Singleton @Singleton
protected Supplier<SessionWithToken> provideSessionWithTokenSupplier( protected Supplier<SessionWithToken> provideSessionWithTokenSupplier(
final LoadingCache<Credentials, SessionWithToken> cache, @Provider final Credentials creds) { final LoadingCache<Credentials, SessionWithToken> cache, @Provider final Supplier<Credentials> creds) {
return new Supplier<SessionWithToken>() { return new Supplier<SessionWithToken>() {
@Override @Override
public SessionWithToken get() { public SessionWithToken get() {
try { return cache.getUnchecked(creds.get());
return cache.get(creds);
} catch (ExecutionException e) {
throw propagate(e.getCause());
}
} }
}; };
} }

View File

@ -22,18 +22,20 @@ import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.annotations.Name; import org.jclouds.annotations.Name;
import org.jclouds.domain.Credentials;
import org.jclouds.lifecycle.Closer; import org.jclouds.lifecycle.Closer;
import org.jclouds.location.Provider;
import org.jclouds.providers.ProviderMetadata; import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.rest.Utils; import org.jclouds.rest.Utils;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.internal.RestContextImpl; import org.jclouds.rest.internal.RestContextImpl;
import org.jclouds.vcloud.director.v1_5.VCloudDirectorContext; import org.jclouds.vcloud.director.v1_5.VCloudDirectorContext;
import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncApi;
import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminApi; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminApi;
import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorAsyncApi; import org.jclouds.vcloud.director.v1_5.admin.VCloudDirectorAdminAsyncApi;
import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorApi; import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorApi;
import org.jclouds.vcloud.director.v1_5.user.VCloudDirectorAsyncApi;
import com.google.common.base.Supplier;
import com.google.inject.Injector; import com.google.inject.Injector;
import com.google.inject.TypeLiteral; import com.google.inject.TypeLiteral;
@ -46,10 +48,11 @@ public class VCloudDirectorContextImpl extends RestContextImpl<VCloudDirectorApi
private final RestContext<VCloudDirectorAdminApi, VCloudDirectorAdminAsyncApi> adminContext; private final RestContext<VCloudDirectorAdminApi, VCloudDirectorAdminAsyncApi> adminContext;
@Inject @Inject
VCloudDirectorContextImpl(@Name String name, ProviderMetadata providerMetadata, @Identity String identity, Utils utils, Closer closer, VCloudDirectorContextImpl(@Name String name, ProviderMetadata providerMetadata,
Injector injector, RestContext<VCloudDirectorAdminApi, VCloudDirectorAdminAsyncApi> adminContext) { @Provider Supplier<Credentials> creds, Utils utils, Closer closer, Injector injector,
super(name, providerMetadata, identity, utils, closer, injector, TypeLiteral.get(VCloudDirectorApi.class), RestContext<VCloudDirectorAdminApi, VCloudDirectorAdminAsyncApi> adminContext) {
TypeLiteral.get(VCloudDirectorAsyncApi.class)); super(name, providerMetadata, creds, utils, closer, injector, TypeLiteral.get(VCloudDirectorApi.class),
TypeLiteral.get(VCloudDirectorAsyncApi.class));
this.adminContext = adminContext; this.adminContext = adminContext;
} }

View File

@ -23,18 +23,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI; import java.net.URI;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.NodeMetadataBuilder; import org.jclouds.compute.domain.NodeMetadataBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.domain.Credentials;
import org.jclouds.domain.LoginCredentials; import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Provider; import org.jclouds.location.Provider;
import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Function; import com.google.common.base.Function;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
@ -43,33 +36,25 @@ import com.google.inject.Inject;
import com.google.inject.Singleton; import com.google.inject.Singleton;
@Singleton @Singleton
public class HardcodedHostToHostNodeMetadata implements public class HardcodedHostToHostNodeMetadata implements Function<NodeMetadata, NodeMetadata> {
Function<NodeMetadata, NodeMetadata> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
private final Supplier<URI> providerSupplier; private final Supplier<URI> providerSupplier;
private final String username; private final Supplier<Credentials> creds;
private final String password;
@Inject @Inject
public HardcodedHostToHostNodeMetadata( public HardcodedHostToHostNodeMetadata(@Provider Supplier<URI> providerSupplier,
@Provider Supplier<URI> providerSupplier, @Provider Supplier<Credentials> creds) {
@Nullable @Identity String identity, this.providerSupplier = checkNotNull(providerSupplier, "endpoint to virtualbox websrvd is needed");
@Nullable @Credential String credential) { this.creds = creds;
this.providerSupplier = checkNotNull(providerSupplier,
"endpoint to virtualbox websrvd is needed");
this.username = identity;
this.password = credential.equals("CHANGE_ME") ? "" : credential;
} }
@Override @Override
public NodeMetadata apply(NodeMetadata host) { public NodeMetadata apply(NodeMetadata host) {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
String username = currentCreds.identity;
String password = currentCreds.credential.equals("CHANGE_ME") ? "" : currentCreds.credential;
LoginCredentials.Builder credentialsBuilder = LoginCredentials.builder( LoginCredentials.Builder credentialsBuilder = LoginCredentials.builder(host.getCredentials()).user(username);
host.getCredentials()).user(username);
if (!password.isEmpty()) if (!password.isEmpty())
credentialsBuilder.password(password); credentialsBuilder.password(password);

View File

@ -29,13 +29,14 @@ import javax.inject.Named;
import org.jclouds.Constants; import org.jclouds.Constants;
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.HttpRequestFilter; import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.HttpUtils; import org.jclouds.http.HttpUtils;
import org.jclouds.location.Provider;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
/** /**
@ -43,8 +44,7 @@ import com.google.common.collect.ImmutableMap;
*/ */
public class SharedKeyLiteAuthentication implements HttpRequestFilter { public class SharedKeyLiteAuthentication implements HttpRequestFilter {
private final String apiKey; private final Supplier<Credentials> creds;
private final String secret;
private final Long timeStamp; private final Long timeStamp;
private final HttpUtils utils; private final HttpUtils utils;
@ -53,10 +53,8 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
Logger signatureLog = Logger.NULL; Logger signatureLog = Logger.NULL;
@Inject @Inject
public SharedKeyLiteAuthentication(@Identity String apiKey, @Credential String secret, @TimeStamp Long timeStamp, public SharedKeyLiteAuthentication(@Provider Supplier<Credentials> creds, @TimeStamp Long timeStamp, HttpUtils utils) {
HttpUtils utils) { this.creds = creds;
this.apiKey = apiKey;
this.secret = secret;
this.timeStamp = timeStamp; this.timeStamp = timeStamp;
this.utils = utils; this.utils = utils;
} }
@ -65,13 +63,14 @@ public class SharedKeyLiteAuthentication implements HttpRequestFilter {
public HttpRequest filter(HttpRequest request) { public HttpRequest filter(HttpRequest request) {
String toSign = createStringToSign(); String toSign = createStringToSign();
String signatureMd5 = getMd5For(toSign); String signatureMd5 = getMd5For(toSign);
request = request.toBuilder().replaceQueryParams(ImmutableMap.of("sig", signatureMd5, "api_key" ,apiKey)).build(); request = request.toBuilder()
.replaceQueryParams(ImmutableMap.of("sig", signatureMd5, "api_key", creds.get().identity)).build();
utils.logRequest(signatureLog, request, "<<"); utils.logRequest(signatureLog, request, "<<");
return request; return request;
} }
private String createStringToSign() { private String createStringToSign() {
return format("%s%s%s", apiKey, secret, timeStamp); return format("%s%s%s", creds.get().identity, creds.get().credential, timeStamp);
} }
private String getMd5For(String stringToHash) { private String getMd5For(String stringToHash) {

View File

@ -33,7 +33,6 @@ import static org.jclouds.util.Strings2.toInputStream;
import java.io.IOException; import java.io.IOException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import javax.annotation.PostConstruct;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -42,6 +41,7 @@ import org.jclouds.blobstore.domain.Blob;
import org.jclouds.blobstore.functions.BlobToHttpGetOptions; import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
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.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi; import org.jclouds.hpcloud.objectstorage.HPCloudObjectStorageAsyncApi;
import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpRequest;
import org.jclouds.http.options.GetOptions; import org.jclouds.http.options.GetOptions;
@ -50,8 +50,6 @@ import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
import org.jclouds.openstack.swift.blobstore.functions.BlobToObject; import org.jclouds.openstack.swift.blobstore.functions.BlobToObject;
import org.jclouds.openstack.swift.domain.SwiftObject; import org.jclouds.openstack.swift.domain.SwiftObject;
import org.jclouds.reflect.Invocation; import org.jclouds.reflect.Invocation;
import org.jclouds.rest.annotations.Credential;
import org.jclouds.rest.annotations.Identity;
import org.jclouds.rest.internal.GeneratedHttpRequest; import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor; import org.jclouds.rest.internal.RestAnnotationProcessor;
@ -75,9 +73,7 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
private final Provider<Long> unixEpochTimestampProvider; private final Provider<Long> unixEpochTimestampProvider;
private final Supplier<Access> access; private final Supplier<Access> access;
private String tenantId; private final Supplier<Credentials> creds;
private final String accessKeyId;
private final String secretKey;
private final BlobToObject blobToObject; private final BlobToObject blobToObject;
private final BlobToHttpGetOptions blob2HttpGetOptions; private final BlobToHttpGetOptions blob2HttpGetOptions;
@ -89,16 +85,15 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
@Inject @Inject
public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor<HPCloudObjectStorageAsyncApi> processor, public HPCloudObjectStorageBlobRequestSigner(RestAnnotationProcessor<HPCloudObjectStorageAsyncApi> processor,
BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto, BlobToObject blobToObject, BlobToHttpGetOptions blob2HttpGetOptions, Crypto crypto,
@TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access, @Identity String accessKey, @TimeStamp Provider<Long> unixEpochTimestampProvider, Supplier<Access> access,
@Credential String secretKey) throws SecurityException, NoSuchMethodException { @org.jclouds.location.Provider final Supplier<Credentials> creds) throws SecurityException,
NoSuchMethodException {
this.processor = checkNotNull(processor, "processor"); this.processor = checkNotNull(processor, "processor");
this.crypto = checkNotNull(crypto, "crypto"); this.crypto = checkNotNull(crypto, "crypto");
this.unixEpochTimestampProvider = checkNotNull(unixEpochTimestampProvider, "unixEpochTimestampProvider"); this.unixEpochTimestampProvider = checkNotNull(unixEpochTimestampProvider, "unixEpochTimestampProvider");
this.access = checkNotNull(access, "access"); this.access = checkNotNull(access, "access");
// accessKey is of the form tenantName:accessKeyId (not tenantId) this.creds = checkNotNull(creds, "creds");
this.accessKeyId = accessKey.substring(accessKey.indexOf(':') + 1);
this.secretKey = secretKey;
this.blobToObject = checkNotNull(blobToObject, "blobToObject"); this.blobToObject = checkNotNull(blobToObject, "blobToObject");
this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions"); this.blob2HttpGetOptions = checkNotNull(blob2HttpGetOptions, "blob2HttpGetOptions");
@ -111,12 +106,6 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
SwiftObject.class)); SwiftObject.class));
} }
@PostConstruct
public void populateTenantId() {
// Defer call from constructor since access.get issues an RPC.
this.tenantId = access.get().getToken().getTenant().get().getId();
}
@Override @Override
public HttpRequest signGetBlob(String container, String name) { public HttpRequest signGetBlob(String container, String name) {
checkNotNull(container, "container"); checkNotNull(container, "container");
@ -166,6 +155,12 @@ public class HPCloudObjectStorageBlobRequestSigner implements BlobRequestSigner
} }
private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) { private HttpRequest signForTemporaryAccess(HttpRequest request, long timeInSeconds) {
Credentials currentCreds = checkNotNull(creds.get(), "credential supplier returned null");
// accessKey is of the form tenantName:accessKeyId (not tenantId)
String accessKeyId = currentCreds.identity.substring(currentCreds.identity.indexOf(':') + 1);
String secretKey = currentCreds.credential;
String tenantId = access.get().getToken().getTenant().get().getId();
HttpRequest.Builder<?> builder = request.toBuilder(); HttpRequest.Builder<?> builder = request.toBuilder();
// HP Cloud does not use X-Auth-Token for temporary signed URLs and // HP Cloud does not use X-Auth-Token for temporary signed URLs and
// leaking this allows clients arbitrary privileges until token timeout. // leaking this allows clients arbitrary privileges until token timeout.