Author: jawi
Date: Tue May 1 10:35:05 2012
New Revision: 1332609
URL: http://svn.apache.org/viewvc?rev=1332609&view=rev
Log:
ACE-270: allow custom keystore/truststore to be supplied to the
ClientCertAuthProcessor.
Modified:
ace/trunk/ace-authenticationprocessor-clientcert/src/main/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessor.java
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessorTest.java
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/MemoryKeyStore.java
ace/trunk/ace-connectionfactory/pom.xml
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
Modified:
ace/trunk/ace-authenticationprocessor-clientcert/src/main/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessor.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-authenticationprocessor-clientcert/src/main/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessor.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-authenticationprocessor-clientcert/src/main/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessor.java
(original)
+++
ace/trunk/ace-authenticationprocessor-clientcert/src/main/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessor.java
Tue May 1 10:35:05 2012
@@ -32,14 +32,14 @@ import org.apache.ace.authentication.api
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.log.LogService;
+import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
import org.osgi.service.useradmin.UserAdmin;
/**
- * Provides an {@link AuthenticationProcessor} that implements basic HTTP
authentication and looks
- * up a user in the {@link UserAdmin} service using (by default, can be
configured otherwise) the
- * keys "username" and "publickey". Only if the public key of the user in
UserAdmin equals to the
- * public key of the obtained certificate, the user is considered
authenticated.
+ * Provides an {@link AuthenticationProcessor} that implements authentication
based on certificates
+ * and looks up a user in the {@link UserAdmin} service using (by default, can
be configured
+ * otherwise) the key "username". If a matching user is found, it is
considered authenticated.
*/
public class ClientCertAuthenticationProcessor implements
AuthenticationProcessor, ManagedService {
@@ -48,14 +48,17 @@ public class ClientCertAuthenticationPro
static final String ATTRIBUTE_X509_CERTIFICATE =
"javax.servlet.request.X509Certificate";
static final String ATTRIBUTE_CIPHER_SUITE =
"javax.servlet.request.cipher_suite";
- static final String PROPERTY_KEY_USERNAME = "key.username";
- static final String PROPERTY_KEY_PUBLICKEY = "key.publickey";
-
- private static final String DEFAULT_PROPERTY_KEY_USERNAME = "username";
- private static final String DEFAULT_PROPERTY_KEY_PUBLICKEY = "publickey";
-
- private volatile String m_keyUsername = DEFAULT_PROPERTY_KEY_USERNAME;
- private volatile String m_keyPublicKey = DEFAULT_PROPERTY_KEY_PUBLICKEY;
+ static final String PROPERTY_USERNAME_LOOKUPKEY = "user.name.lookupKey";
+ static final String PROPERTY_USERNAME_MATCH_POLICY =
"user.name.matchPolicy";
+ static final String PROPERTY_VERIFY_CERT_VALIDITY =
"certificate.verifyValidity";
+
+ private static final String DEFAULT_PROPERTY_USERNAME_LOOKUPKEY =
"username";
+ private static final String DEFAULT_PROPERTY_USERNAME_MATCHPOLICY = "cn";
+ private static final boolean DEFAULT_PROPERTY_VERIFY_CERT_VALIDITY = true;
+
+ private volatile String m_nameLookupKey =
DEFAULT_PROPERTY_USERNAME_LOOKUPKEY;
+ private volatile String m_nameMatchPolicy =
DEFAULT_PROPERTY_USERNAME_MATCHPOLICY;
+ private volatile boolean m_verifyCertValidity =
DEFAULT_PROPERTY_VERIFY_CERT_VALIDITY;
private volatile LogService m_log;
/**
@@ -80,7 +83,12 @@ public class ClientCertAuthenticationPro
throw new IllegalArgumentException("Invalid context!");
}
- return (context[0] instanceof HttpServletRequest);
+ if (!(context[0] instanceof HttpServletRequest)) {
+ return false;
+ }
+
+ final HttpServletRequest request = (HttpServletRequest) context[0];
+ return (request.getAttribute(ATTRIBUTE_CIPHER_SUITE) != null) &&
(request.getAttribute(ATTRIBUTE_X509_CERTIFICATE) != null);
}
/**
@@ -112,15 +120,15 @@ public class ClientCertAuthenticationPro
return null;
}
- String username = getCommonName(cert);
- if (username == null) {
+ String name = getName(cert);
+ if (name == null) {
// No common name given; cannot retrieve user credentials...
m_log.log(LogService.LOG_DEBUG, "Failed to obtain common name of
X509 certificate!");
return null;
}
-
- User user = userAdmin.getUser(m_keyUsername, username);
- if (user == null || !user.hasCredential(m_keyPublicKey,
cert.getPublicKey().getEncoded())) {
+
+ User user = getUser(userAdmin, name);
+ if (user == null) {
// Invalid/unknown user!
m_log.log(LogService.LOG_DEBUG, "Failed to validate user using
certificate!");
return null;
@@ -134,38 +142,48 @@ public class ClientCertAuthenticationPro
*/
public void updated(Dictionary dictionary) throws ConfigurationException {
if (dictionary != null) {
- String keyUsername = (String)
dictionary.get(PROPERTY_KEY_USERNAME);
- if (keyUsername == null || "".equals(keyUsername.trim())) {
- throw new ConfigurationException(PROPERTY_KEY_USERNAME,
"Missing property");
+ String usernameLookupKey = (String)
dictionary.get(PROPERTY_USERNAME_LOOKUPKEY);
+ if (usernameLookupKey == null ||
"".equals(usernameLookupKey.trim())) {
+ throw new ConfigurationException(PROPERTY_USERNAME_LOOKUPKEY,
"Missing property");
}
- String keyPassword = (String)
dictionary.get(PROPERTY_KEY_PUBLICKEY);
- if (keyPassword == null || "".equals(keyPassword.trim())) {
- throw new ConfigurationException(PROPERTY_KEY_PUBLICKEY,
"Missing property");
+ String usernameMatchPolicy = (String)
dictionary.get(PROPERTY_USERNAME_MATCH_POLICY);
+ if (usernameMatchPolicy == null ||
"".equals(usernameMatchPolicy.trim())) {
+ throw new
ConfigurationException(PROPERTY_USERNAME_MATCH_POLICY, "Missing property");
+ }
+
+ Object verifyCertValidity =
dictionary.get(PROPERTY_VERIFY_CERT_VALIDITY);
+ if (verifyCertValidity == null ||
!("true".equals(verifyCertValidity) || "false".equals(verifyCertValidity))) {
+ throw new
ConfigurationException(PROPERTY_VERIFY_CERT_VALIDITY, "Missing or invalid
property!");
}
- m_keyUsername = keyUsername;
- m_keyPublicKey = keyPassword;
+ m_nameLookupKey = usernameLookupKey;
+ m_nameMatchPolicy = usernameMatchPolicy;
+ m_verifyCertValidity = Boolean.parseBoolean((String)
verifyCertValidity);
}
else {
- m_keyUsername = DEFAULT_PROPERTY_KEY_USERNAME;
- m_keyPublicKey = DEFAULT_PROPERTY_KEY_PUBLICKEY;
+ m_nameLookupKey = DEFAULT_PROPERTY_USERNAME_LOOKUPKEY;
+ m_nameMatchPolicy = DEFAULT_PROPERTY_USERNAME_MATCHPOLICY;
+ m_verifyCertValidity = DEFAULT_PROPERTY_VERIFY_CERT_VALIDITY;
}
}
/**
- * Retrieves the common name for the given certificate.
+ * Retrieves the name for the given certificate.
*
- * @param certificate the certificate to get its common name for, cannot
be <code>null</code>.
- * @return the common name for the given certificate, can be
<code>null</code>.
+ * @param certificate the certificate to get its name for, cannot be
<code>null</code>.
+ * @return the name for the given certificate, can be <code>null</code>.
*/
- private String getCommonName(X509Certificate certificate) {
+ private String getName(X509Certificate certificate) {
try {
String dn = certificate.getSubjectX500Principal().getName();
+ if ("dn".equalsIgnoreCase(m_nameMatchPolicy)) {
+ return dn;
+ }
LdapName ldapDN = new LdapName(dn);
for (Rdn rdn : ldapDN.getRdns()) {
- if ("CN".equals(rdn.getType())) {
+ if (m_nameMatchPolicy.equalsIgnoreCase(rdn.getType())) {
return (String) rdn.getValue();
}
}
@@ -177,6 +195,29 @@ public class ClientCertAuthenticationPro
}
/**
+ * Searches for a user with a given name.
+ * <p>
+ * This method first looks whether there's a user with the property
+ * "m_keyUsername" that matches the given username, if not found, it will
+ * try to retrieve a role with the given name.
+ * </p>
+ *
+ * @param userAdmin the {@link UserAdmin} service to get users from;
+ * @param name the name of the user to retrieve.
+ * @return a {@link User}, can be <code>null</code> if no such user is
found.
+ */
+ private User getUser(UserAdmin userAdmin, String name) {
+ Role user = null;
+ if (m_nameLookupKey != null) {
+ user = userAdmin.getUser(m_nameLookupKey, name);
+ }
+ if (user == null) {
+ user = userAdmin.getRole(name);
+ }
+ return (user instanceof User) ? (User) user : null;
+ }
+
+ /**
* Validates the certificate chain whether all certificates are valid and
not expired.
*
* @param certificateChain the chain of certificates to validate, cannot
be <code>null</code>.
@@ -189,7 +230,9 @@ public class ClientCertAuthenticationPro
// Bogus certificate given...
return null;
}
- cert.checkValidity();
+ if (m_verifyCertValidity) {
+ cert.checkValidity();
+ }
}
}
catch (CertificateExpiredException e) {
Modified:
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessorTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessorTest.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessorTest.java
(original)
+++
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/ClientCertAuthenticationProcessorTest.java
Tue May 1 10:35:05 2012
@@ -20,8 +20,9 @@ package org.apache.ace.authenticationpro
import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.ATTRIBUTE_CIPHER_SUITE;
import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.ATTRIBUTE_X509_CERTIFICATE;
-import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.PROPERTY_KEY_PUBLICKEY;
-import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.PROPERTY_KEY_USERNAME;
+import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.PROPERTY_USERNAME_LOOKUPKEY;
+import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.PROPERTY_USERNAME_MATCH_POLICY;
+import static
org.apache.ace.authenticationprocessor.clientcert.ClientCertAuthenticationProcessor.PROPERTY_VERIFY_CERT_VALIDITY;
import static org.apache.ace.test.utils.TestUtils.UNIT;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -34,9 +35,9 @@ import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
+import javax.security.auth.x500.X500Principal;
import javax.servlet.http.HttpServletRequest;
-import org.mockito.Mockito;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.log.LogService;
import org.osgi.service.useradmin.User;
@@ -122,7 +123,6 @@ public class ClientCertAuthenticationPro
m_userAdmin = mock(UserAdmin.class);
m_servletRequest = mock(HttpServletRequest.class);
-
when(m_servletRequest.getAuthType()).thenReturn(HttpServletRequest.CLIENT_CERT_AUTH);
when(m_servletRequest.getAttribute(ATTRIBUTE_CIPHER_SUITE)).thenReturn("bogus-cipher-suite");
}
@@ -193,13 +193,11 @@ public class ClientCertAuthenticationPro
@Test(groups = { UNIT })
public void testAuthenticateKnownUserYieldsValidResult() {
X509Certificate[] certChain = createValidCertificateChain("bob");
- PublicKey publicKey = certChain[0].getPublicKey();
when(m_servletRequest.getAttribute(ATTRIBUTE_X509_CERTIFICATE)).thenReturn(certChain);
User user = mock(User.class);
when(user.getName()).thenReturn("bob");
- when(user.hasCredential(eq("publickey"),
eq(publicKey.getEncoded()))).thenReturn(Boolean.TRUE);
when(m_userAdmin.getUser(eq("username"), eq("bob"))).thenReturn(user);
@@ -210,6 +208,37 @@ public class ClientCertAuthenticationPro
}
/**
+ * Tests that authenticating a known user with a valid certificate chain
will not yield null.
+ */
+ @Test(groups = { UNIT })
+ public void
testAuthenticateKnownUserWithValidCertificateChainYieldsValidResult() throws
ConfigurationException {
+ ClientCertAuthenticationProcessor processor =
createAuthorizationProcessor();
+
+ final String lookupKey = "anyKey";
+ final String matchPolicy = "dn";
+
+ Properties props = new Properties();
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, lookupKey);
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, matchPolicy);
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
+ processor.updated(props);
+
+ X509Certificate[] certChain =
createValidCertificateChainWithDN("cn=Alice,dc=acme,dc=corp",
"cn=Fido,ou=dev,dc=acme,dc=corp", "cn=Bob,ou=dev,dc=acme,dc=corp");
+
+
when(m_servletRequest.getAttribute(ATTRIBUTE_X509_CERTIFICATE)).thenReturn(certChain);
+
+ User user = mock(User.class);
+ when(user.getName()).thenReturn("bob");
+
+ when(m_userAdmin.getUser(eq(lookupKey),
eq("CN=Bob,OU=dev,DC=acme,DC=corp"))).thenReturn(user);
+
+ User result = processor.authenticate(m_userAdmin, m_servletRequest);
+ assert result != null : "Expected a valid user to be returned!";
+
+ assert "bob".equals(user.getName()) : "Expected bob to be returned as
user!";
+ }
+
+ /**
* Tests that a missing cipher suite header will the authenticate method
to yield null.
*/
@Test(groups = { UNIT })
@@ -245,7 +274,9 @@ public class ClientCertAuthenticationPro
*/
@Test(groups = { UNIT })
public void testCanHandleDoesAcceptServletRequest() {
- assert
createAuthorizationProcessor().canHandle(mock(HttpServletRequest.class));
+
when(m_servletRequest.getAttribute(ATTRIBUTE_X509_CERTIFICATE)).thenReturn(createValidCertificateChain("alice"));
+
+ assert createAuthorizationProcessor().canHandle(m_servletRequest);
}
/**
@@ -277,31 +308,27 @@ public class ClientCertAuthenticationPro
*/
@Test(groups = { UNIT })
public void testUpdatedDoesAcceptCorrectProperties() throws
ConfigurationException {
- final String keyUsername = "foo";
- final String keyPublicKey = "bar";
-
- Mockito.reset(m_userAdmin, m_servletRequest);
+ final String lookupKey = "anyKey";
+ final String matchPolicy = "cn";
Properties props = new Properties();
- props.put(PROPERTY_KEY_USERNAME, keyUsername);
- props.put(PROPERTY_KEY_PUBLICKEY, keyPublicKey);
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, lookupKey);
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, matchPolicy);
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
ClientCertAuthenticationProcessor processor =
createAuthorizationProcessor();
processor.updated(props);
X509Certificate[] certificateChain =
createValidCertificateChain("alice");
- PublicKey publickey = certificateChain[0].getPublicKey();
// Test whether we can use the new properties...
when(m_servletRequest.getAttribute(ATTRIBUTE_X509_CERTIFICATE)).thenReturn(certificateChain);
-
when(m_servletRequest.getAttribute(ATTRIBUTE_CIPHER_SUITE)).thenReturn("bogus-cipher-suite");
User user = mock(User.class);
when(user.getName()).thenReturn("alice");
- when(user.hasCredential(eq(keyPublicKey),
eq(publickey.getEncoded()))).thenReturn(Boolean.TRUE);
- when(m_userAdmin.getUser(eq(keyUsername),
eq("alice"))).thenReturn(user);
+ when(m_userAdmin.getUser(eq(lookupKey), eq("alice"))).thenReturn(user);
User result = processor.authenticate(m_userAdmin, m_servletRequest);
assert result != null : "Expected a valid user to be returned!";
@@ -310,47 +337,76 @@ public class ClientCertAuthenticationPro
}
/**
- * Tests that updated throws an exception for missing "key.password"
property.
+ * Tests that updated throws an exception for missing "username match
policy" property.
*/
@Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
- public void testUpdatedDoesNotAcceptEmptyKeyPassword() throws
ConfigurationException {
+ public void testUpdatedDoesNotAcceptEmptyMatchPolicy() throws
ConfigurationException {
Properties props = new Properties();
- props.put(PROPERTY_KEY_USERNAME, "foo");
- props.put(PROPERTY_KEY_PUBLICKEY, "");
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, "foo");
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, "");
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
createAuthorizationProcessor().updated(props);
}
/**
- * Tests that updated throws an exception for missing "key.username"
property.
+ * Tests that updated throws an exception for missing "username lookup
key" property.
*/
@Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
- public void testUpdatedDoesNotAcceptEmptyKeyUsername() throws
ConfigurationException {
+ public void testUpdatedDoesNotAcceptEmptyLookupKey() throws
ConfigurationException {
Properties props = new Properties();
- props.put(PROPERTY_KEY_USERNAME, "");
- props.put(PROPERTY_KEY_PUBLICKEY, "foo");
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, "");
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, "foo");
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
createAuthorizationProcessor().updated(props);
}
/**
- * Tests that updated throws an exception for missing "key.password"
property.
+ * Tests that updated throws an exception for missing "verify cert
validity" property.
*/
@Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
- public void testUpdatedDoesNotAcceptMissingKeyPassword() throws
ConfigurationException {
+ public void testUpdatedDoesNotAcceptEmptyVerifyCertValidity() throws
ConfigurationException {
Properties props = new Properties();
- props.put(PROPERTY_KEY_USERNAME, "foo");
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, "foo");
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, "bar");
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "");
createAuthorizationProcessor().updated(props);
}
/**
- * Tests that updated throws an exception for missing "key.username"
property.
+ * Tests that updated throws an exception for missing "username match
policy" property.
*/
@Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
- public void testUpdatedDoesNotAcceptMissingKeyUsername() throws
ConfigurationException {
+ public void testUpdatedDoesNotAcceptMissingMatchPolicy() throws
ConfigurationException {
Properties props = new Properties();
- props.put(PROPERTY_KEY_PUBLICKEY, "foo");
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, "foo");
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
+
+ createAuthorizationProcessor().updated(props);
+ }
+
+ /**
+ * Tests that updated throws an exception for missing "user name lookup
key" property.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
+ public void testUpdatedDoesNotAcceptMissingUsernameLookupKey() throws
ConfigurationException {
+ Properties props = new Properties();
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, "foo");
+ props.put(PROPERTY_VERIFY_CERT_VALIDITY, "true");
+
+ createAuthorizationProcessor().updated(props);
+ }
+
+ /**
+ * Tests that updated throws an exception for missing "verify cert
validity" property.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
+ public void testUpdatedDoesNotAcceptMissingVerifyCertValidity() throws
ConfigurationException {
+ Properties props = new Properties();
+ props.put(PROPERTY_USERNAME_LOOKUPKEY, "foo");
+ props.put(PROPERTY_USERNAME_MATCH_POLICY, "foo");
createAuthorizationProcessor().updated(props);
}
@@ -378,6 +434,33 @@ public class ClientCertAuthenticationPro
}
/**
+ * Creates a new (valid) chain with certificate(s) valid from yesterday
until tomorrow.
+ *
+ * @param dns the distinguished names of the certificates in the returned
chain.
+ * @return a new chain with {@link X509Certificate}s, never
<code>null</code>.
+ */
+ private X509Certificate[] createValidCertificateChainWithDN(String... dns)
{
+ X509Certificate[] result = new X509Certificate[dns.length];
+
+ X500Principal signerDN = m_keystore.getCA_DN();
+ KeyPair signerKeyPair = m_keystore.getCA_KeyPair();
+
+ for (int i = 0; i < result.length; i++) {
+ KeyPair certKeyPair = m_keystore.generateKeyPair();
+
+ String alias = String.format("alias%d", i);
+ String dn = dns[i];
+ int idx = result.length - i - 1;
+
+ result[idx] = m_keystore.createCertificate(signerDN,
signerKeyPair.getPrivate(), alias, dn, yesterday(), tomorrow(),
certKeyPair.getPublic());
+
+ signerDN = result[idx].getSubjectX500Principal();
+ signerKeyPair = certKeyPair;
+ }
+ return result;
+ }
+
+ /**
* Creates a new (valid) certificate valid from yesterday until tomorrow.
*
* @param name the (common) name of the certificate;
Modified:
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/MemoryKeyStore.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/MemoryKeyStore.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/MemoryKeyStore.java
(original)
+++
ace/trunk/ace-authenticationprocessor-clientcert/src/test/java/org/apache/ace/authenticationprocessor/clientcert/MemoryKeyStore.java
Tue May 1 10:35:05 2012
@@ -22,6 +22,7 @@ package org.apache.ace.authenticationpro
import java.math.BigInteger;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.Date;
@@ -34,7 +35,7 @@ import org.bouncycastle.x509.X509V1Certi
* Provides a memory-only certificate keystore.
*/
final class MemoryKeyStore {
- private static final String SIGNATURE_ALGORITHM = "SHA1withRSA"; //
MD5withRSA
+ private static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
private final X509V1CertificateGenerator m_certGen = new
X509V1CertificateGenerator();
private final KeyPair m_caKey;
@@ -59,13 +60,27 @@ final class MemoryKeyStore {
throw new RuntimeException(e);
}
}
+
+ /**
+ * @return the {@link KeyPair} of the CA, never <code>null</code>.
+ */
+ public KeyPair getCA_KeyPair() {
+ return m_caKey;
+ }
+
+ /**
+ * @return
+ */
+ public X500Principal getCA_DN() {
+ return m_rootCert.getIssuerX500Principal();
+ }
/**
- * Generates a new 512-bit keypair.
+ * Generates a new 1024-bit keypair.
*
* @return a new {@link KeyPair}, never <code>null</code>.
*/
- public final KeyPair generateKeyPair() {
+ public KeyPair generateKeyPair() {
try {
return m_generator.generateKeyPair();
}
@@ -78,19 +93,26 @@ final class MemoryKeyStore {
* @throws IllegalStateException if an internal exception occurs.
* @throws IllegalArgumentException if the alias already exists.
*/
- public X509Certificate createCertificate(String alias, String name, Date
before, Date after, PublicKey key)
- throws IllegalStateException, IllegalArgumentException {
+ public X509Certificate createCertificate(String alias, String name, Date
before, Date after, PublicKey key) throws IllegalArgumentException {
+ return createCertificate(getCA_DN(), m_caKey.getPrivate(), alias,
name, before, after, key);
+ }
+
+ /**
+ * @throws IllegalStateException if an internal exception occurs.
+ * @throws IllegalArgumentException if the alias already exists.
+ */
+ public X509Certificate createCertificate(X500Principal issuerDN,
PrivateKey issuerKey, String alias, String name, Date notBefore, Date notAfter,
PublicKey key) throws IllegalArgumentException {
try {
m_certGen.reset();
m_certGen.setSerialNumber(BigInteger.valueOf(++m_serial));
- m_certGen.setIssuerDN(m_rootCert.getIssuerX500Principal());
- m_certGen.setNotBefore(before);
- m_certGen.setNotAfter(after);
+ m_certGen.setIssuerDN(issuerDN);
+ m_certGen.setNotBefore(notBefore);
+ m_certGen.setNotAfter(notAfter);
m_certGen.setSubjectDN(new X500Principal(name));
m_certGen.setPublicKey(key);
m_certGen.setSignatureAlgorithm(SIGNATURE_ALGORITHM);
- X509Certificate cert = m_certGen.generate(m_caKey.getPrivate());
+ X509Certificate cert = m_certGen.generate(issuerKey);
return cert;
}
Modified: ace/trunk/ace-connectionfactory/pom.xml
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/pom.xml?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
--- ace/trunk/ace-connectionfactory/pom.xml (original)
+++ ace/trunk/ace-connectionfactory/pom.xml Tue May 1 10:35:05 2012
@@ -43,6 +43,7 @@
<properties>
<import.package>
!org.junit,
+ javax.net.ssl,
org.apache.ace.connectionfactory;version=${project.version},
org.osgi.framework,
org.osgi.service.cm,
Modified:
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
(original)
+++
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImpl.java
Tue May 1 10:35:05 2012
@@ -28,6 +28,9 @@ import java.util.Dictionary;
import java.util.HashMap;
import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
import
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory.MissingValueException;
@@ -37,7 +40,7 @@ import org.osgi.service.cm.ManagedServic
import org.osgi.service.useradmin.User;
/**
- * Provides a default implementation for {@link ConnectionFactory} based on
the standard <code>java.net</code>
+ * Provides a default implementation for {@link ConnectionFactory} based on
the standard <code>java.net</code>
* implementation of {@link URLConnection}.
*/
public class ConnectionFactoryImpl implements ConnectionFactory,
ManagedServiceFactory {
@@ -45,9 +48,9 @@ public class ConnectionFactoryImpl imple
public static final String FACTORY_PID =
"org.apache.ace.connectionfactory";
private static final String HTTP_HEADER_AUTHORIZATION = "Authorization";
-
+
private final Map<String /* config PID */, UrlCredentials>
m_credentialMapping;
-
+
/**
* Creates a new {@link ConnectionFactoryImpl}.
*/
@@ -122,7 +125,7 @@ public class ConnectionFactoryImpl imple
try {
creds = UrlCredentialsFactory.getCredentials(properties);
-
+
synchronized (m_credentialMapping) {
m_credentialMapping.put(pid, creds);
}
@@ -131,12 +134,12 @@ public class ConnectionFactoryImpl imple
throw new ConfigurationException(e.getProperty(), e.getMessage());
}
}
-
+
/**
* Returns the credentials to access the given URL.
*
* @param url the URL to find the credentials for, cannot be
<code>null</code>.
- * @return a {@link UrlCredentials} instance for the given URL, or
<code>null</code>
+ * @return a {@link UrlCredentials} instance for the given URL, or
<code>null</code>
* if none were found, or if none were necessary.
*/
final UrlCredentials getCredentials(URL url) {
@@ -150,20 +153,19 @@ public class ConnectionFactoryImpl imple
return c;
}
}
-
+
return null;
}
/**
* Returns the authorization header for HTTP Basic Authentication.
*
- * @param creds the credentials to supply.
+ * @param values the credential values to supply, cannot be
<code>null</code> and should be an array of two elements.
* @return a string that denotes the basic authentication header ("Basic "
+ encoded credentials), never <code>null</code>.
*/
- final String getBasicAuthCredentials(UrlCredentials creds) {
- final Object[] values = creds.getCredentials();
- if (values.length < 2) {
- throw new IllegalArgumentException("Insufficient credentials
passed! Expected 2 values, got " + values.length + " values.");
+ final String getBasicAuthCredentials(Object[] values) {
+ if ((values == null) || values.length < 2) {
+ throw new IllegalArgumentException("Insufficient credentials
passed: expected 2 values!");
}
StringBuilder sb = new StringBuilder();
@@ -185,19 +187,45 @@ public class ConnectionFactoryImpl imple
}
/**
+ * Applies basic authentication to the given connection, if it is a {@link
HttpURLConnection}.
+ *
+ * @param conn the connection to apply basic authentication to;
+ * @param values the credentials to apply.
+ */
+ private void applyBasicAuthentication(URLConnection conn, Object[] values)
{
+ if (conn instanceof HttpURLConnection) {
+ conn.setRequestProperty(HTTP_HEADER_AUTHORIZATION,
getBasicAuthCredentials(values));
+ }
+ }
+
+ /**
+ * Applies the use of client certificates to the given connection, if it a
{@link HttpsURLConnection}.
+ *
+ * @param conn the connection to apply client certs to;
+ * @param values the credentials to apply.
+ */
+ private void applyClientCertificate(URLConnection conn, Object[] values) {
+ if (conn instanceof HttpsURLConnection) {
+ ((HttpsURLConnection) conn).setSSLSocketFactory(((SSLContext)
values[0]).getSocketFactory());
+ }
+ }
+
+ /**
* Supplies the actual credentials to the given {@link URLConnection}.
*
* @param conn the connection to supply the credentials to, cannot be
<code>null</code>;
- * @param creds the credentials to supply, cannot be <code>null</code>.
+ * @param urlCreds the URL credentials to supply, cannot be
<code>null</code>.
* @throws IOException in case of I/O problems.
*/
- private void supplyCredentials(URLConnection conn, UrlCredentials creds)
throws IOException {
- final AuthType type = creds.getType();
-
+ private void supplyCredentials(URLConnection conn, UrlCredentials
urlCreds) throws IOException {
+ final AuthType type = urlCreds.getType();
+ final Object[] creds = urlCreds.getCredentials();
+
if (AuthType.BASIC.equals(type)) {
- if (conn instanceof HttpURLConnection) {
- conn.setRequestProperty(HTTP_HEADER_AUTHORIZATION,
getBasicAuthCredentials(creds));
- }
+ applyBasicAuthentication(conn, creds);
+ }
+ else if (AuthType.CLIENT_CERT.equals(type)) {
+ applyClientCertificate(conn, creds);
}
else if (!AuthType.NONE.equals(type)) {
throw new IllegalArgumentException("Unknown authentication type: "
+ type);
Modified:
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
(original)
+++
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentials.java
Tue May 1 10:35:05 2012
@@ -31,7 +31,9 @@ final class UrlCredentials {
/** Indicates no authentication. */
NONE,
/** Indicates basic HTTP authentication. */
- BASIC;
+ BASIC,
+ /** Indicates the use of client certificates. */
+ CLIENT_CERT;
}
private final AuthType m_type;
Modified:
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
(original)
+++
ace/trunk/ace-connectionfactory/src/main/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactory.java
Tue May 1 10:35:05 2012
@@ -19,10 +19,23 @@
package org.apache.ace.connectionfactory.impl;
+import java.io.Closeable;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.SecureRandom;
import java.util.Dictionary;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+
import org.apache.ace.connectionfactory.impl.UrlCredentials.AuthType;
/**
@@ -63,6 +76,10 @@ final class UrlCredentialsFactory {
public static final String KEY_AUTH_TYPE = "authentication.type";
public static final String KEY_AUTH_USER_NAME = "authentication.user.name";
public static final String KEY_AUTH_USER_PASSWORD =
"authentication.user.password";
+ public static final String KEY_AUTH_KEYSTORE_FILE =
"authentication.keystore.file";
+ public static final String KEY_AUTH_KEYSTORE_PASS =
"authentication.keystore.storepass";
+ public static final String KEY_AUTH_TRUSTSTORE_FILE =
"authentication.truststore.file";
+ public static final String KEY_AUTH_TRUSTSTORE_PASS =
"authentication.truststore.storepass";
/**
* Not used.
@@ -130,6 +147,47 @@ final class UrlCredentialsFactory {
}
creds = new Object[] { userName, password };
+ } else if (AuthType.CLIENT_CERT.equals(type)) {
+ String keystoreFile = getStringProperty(props,
prefix.concat(KEY_AUTH_KEYSTORE_FILE));
+ String keystorePass = getStringProperty(props,
prefix.concat(KEY_AUTH_KEYSTORE_PASS));
+ if ((keystoreFile != null) && (keystorePass == null)) {
+ throw new
MissingValueException(prefix.concat(KEY_AUTH_KEYSTORE_PASS));
+ }
+ if ((keystoreFile == null) && (keystorePass != null)) {
+ throw new
MissingValueException(prefix.concat(KEY_AUTH_KEYSTORE_FILE));
+ }
+
+ String truststoreFile = getStringProperty(props,
prefix.concat(KEY_AUTH_TRUSTSTORE_FILE));
+ String truststorePass = getStringProperty(props,
prefix.concat(KEY_AUTH_TRUSTSTORE_PASS));
+ if ((truststoreFile != null) && (truststorePass == null)) {
+ throw new
MissingValueException(prefix.concat(KEY_AUTH_TRUSTSTORE_PASS));
+ }
+ if ((truststoreFile == null) && (truststorePass != null)) {
+ throw new
MissingValueException(prefix.concat(KEY_AUTH_TRUSTSTORE_FILE));
+ }
+
+ if ((keystoreFile == null) && (truststoreFile == null)) {
+ try {
+ // No configuration given; use the system-wide defaults...
+ creds = new Object[] { SSLContext.getDefault() };
+ }
+ catch (Exception e) {
+ throw new IllegalArgumentException("Failed to obtain SSL
context!", e);
+ }
+ } else {
+ try {
+ KeyManager[] keyManagers =
getKeyManagerFactory(keystoreFile, keystorePass);
+ TrustManager[] trustManagers =
getTrustManagerFactory(truststoreFile, truststorePass);
+
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(keyManagers, trustManagers, new
SecureRandom());
+
+ creds = new Object[] { context };
+ }
+ catch (Exception e) {
+ throw new IllegalArgumentException("Failed to load
keystore!", e);
+ }
+ }
} else {
throw new IllegalArgumentException("Invalid/unhandled
authentication type: " + authType);
}
@@ -146,9 +204,78 @@ final class UrlCredentialsFactory {
}
return null;
}
-
+
private static String getStringProperty(Dictionary dict, String key,
String defaultValue) {
String value = getStringProperty(dict, key);
return (value == null) ? defaultValue : value;
}
+
+ /**
+ * @param keystoreFile
+ * @param storePass
+ * @return
+ * @throws IOException
+ * @throws GeneralSecurityException
+ */
+ private static KeyManager[] getKeyManagerFactory(String keystoreFile,
String storePass) throws IOException, GeneralSecurityException {
+ if (keystoreFile == null) {
+ return null;
+ }
+
+ InputStream keyInput = null;
+ try {
+ KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ KeyStore keyStore =
KeyStore.getInstance(KeyStore.getDefaultType());
+
+ keyInput = new FileInputStream(keystoreFile);
+
+ keyStore.load(keyInput, storePass.toCharArray());
+
+ keyManagerFactory.init(keyStore, storePass.toCharArray());
+ return keyManagerFactory.getKeyManagers();
+ }
+ finally {
+ closeSafely(keyInput);
+ }
+ }
+
+ /**
+ * @param truststoreFile
+ * @param storePass
+ * @return
+ * @throws IOException
+ * @throws GeneralSecurityException
+ */
+ private static TrustManager[] getTrustManagerFactory(String
truststoreFile, String storePass) throws IOException, GeneralSecurityException {
+ if (truststoreFile == null) {
+ return null;
+ }
+
+ InputStream trustInput = null;
+ try {
+ TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ KeyStore trustStore =
KeyStore.getInstance(KeyStore.getDefaultType());
+
+ trustInput = new FileInputStream(truststoreFile);
+
+ trustStore.load(trustInput, storePass.toCharArray());
+
+ trustManagerFactory.init(trustStore);
+ return trustManagerFactory.getTrustManagers();
+ }
+ finally {
+ closeSafely(trustInput);
+ }
+ }
+
+ private static void closeSafely(Closeable resource) {
+ try {
+ if (resource != null) {
+ resource.close();
+ }
+ }
+ catch (IOException e) {
+ // Ignore; nothing we can/will do...
+ }
+ }
}
Modified:
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
(original)
+++
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/ConnectionFactoryImplTest.java
Tue May 1 10:35:05 2012
@@ -99,11 +99,11 @@ public class ConnectionFactoryImplTest {
Properties props = createBasicAuthConfig(TEST_URL.toExternalForm());
connFactory.updated("pid1", props);
-
+
UrlCredentials credentials = connFactory.getCredentials(TEST_URL);
assert credentials != null : "Expected valid credentials to be found!";
- String header = new
ConnectionFactoryImpl().getBasicAuthCredentials(credentials);
+ String header = new
ConnectionFactoryImpl().getBasicAuthCredentials(credentials.getCredentials());
assert header != null : "Expected valid HTTP header to be returned!";
assert header.equals(header.trim()) : "Expected HTTP header not to
contain any leading/trailing whitespace!";
assert "Basic Zm9vOmJhcg==".equals(header) : "Expected HTTP header to
be constant!";
Modified:
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
URL:
http://svn.apache.org/viewvc/ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java?rev=1332609&r1=1332608&r2=1332609&view=diff
==============================================================================
---
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
(original)
+++
ace/trunk/ace-connectionfactory/src/test/java/org/apache/ace/connectionfactory/impl/UrlCredentialsFactoryTest.java
Tue May 1 10:35:05 2012
@@ -48,6 +48,87 @@ public class UrlCredentialsFactoryTest {
* Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
*/
@Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+ public void
testGetCredentialsWithDictionaryClientCertTypeMissingKeystorePasswordFail() {
+ Properties props = new Properties();
+ props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "bar");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "qux");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "foo");
+
+ UrlCredentialsFactory.getCredentials(props);
+ }
+
+ /**
+ * Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+ public void
testGetCredentialsWithDictionaryClientCertTypeMissingKeystoreFileFail() {
+ Properties props = new Properties();
+ props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "bar");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "qux");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "foo");
+
+ UrlCredentialsFactory.getCredentials(props);
+ }
+
+ /**
+ * Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+ */
+ @Test(groups = { UNIT })
+ public void testGetCredentialsWithDictionaryClientCertTypeOk() {
+ Properties props = new Properties();
+ props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "foo");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "bar");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "qux");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "quu");
+
+ try {
+ UrlCredentialsFactory.getCredentials(props);
+ }
+ catch (IllegalArgumentException e) {
+ // Ok; expected as the implementation tries to open the files
"foo" and "qux"...
+ }
+ }
+
+ /**
+ * Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+ public void
testGetCredentialsWithDictionaryClientCertTypeMissingTruststorePasswordFail() {
+ Properties props = new Properties();
+ props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "bar");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "qux");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_FILE, "foo");
+
+ UrlCredentialsFactory.getCredentials(props);
+ }
+
+ /**
+ * Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
+ public void
testGetCredentialsWithDictionaryClientCertTypeMissingTruststoreFileFail() {
+ Properties props = new Properties();
+ props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TYPE, "client_cert");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_FILE, "bar");
+ props.put(UrlCredentialsFactory.KEY_AUTH_KEYSTORE_PASS, "qux");
+ props.put(UrlCredentialsFactory.KEY_AUTH_TRUSTSTORE_PASS, "foo");
+
+ UrlCredentialsFactory.getCredentials(props);
+ }
+
+ /**
+ * Test method for {@link
org.apache.ace.connectionfactory.impl.UrlCredentialsFactory#getCredentials(java.util.Dictionary)}.
+ */
+ @Test(groups = { UNIT }, expectedExceptions = MissingValueException.class)
public void testGetCredentialsWithDictionaryBasicTypeMissingUserNameFail()
{
Properties props = new Properties();
props.put(UrlCredentialsFactory.KEY_AUTH_BASE_URL,
"http://localhost:8080/");