[java-opensaml] 10/16: HttpClientSecurity -Configuration, -Resolver and tests.

Brent Putman putmanb at georgetown.edu
Sun Dec 17 00:08:20 EST 2017


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch master
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=123a057449368c7bb36cf369b17afb65f0fd54b8

commit 123a057449368c7bb36cf369b17afb65f0fd54b8
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Fri Dec 15 16:49:15 2017 -0500

    HttpClientSecurity -Configuration, -Resolver and tests.
---
 .../HttpClientSecurityConfiguration.java           |  95 +++++++
 .../HttpClientSecurityConfigurationCriterion.java  | 113 +++++++++
 .../HttpClientSecurityParametersResolver.java      |  28 +++
 .../impl/BasicHttpClientSecurityConfiguration.java | 272 +++++++++++++++++++++
 .../BasicHttpClientSecurityParametersResolver.java | 158 ++++++++++++
 .../BasicHttpClientSecurityConfigurationTest.java  | 103 ++++++++
 ...icHttpClientSecurityParametersResolverTest.java | 233 ++++++++++++++++++
 .../src/test/resources/logback-test.xml            |   4 +
 8 files changed, 1006 insertions(+)

diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfiguration.java b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfiguration.java
new file mode 100644
index 0000000..2596eae
--- /dev/null
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfiguration.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+/**
+ * The security configuration information to use when performing HTTP client requests.
+ */
+public interface HttpClientSecurityConfiguration {
+    
+    /**
+     * Get an instance of {@link CredentialsProvider} used for authentication by the HttpClient instance.
+     * 
+     * @return the credentials provider, or null
+     */
+    @Nullable public CredentialsProvider getCredentialsProvider();
+    
+    /**
+     * Get an instance of {@link AuthCache} used for authentication by the HttpClient instance.
+     * 
+     * @return the cache, or null
+     * 
+     * @since 3.4.0
+     */
+    @Nullable public AuthCache getAuthCache();
+    
+    /**
+     * Sets the optional trust engine used in evaluating server TLS credentials.
+     * 
+     * @return the trust engine instance to use, or null
+     */
+    @Nullable public TrustEngine<? super X509Credential> getTLSTrustEngine();
+    
+    /**
+     * Get the optional criteria set used in evaluating server TLS credentials.
+     * 
+     * @return the criteria set instance to use
+     */
+    @Nullable public CriteriaSet getTLSCriteriaSet();
+    
+    /**
+     * Get the optional list of TLS protocols. 
+     * 
+     * @return the TLS protocols, or null
+     */
+    @Nullable public List<String> getTLSProtocols();
+    
+    /**
+     * Get the optional list of TLS cipher suites.
+     * 
+     * @return the list of TLS cipher suites, or null
+     */
+    @Nullable public List<String> getTLSCipherSuites();
+    
+    /**
+     * Get the optional hostname verifier.
+     * 
+     * @return the hostname verifier, or null
+     */
+    @Nullable public X509HostnameVerifier getHostnameVerifier();
+    
+    /**
+     * Get the optional client TLS credential.
+     * 
+     * @return the client TLS credential, or null
+     */
+    @Nullable public X509Credential getClientTLSCredential();
+
+}
diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfigurationCriterion.java b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfigurationCriterion.java
new file mode 100644
index 0000000..070bf01
--- /dev/null
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityConfigurationCriterion.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotLive;
+import net.shibboleth.utilities.java.support.annotation.constraint.Unmodifiable;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.resolver.Criterion;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Criterion which holds one or more instances of {@link HttpClientSecurityConfiguration}.
+ */
+public class HttpClientSecurityConfigurationCriterion implements Criterion {
+    
+    /** The list of configuration instances. */
+    @Nonnull @NonnullElements private List<HttpClientSecurityConfiguration> configs;
+    
+    /**
+     * Constructor.
+     *
+     * @param configurations list of configuration instances
+     */
+    public HttpClientSecurityConfigurationCriterion(@Nonnull @NonnullElements @NotEmpty final
+            List<HttpClientSecurityConfiguration> configurations) {
+        Constraint.isNotNull(configurations, "List of configurations cannot be null");
+        configs = new ArrayList<>(Collections2.filter(configurations, Predicates.notNull()));
+        Constraint.isGreaterThanOrEqual(1, configs.size(), "At least one configuration is required");
+        
+    }
+    
+    /**
+     * Constructor.
+     *
+     * @param configurations varargs array of configuration instances
+     */
+    public HttpClientSecurityConfigurationCriterion(@Nonnull @NonnullElements  @NotEmpty final
+            HttpClientSecurityConfiguration... configurations) {
+        Constraint.isNotNull(configurations, "List of configurations cannot be null");
+        configs = new ArrayList<>(Collections2.filter(Arrays.asList(configurations), Predicates.notNull()));
+        Constraint.isGreaterThanOrEqual(1, configs.size(), "At least one configuration is required");
+    }
+    
+    /**
+     * Get the list of configuration instances.
+     * @return the list of configuration instances
+     */
+    @Nonnull @NonnullElements @NotLive @Unmodifiable @NotEmpty
+    public List<HttpClientSecurityConfiguration> getConfigurations() {
+        return ImmutableList.copyOf(configs);
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("HttpClientSecurityConfigurationCriterion [configs=");
+        builder.append(configs);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int hashCode() {
+        return configs.hashCode();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+
+        if (obj == null) {
+            return false;
+        }
+
+        if (obj instanceof HttpClientSecurityConfigurationCriterion) {
+            return configs.equals(((HttpClientSecurityConfigurationCriterion) obj).getConfigurations());
+        }
+
+        return false;
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParametersResolver.java b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParametersResolver.java
new file mode 100644
index 0000000..be3d72b
--- /dev/null
+++ b/opensaml-security-api/src/main/java/org/opensaml/security/httpclient/HttpClientSecurityParametersResolver.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient;
+
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.Resolver;
+
+/**
+ * An interface for components which resolve {@link HttpClientSecurityParameters} based on a {@link CriteriaSet}.
+ */
+public interface HttpClientSecurityParametersResolver extends Resolver<HttpClientSecurityParameters, CriteriaSet> {
+
+}
diff --git a/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfiguration.java b/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfiguration.java
new file mode 100644
index 0000000..49b3186
--- /dev/null
+++ b/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfiguration.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.AuthCache;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.opensaml.security.httpclient.HttpClientSecurityConfiguration;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+/**
+ * Basic implementation of {@link HttpClientSecurityConfiguration}.
+ */
+public class BasicHttpClientSecurityConfiguration implements HttpClientSecurityConfiguration {
+    
+    /** HttpClient credentials provider. */
+    @Nullable private CredentialsProvider credentialsProvider;
+    
+    /** HttpClient {@link AuthCache} to allow pre-emptive authentication. */
+    @Nullable private AuthCache authCache;
+    
+    /** Optional trust engine used in evaluating server TLS credentials. */
+    @Nullable private TrustEngine<? super X509Credential> tlsTrustEngine;
+    
+    /** Optional criteria set used in evaluating server TLS credentials. */
+    @Nullable private CriteriaSet tlsCriteriaSet;
+    
+    /** TLS Protocols. */
+    @Nullable private List<String> tlsProtocols;
+    
+    /** TLS cipher suites. */
+    @Nullable private List<String> tlsCipherSuites;
+    
+    /** The hostname verifier. */
+    @Nullable private X509HostnameVerifier hostnameVerifier;
+    
+    /** The X509 credential used for client TLS. */
+    @Nullable private X509Credential clientTLSCredential;
+    
+    /**
+     * Get an instance of {@link CredentialsProvider} used for authentication by the HttpClient instance.
+     * 
+     * @return the credentials provider, or null
+     */
+    @Nullable public CredentialsProvider getCredentialsProvider() {
+        return credentialsProvider;
+    }
+    
+    /**
+     * Set an instance of {@link CredentialsProvider} used for authentication by the HttpClient instance.
+     * 
+     * @param provider the credentials provider
+     */
+    public void setCredentialsProvider(@Nullable final CredentialsProvider provider) {
+        credentialsProvider = provider;
+    }
+    
+    /**
+     * Get an instance of {@link AuthCache} used for authentication by the HttpClient instance.
+     * 
+     * @return the cache, or null
+     * 
+     * @since 3.4.0
+     */
+    @Nullable public AuthCache getAuthCache() {
+        return authCache;
+    }
+    
+    /**
+     * Set an instance of {@link AuthCache} used for authentication by the HttpClient instance.
+     * 
+     * @param cache the auth cache
+     * 
+     * @since 3.4.0
+     */
+    public void setAuthCache(@Nullable final AuthCache cache) {
+        authCache = cache;
+    }
+    
+    
+    /**
+     * A convenience method to set a (single) username and password used for BASIC authentication.
+     * To disable BASIC authentication pass null for the credentials instance.
+     * 
+     * <p>
+     * An {@link AuthScope} will be generated which specifies any host, port, scheme and realm.
+     * </p>
+     * 
+     * <p>To specify multiple usernames and passwords for multiple host, port, scheme, and realm combinations, instead 
+     * provide an instance of {@link CredentialsProvider} via {@link #setCredentialsProvider(CredentialsProvider)}.</p>
+     * 
+     * @param credentials the username and password credentials
+     */
+    public void setBasicCredentials(@Nullable final UsernamePasswordCredentials credentials) {
+        setBasicCredentialsWithScope(credentials, null);
+    }
+    
+    /**
+     * A convenience method to set a (single) username and password used for BASIC authentication.
+     * To disable BASIC authentication pass null for the credentials instance.
+     * 
+     * <p>
+     * If the <code>authScope</code> is null, an {@link AuthScope} will be generated which specifies
+     * any host, port, scheme and realm.
+     * </p>
+     * 
+     * <p>To specify multiple usernames and passwords for multiple host, port, scheme, and realm combinations, instead 
+     * provide an instance of {@link CredentialsProvider} via {@link #setCredentialsProvider(CredentialsProvider)}.</p>
+     * 
+     * @param credentials the username and password credentials
+     * @param scope the HTTP client auth scope with which to scope the credentials, may be null
+     */
+    public void setBasicCredentialsWithScope(@Nullable final UsernamePasswordCredentials credentials,
+            @Nullable final AuthScope scope) {
+
+        if (credentials != null) {
+            AuthScope authScope = scope;
+            if (authScope == null) {
+                authScope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT);
+            }
+            final BasicCredentialsProvider provider = new BasicCredentialsProvider();
+            provider.setCredentials(authScope, credentials);
+            credentialsProvider = provider;
+        } else {
+            credentialsProvider = null;
+        }
+
+    }
+    
+    /**
+     * Sets the optional trust engine used in evaluating server TLS credentials.
+     * 
+     * @return the trust engine instance to use, or null
+     */
+    @Nullable public TrustEngine<? super X509Credential> getTLSTrustEngine() {
+        return tlsTrustEngine;
+    }
+    
+    /**
+     * Sets the optional trust engine used in evaluating server TLS credentials.
+     * 
+     * @param engine the trust engine instance to use
+     */
+    public void setTLSTrustEngine(@Nullable final TrustEngine<? super X509Credential> engine) {
+        tlsTrustEngine = engine;
+    }
+
+    /**
+     * Get the optional criteria set used in evaluating server TLS credentials.
+     * 
+     * @return the criteria set instance to use
+     */
+    @Nullable public CriteriaSet getTLSCriteriaSet() {
+        return tlsCriteriaSet;
+    }
+
+    /**
+     * Set the optional criteria set used in evaluating server TLS credentials.
+     * 
+     * @param criteriaSet the new criteria set instance to use
+     */
+    public void setTLSCriteriaSet(@Nullable final CriteriaSet criteriaSet) {
+        tlsCriteriaSet = criteriaSet;
+    }
+
+    /**
+     * Get the optional list of TLS protocols. 
+     * 
+     * @return the TLS protocols, or null
+     */
+    @Nullable public List<String> getTLSProtocols() {
+        return tlsProtocols;
+    }
+
+    /**
+     * Set the optional list of TLS protocols. 
+     * 
+     * @param protocols the TLS protocols or null
+     */
+    public void setTLSProtocols(@Nullable final Collection<String> protocols) {
+        tlsProtocols = new ArrayList<>(StringSupport.normalizeStringCollection(protocols));
+        if (tlsProtocols.isEmpty()) {
+            tlsProtocols = null;
+        }
+    }
+
+    /**
+     * Get the optional list of TLS cipher suites.
+     * 
+     * @return the list of TLS cipher suites, or null
+     */
+    @Nullable public List<String> getTLSCipherSuites() {
+        return tlsCipherSuites;
+    }
+
+    /**
+     * Set the optional list of TLS cipher suites.
+     * 
+     * @param cipherSuites the TLS cipher suites, or null
+     */
+    public void setTLSCipherSuites(@Nullable final Collection<String> cipherSuites) {
+        tlsCipherSuites = new ArrayList<>(StringSupport.normalizeStringCollection(cipherSuites));
+        if (tlsCipherSuites.isEmpty()) {
+            tlsCipherSuites = null;
+        }
+    }
+
+    /**
+     * Get the optional hostname verifier.
+     * 
+     * @return the hostname verifier, or null
+     */
+    @Nullable public X509HostnameVerifier getHostnameVerifier() {
+        return hostnameVerifier;
+    }
+
+    /**
+     * Set the optional hostname verifier.
+     * 
+     * @param verifier the hostname verifier, or null
+     */
+    public void setHostnameVerifier(@Nullable final X509HostnameVerifier verifier) {
+        hostnameVerifier = verifier;
+    }
+
+    /**
+     * Get the optional client TLS credential.
+     * 
+     * @return the client TLS credential, or null
+     */
+    @Nullable public X509Credential getClientTLSCredential() {
+        return clientTLSCredential;
+    }
+
+    /**
+     * Set the optional client TLS credential.
+     * 
+     * @param credential the client TLS credential, or null
+     */
+    public void setClientTLSCredential(@Nullable final X509Credential credential) {
+        clientTLSCredential = credential;
+    }
+
+}
diff --git a/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolver.java b/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolver.java
new file mode 100644
index 0000000..b77161b
--- /dev/null
+++ b/opensaml-security-impl/src/main/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolver.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient.impl;
+
+import java.security.Key;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.credential.CredentialSupport;
+import org.opensaml.security.httpclient.HttpClientSecurityConfiguration;
+import org.opensaml.security.httpclient.HttpClientSecurityConfigurationCriterion;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.opensaml.security.httpclient.HttpClientSecurityParametersResolver;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.ObjectSupport;
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ * Basic implementation of {@link HttpClientSecurityParametersResolver}.
+ * 
+ * <p>
+ * The following {@link net.shibboleth.utilities.java.support.resolver.Criterion} inputs are supported:
+ * <ul>
+ * <li>{@link HttpClientSecurityConfigurationCriterion} - required</li> 
+ * </ul>
+ * </p>
+ */
+public class BasicHttpClientSecurityParametersResolver implements HttpClientSecurityParametersResolver {
+    
+    /** Logger. */
+    private Logger log = LoggerFactory.getLogger(BasicHttpClientSecurityParametersResolver.class);
+
+    /** {@inheritDoc} */
+    public Iterable<HttpClientSecurityParameters> resolve(@Nonnull final CriteriaSet criteria) 
+            throws ResolverException {
+        
+        final HttpClientSecurityParameters params = resolveSingle(criteria);
+        if (params != null) {
+            return Collections.singletonList(params);
+        } else {
+            return Collections.emptyList();
+        }
+    }
+
+    /** {@inheritDoc} */
+    public HttpClientSecurityParameters resolveSingle(@Nonnull final CriteriaSet criteria) throws ResolverException {
+        Constraint.isNotNull(criteria, "CriteriaSet was null");
+        Constraint.isNotNull(criteria.get(HttpClientSecurityConfigurationCriterion.class), 
+                "Resolver requires an instance of HttpClientSecurityConfigurationCriterion");
+        
+        final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
+        
+        resolveAndPopulateParams(params, criteria);
+        
+        if (validate(params)) {
+            logResult(params);
+            return params;
+        } else {
+            return null;
+        }
+    }
+    
+    /**
+     * Resolve and populate all parametersu.
+     * 
+     * @param params the parameters instance to populate
+     * @param criteria the criteria to process
+     */
+    protected void resolveAndPopulateParams(@Nonnull final HttpClientSecurityParameters params, 
+            @Nonnull final CriteriaSet criteria) {
+        
+        final List<HttpClientSecurityConfiguration> configs = 
+                criteria.get(HttpClientSecurityConfigurationCriterion.class).getConfigurations();
+        
+        for (final HttpClientSecurityConfiguration config : configs) {
+            params.setAuthCache(ObjectSupport.firstNonNull(params.getAuthCache(), 
+                    config.getAuthCache()));
+            params.setClientTLSCredential(ObjectSupport.firstNonNull(params.getClientTLSCredential(), 
+                    config.getClientTLSCredential()));
+            params.setCredentialsProvider(ObjectSupport.firstNonNull(params.getCredentialsProvider(), 
+                    config.getCredentialsProvider()));
+            params.setHostnameVerifier(ObjectSupport.firstNonNull(params.getHostnameVerifier(), 
+                    config.getHostnameVerifier()));
+            params.setTLSCipherSuites(ObjectSupport.firstNonNull(params.getTLSCipherSuites(), 
+                    config.getTLSCipherSuites()));
+            params.setTLSCriteriaSet(ObjectSupport.firstNonNull(params.getTLSCriteriaSet(), 
+                    config.getTLSCriteriaSet()));
+            params.setTLSProtocols(ObjectSupport.firstNonNull(params.getTLSProtocols(), 
+                    config.getTLSProtocols()));
+            params.setTLSTrustEngine(ObjectSupport.<TrustEngine<? super X509Credential>>firstNonNull(
+                    params.getTLSTrustEngine(), config.getTLSTrustEngine()));
+        }
+    }
+
+    /**
+     * Validate that the {@link HttpClientSecurityParameters} instance has all the required properties populated.
+     * 
+     * @param params the parameters instance to evaluate
+     * 
+     * @return true if parameters instance passes validation, false otherwise
+     */
+    protected boolean validate(@Nonnull final HttpClientSecurityParameters params) {
+        // Default impl is no required data.
+        return true;
+    }
+    
+    /**
+     * Log the resolved parameters.
+     * 
+     * @param params the resolved param
+     */
+    protected void logResult(@Nonnull final HttpClientSecurityParameters params) {
+        if (log.isDebugEnabled()) {
+            log.debug("Resolved HttpClientSecurityParameters:");
+            
+            final Key clientTLSKey = CredentialSupport.extractSigningKey(params.getClientTLSCredential());
+            if (clientTLSKey != null) {
+                log.debug("\tClient TLS credential with key algorithm: {}", clientTLSKey.getAlgorithm());
+            } else {
+                log.debug("\tClient TLS credential: null"); 
+            }
+            
+            log.debug("\tHostnameVerifier: {}", params.getHostnameVerifier() != null ? "present" : "null");
+            log.debug("\tTLS TrustEngine: {}", params.getTLSTrustEngine() != null ? "present" : "null");
+            log.debug("\tTLS CriteriaSet: {}", params.getTLSCriteriaSet() != null ? "present" : "null");
+            
+            log.debug("\tTLS cipher suites: {}", params.getTLSCipherSuites()); 
+            log.debug("\tTLS protocols: {}", params.getTLSProtocols()); 
+            
+            log.debug("\tAuthCache: {}", params.getAuthCache() != null ? "present" : "null");
+            log.debug("\tCredentialsProvider: {}", params.getCredentialsProvider() != null ? "present" : "null");
+        }
+    }
+
+}
diff --git a/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfigurationTest.java b/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfigurationTest.java
new file mode 100644
index 0000000..874766a
--- /dev/null
+++ b/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityConfigurationTest.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient.impl;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.security.cert.CertificateException;
+
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.credential.CredentialSupport;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.security.x509.X509Support;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+
+/**
+ *
+ */
+public class BasicHttpClientSecurityConfigurationTest {
+    
+    private X509Credential x509Credential;
+    
+    @BeforeMethod
+    protected void setUp() throws CertificateException, URISyntaxException {
+        x509Credential = CredentialSupport.getSimpleCredential(
+                X509Support.decodeCertificate(new File(this.getClass().getResource("/data/certificate.pem").toURI())), null);
+    }
+    
+    @Test
+    public void testBasic() {
+        BasicHttpClientSecurityConfiguration config = new BasicHttpClientSecurityConfiguration();
+        config.setAuthCache(new BasicAuthCache());
+        config.setClientTLSCredential(x509Credential);
+        config.setCredentialsProvider(new BasicCredentialsProvider());
+        config.setHostnameVerifier(new StrictHostnameVerifier());
+        config.setTLSCipherSuites(Lists.newArrayList("test"));
+        config.setTLSCriteriaSet(new CriteriaSet());
+        config.setTLSProtocols(Lists.newArrayList("test"));
+        config.setTLSTrustEngine(new MockTrustEngine());
+        
+        Assert.assertNotNull(config.getAuthCache());
+        Assert.assertNotNull(config.getClientTLSCredential());
+        Assert.assertNotNull(config.getCredentialsProvider());
+        Assert.assertNotNull(config.getHostnameVerifier());
+        Assert.assertNotNull(config.getTLSCipherSuites());
+        Assert.assertNotNull(config.getTLSCriteriaSet());
+        Assert.assertNotNull(config.getTLSProtocols());
+        Assert.assertNotNull(config.getTLSTrustEngine());
+    }
+    
+    @Test
+    public void testEmptyLists() {
+        BasicHttpClientSecurityConfiguration config = new BasicHttpClientSecurityConfiguration();
+        config.setTLSCipherSuites(Lists.<String>newArrayList());
+        config.setTLSProtocols(Lists.<String>newArrayList());
+        
+        Assert.assertNull(config.getTLSCipherSuites());
+        Assert.assertNull(config.getTLSProtocols());
+    }
+    
+    @Test
+    public void testCredentialsProvider() {
+        BasicHttpClientSecurityConfiguration config = new BasicHttpClientSecurityConfiguration();
+        config.setBasicCredentials(new UsernamePasswordCredentials("test", "test"));
+        
+        Assert.assertNotNull(config.getCredentialsProvider());
+    }
+    
+    
+    // Helpers
+    
+    public static class MockTrustEngine implements TrustEngine<X509Credential>  {
+        public boolean validate(X509Credential token, CriteriaSet trustBasisCriteria) throws SecurityException {
+            return false;
+        }
+    }
+
+}
diff --git a/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolverTest.java b/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolverTest.java
new file mode 100644
index 0000000..1d54639
--- /dev/null
+++ b/opensaml-security-impl/src/test/java/org/opensaml/security/httpclient/impl/BasicHttpClientSecurityParametersResolverTest.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements.  See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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.opensaml.security.httpclient.impl;
+
+import java.io.File;
+import java.net.URISyntaxException;
+import java.security.KeyException;
+import java.security.cert.CertificateException;
+
+import org.apache.http.conn.ssl.StrictHostnameVerifier;
+import org.apache.http.impl.client.BasicAuthCache;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.opensaml.security.SecurityException;
+import org.opensaml.security.credential.CredentialSupport;
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.security.httpclient.HttpClientSecurityConfigurationCriterion;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.security.x509.X509Support;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+
+import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
+import net.shibboleth.utilities.java.support.resolver.ResolverException;
+
+/**
+ *
+ */
+public class BasicHttpClientSecurityParametersResolverTest {
+    
+    private BasicHttpClientSecurityParametersResolver resolver;
+    
+    private X509Credential x509Credential1, x509Credential2, x509Credential3;
+    
+    @BeforeMethod
+    protected void setUp() throws CertificateException, URISyntaxException, KeyException {
+        resolver = new BasicHttpClientSecurityParametersResolver();
+        x509Credential1 = CredentialSupport.getSimpleCredential(
+                X509Support.decodeCertificate(new File(this.getClass().getResource("/data/certificate.pem").toURI())), 
+                KeySupport.decodePrivateKey(new File(this.getClass().getResource("/data/rsa-privkey-nopass.pem").toURI()), null)
+                );
+        x509Credential2 = CredentialSupport.getSimpleCredential(
+                X509Support.decodeCertificate(new File(this.getClass().getResource("/data/certificate.pem").toURI())), 
+                KeySupport.decodePrivateKey(new File(this.getClass().getResource("/data/rsa-privkey-nopass.pem").toURI()), null)
+                );
+        x509Credential3 = CredentialSupport.getSimpleCredential(
+                X509Support.decodeCertificate(new File(this.getClass().getResource("/data/certificate.pem").toURI())), 
+                KeySupport.decodePrivateKey(new File(this.getClass().getResource("/data/rsa-privkey-nopass.pem").toURI()), null)
+                );
+    }
+    
+    @Test
+    public void testSingleConfigFullyPopulated() throws ResolverException {
+        CriteriaSet criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                buildBaseConfiguration(x509Credential1)));
+        
+        HttpClientSecurityParameters params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getAuthCache());
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertNotNull(params.getCredentialsProvider());
+        Assert.assertNotNull(params.getHostnameVerifier());
+        Assert.assertNotNull(params.getTLSCipherSuites());
+        Assert.assertNotNull(params.getTLSCriteriaSet());
+        Assert.assertNotNull(params.getTLSProtocols());
+        Assert.assertNotNull(params.getTLSTrustEngine());
+    }
+    
+    @Test
+    public void testSingleConfigEmpty() throws ResolverException {
+        CriteriaSet criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                new BasicHttpClientSecurityConfiguration()));
+        
+        HttpClientSecurityParameters params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNull(params.getAuthCache());
+        Assert.assertNull(params.getClientTLSCredential());
+        Assert.assertNull(params.getCredentialsProvider());
+        Assert.assertNull(params.getHostnameVerifier());
+        Assert.assertNull(params.getTLSCipherSuites());
+        Assert.assertNull(params.getTLSCriteriaSet());
+        Assert.assertNull(params.getTLSProtocols());
+        Assert.assertNull(params.getTLSTrustEngine());
+    }
+    
+    @Test
+    public void testMultipleConfigsSimple() throws ResolverException {
+        CriteriaSet criteria;
+        HttpClientSecurityParameters params;
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                buildBaseConfiguration(x509Credential1),
+                new BasicHttpClientSecurityConfiguration(),
+                new BasicHttpClientSecurityConfiguration()));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getAuthCache());
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertNotNull(params.getCredentialsProvider());
+        Assert.assertNotNull(params.getHostnameVerifier());
+        Assert.assertNotNull(params.getTLSCipherSuites());
+        Assert.assertNotNull(params.getTLSCriteriaSet());
+        Assert.assertNotNull(params.getTLSProtocols());
+        Assert.assertNotNull(params.getTLSTrustEngine());
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                new BasicHttpClientSecurityConfiguration(),
+                buildBaseConfiguration(x509Credential1),
+                new BasicHttpClientSecurityConfiguration()));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getAuthCache());
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertNotNull(params.getCredentialsProvider());
+        Assert.assertNotNull(params.getHostnameVerifier());
+        Assert.assertNotNull(params.getTLSCipherSuites());
+        Assert.assertNotNull(params.getTLSCriteriaSet());
+        Assert.assertNotNull(params.getTLSProtocols());
+        Assert.assertNotNull(params.getTLSTrustEngine());
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                new BasicHttpClientSecurityConfiguration(),
+                new BasicHttpClientSecurityConfiguration(),
+                buildBaseConfiguration(x509Credential1)));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getAuthCache());
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertNotNull(params.getCredentialsProvider());
+        Assert.assertNotNull(params.getHostnameVerifier());
+        Assert.assertNotNull(params.getTLSCipherSuites());
+        Assert.assertNotNull(params.getTLSCriteriaSet());
+        Assert.assertNotNull(params.getTLSProtocols());
+        Assert.assertNotNull(params.getTLSTrustEngine());
+    }
+    
+    @Test
+    public void testMultipleConfigsLayered() throws ResolverException {
+        CriteriaSet criteria;
+        HttpClientSecurityParameters params;
+        
+        BasicHttpClientSecurityConfiguration config1 = buildBaseConfiguration(x509Credential1);
+        BasicHttpClientSecurityConfiguration config2 = buildBaseConfiguration(x509Credential2);
+        BasicHttpClientSecurityConfiguration config3 = buildBaseConfiguration(x509Credential3);
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                config1,
+                config2,
+                config3));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertSame(params.getClientTLSCredential(), config1.getClientTLSCredential());
+        
+        config1.setClientTLSCredential(null);
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                config1,
+                config2,
+                config3));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertSame(params.getClientTLSCredential(), config2.getClientTLSCredential());
+        
+        config2.setClientTLSCredential(null);
+        
+        criteria = new CriteriaSet(new HttpClientSecurityConfigurationCriterion(
+                config1,
+                config2,
+                config3));
+        
+        params = resolver.resolveSingle(criteria);
+        
+        Assert.assertNotNull(params);;
+        Assert.assertNotNull(params.getClientTLSCredential());
+        Assert.assertSame(params.getClientTLSCredential(), config3.getClientTLSCredential());
+    }
+    
+    
+    // Helpers
+    
+    private BasicHttpClientSecurityConfiguration buildBaseConfiguration(X509Credential x509Credential)  {
+        BasicHttpClientSecurityConfiguration config = new BasicHttpClientSecurityConfiguration();
+        config.setAuthCache(new BasicAuthCache());
+        config.setClientTLSCredential(x509Credential);
+        config.setCredentialsProvider(new BasicCredentialsProvider());
+        config.setHostnameVerifier(new StrictHostnameVerifier());
+        config.setTLSCipherSuites(Lists.newArrayList("test"));
+        config.setTLSCriteriaSet(new CriteriaSet());
+        config.setTLSProtocols(Lists.newArrayList("test"));
+        config.setTLSTrustEngine(new MockTrustEngine());
+        return config;
+    }
+    
+    public static class MockTrustEngine implements TrustEngine<X509Credential>  {
+        public boolean validate(X509Credential token, CriteriaSet trustBasisCriteria) throws SecurityException {
+            return false;
+        }
+    }
+
+}
diff --git a/opensaml-security-impl/src/test/resources/logback-test.xml b/opensaml-security-impl/src/test/resources/logback-test.xml
index d03dd06..7374663 100644
--- a/opensaml-security-impl/src/test/resources/logback-test.xml
+++ b/opensaml-security-impl/src/test/resources/logback-test.xml
@@ -8,6 +8,10 @@
         </encoder>
     </appender>
     
+    <logger name="org.opensaml.security.httpclient">
+        <level value="DEBUG"/>
+    </logger>
+    
     <logger name="org.opensaml">
         <level value="WARN"/>
     </logger>

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list