mirror of https://github.com/apache/jclouds.git
Merge pull request #1361 from dralves/oauth-bug
made oauth throw AuthorizationException when required
This commit is contained in:
commit
ef08f1b8d3
|
@ -16,10 +16,30 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.jclouds.oauth.v2.functions;
|
||||
|
||||
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.util.concurrent.UncheckedExecutionException;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.oauth.v2.domain.OAuthCredentials;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Throwables.propagate;
|
||||
import static java.lang.String.format;
|
||||
import static org.jclouds.crypto.Pems.privateKeySpec;
|
||||
|
@ -27,31 +47,12 @@ 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 java.io.IOException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
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;
|
||||
import static org.jclouds.util.Throwables2.getFirstThrowableOfType;
|
||||
|
||||
/**
|
||||
* Loads {@link OAuthCredentials} from a pem private key using the KeyFactory obtained from the JWT Algorithm
|
||||
* Name<->KeyFactory name mapping in OAuthConstants. The pem pk algorithm must match the KeyFactory algorithm.
|
||||
*
|
||||
*
|
||||
* @author David Alves
|
||||
* @see org.jclouds.oauth.v2.OAuthConstants#OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES
|
||||
*/
|
||||
|
@ -63,10 +64,10 @@ public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> {
|
|||
|
||||
@Inject
|
||||
public OAuthCredentialsSupplier(@Provider Supplier<Credentials> creds, OAuthCredentialsForCredentials loader,
|
||||
@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
|
||||
@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
|
||||
this.creds = creds;
|
||||
checkState(OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm),
|
||||
format("No mapping for key factory for algorithm: %s", signatureOrMacAlgorithm));
|
||||
checkArgument(OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.containsKey(signatureOrMacAlgorithm),
|
||||
format("No mapping for key factory for algorithm: %s", signatureOrMacAlgorithm));
|
||||
// throw out the private key related to old credentials
|
||||
this.keyCache = CacheBuilder.newBuilder().maximumSize(2).build(checkNotNull(loader, "loader"));
|
||||
}
|
||||
|
@ -82,7 +83,7 @@ public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> {
|
|||
@Inject
|
||||
public OAuthCredentialsForCredentials(@Named(SIGNATURE_OR_MAC_ALGORITHM) String signatureOrMacAlgorithm) {
|
||||
this.keyFactoryAlgorithm = OAUTH_ALGORITHM_NAMES_TO_KEYFACTORY_ALGORITHM_NAMES.get(checkNotNull(
|
||||
signatureOrMacAlgorithm, "signatureOrMacAlgorithm"));
|
||||
signatureOrMacAlgorithm, "signatureOrMacAlgorithm"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,20 +97,31 @@ public class OAuthCredentialsSupplier implements Supplier<OAuthCredentials> {
|
|||
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);
|
||||
.privateKey(privateKey).build();
|
||||
} catch (IOException e) {
|
||||
throw propagate(e);
|
||||
// catch security exceptions InvalidKeySpecException and NoSuchAlgorithmException as GSE
|
||||
} catch (GeneralSecurityException e) {
|
||||
throw new AuthorizationException("security exception loading credentials. " + e.getMessage(), e);
|
||||
// catch IAE that is thrown when parsing the pk fails
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new AuthorizationException("cannot parse pk. " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuthCredentials get() {
|
||||
return keyCache.getUnchecked(checkNotNull(creds.get(), "credential supplier returned null"));
|
||||
try {
|
||||
// loader always throws UncheckedExecutionException so no point in using get()
|
||||
return keyCache.getUnchecked(checkNotNull(creds.get(), "credential supplier returned null"));
|
||||
} catch (UncheckedExecutionException e) {
|
||||
Throwable authorizationException = getFirstThrowableOfType(e, AuthorizationException.class);
|
||||
if (authorizationException != null) {
|
||||
throw ((AuthorizationException) authorizationException);
|
||||
}
|
||||
throw propagate(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.jclouds.oauth.v2.functions;
|
||||
|
||||
import com.google.common.base.Suppliers;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.oauth.v2.OAuthTestUtils;
|
||||
import org.jclouds.rest.AuthorizationException;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.jclouds.oauth.v2.functions.OAuthCredentialsSupplier.OAuthCredentialsForCredentials;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* @author David Alves
|
||||
*/
|
||||
@Test(groups = "unit")
|
||||
public class OAuthCredentialsSupplierTest {
|
||||
|
||||
@Test(expectedExceptions = AuthorizationException.class)
|
||||
public void testAuthorizationExceptionIsThrownOnBadKeys() {
|
||||
OAuthCredentialsSupplier supplier = new OAuthCredentialsSupplier(Suppliers.ofInstance(new Credentials("MOMMA",
|
||||
"MIA")), new OAuthCredentialsForCredentials("RS256"), "RS256");
|
||||
supplier.get();
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||
public void testGSEChildExceptionsPropagateAsAuthorizationException() {
|
||||
OAuthCredentialsSupplier supplier = new OAuthCredentialsSupplier(Suppliers.ofInstance(new Credentials("MOMMA",
|
||||
"MIA")), new OAuthCredentialsForCredentials("MOMMA"), "MOMMA");
|
||||
supplier.get();
|
||||
}
|
||||
|
||||
public void testCredentialsAreLoadedOnRightAlgoAndCredentials() {
|
||||
Properties propertied = OAuthTestUtils.defaultProperties(new Properties());
|
||||
Credentials validCredentials = new Credentials(propertied.getProperty("oauth.identity"),
|
||||
propertied.getProperty("oauth.credential"));
|
||||
OAuthCredentialsSupplier supplier = new OAuthCredentialsSupplier(Suppliers.ofInstance(validCredentials),
|
||||
new OAuthCredentialsForCredentials("RS256"), "RS256");
|
||||
assertNotNull(supplier.get());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue