[java-identity-provider] branch master updated: IDP-1170 - REST DataConnector
Scott Cantor
cantor.2 at osu.edu
Thu Aug 10 16:45:14 EDT 2017
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=fe8a5c8712b65777d508c73de393b6ad90859df6
The following commit(s) were added to refs/heads/master by this push:
new fe8a5c8 IDP-1170 - REST DataConnector
fe8a5c8 is described below
commit fe8a5c8712b65777d508c73de393b6ad90859df6
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Aug 10 16:45:13 2017 -0400
IDP-1170 - REST DataConnector
https://issues.shibboleth.net/jira/browse/IDP-1170
Add certificate and certificateAuthority shortcuts to schema
---
idp-attribute-resolver-spring/pom.xml | 7 ++
.../dc/http/impl/HTTPDataConnectorParser.java | 70 ++++++++++++++--
.../dc/http/HTTPDataConnectorParserTest.java | 94 ++++++++++++++++++++++
.../dc/http/http-attribute-resolver-v2-ca.xml | 18 +++++
.../http-attribute-resolver-v2-certificate.xml | 18 +++++
.../resolver/spring/dc/http/spring-beans.xml | 8 ++
.../schema/shibboleth-attribute-resolver.xsd | 14 ++++
7 files changed, 222 insertions(+), 7 deletions(-)
diff --git a/idp-attribute-resolver-spring/pom.xml b/idp-attribute-resolver-spring/pom.xml
index d809c3d..a47c608 100644
--- a/idp-attribute-resolver-spring/pom.xml
+++ b/idp-attribute-resolver-spring/pom.xml
@@ -132,6 +132,13 @@
</dependency>
<dependency>
<groupId>${opensaml.groupId}</groupId>
+ <artifactId>opensaml-saml-impl</artifactId>
+ <version>${opensaml.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-storage-impl</artifactId>
<version>${opensaml.version}</version>
<scope>test</scope>
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/impl/HTTPDataConnectorParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/impl/HTTPDataConnectorParser.java
index 2733151..3d49cfc 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/impl/HTTPDataConnectorParser.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/impl/HTTPDataConnectorParser.java
@@ -30,6 +30,8 @@ import net.shibboleth.idp.attribute.resolver.dc.http.impl.TemplatedURLBuilder;
import net.shibboleth.idp.attribute.resolver.spring.dc.AbstractDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.CacheConfigParser;
import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.idp.profile.spring.factory.StaticExplicitKeyFactoryBean;
+import net.shibboleth.idp.profile.spring.factory.StaticPKIXFactoryBean;
import net.shibboleth.idp.profile.spring.relyingparty.metadata.ScriptTypeBeanParser;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
import net.shibboleth.utilities.java.support.logic.Constraint;
@@ -37,6 +39,7 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
import net.shibboleth.utilities.java.support.xml.AttributeSupport;
import net.shibboleth.utilities.java.support.xml.ElementSupport;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinition;
@@ -59,6 +62,7 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
return HTTPDataConnector.class;
}
+// Checkstyle: CyclomaticComplexity OFF
/** {@inheritDoc} */
@Override protected void doV2Parse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
@Nonnull final BeanDefinitionBuilder builder) {
@@ -74,7 +78,14 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
final String securityParams =
StringSupport.trimOrNull(config.getAttributeNS(null, "httpClientSecurityParametersRef"));
- if (securityParams != null) {
+ final BeanDefinition httpClientSecurityBean =
+ v2Parser.buildHttpClientSecurityParams(config.getAttributeNS(null, "id"));
+ if (httpClientSecurityBean != null) {
+ if (securityParams != null) {
+ log.warn("Ignoring httpClientSecurityParametersRef setting in favor of manual settings");
+ }
+ builder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityBean);
+ } else if (securityParams != null) {
builder.addPropertyReference("httpClientSecurityParameters", securityParams);
}
@@ -82,7 +93,7 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
if (searchBuilderID != null) {
builder.addPropertyReference("executableSearchBuilder", searchBuilderID);
} else {
- final BeanDefinition def = v2Parser.createTemplateBuilder();
+ final BeanDefinition def = v2Parser.createTemplateBuilder(httpClientSecurityBean);
if (def != null) {
builder.addPropertyValue("executableSearchBuilder", def);
}
@@ -114,6 +125,7 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
builder.setInitMethodName("initialize");
builder.setDestroyMethodName("destroy");
}
+// Checkstyle: CyclomaticComplexity ON
/**
* Utility class for parsing v2 schema configuration.
@@ -163,9 +175,10 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
/**
* Create the definition of the template driven search builder.
*
+ * @param httpClientSecurityParams instance of {@link HttpClientSecurityParameters} to inject
* @return the bean definition for the template search builder.
*/
- @Nonnull public BeanDefinition createTemplateBuilder() {
+ @Nonnull public BeanDefinition createTemplateBuilder(@Nullable final BeanDefinition httpClientSecurityParams) {
final BeanDefinitionBuilder templateBuilder =
BeanDefinitionBuilder.genericBeanDefinition(TemplatedURLBuilder.class);
templateBuilder.setInitMethodName("initialize");
@@ -178,10 +191,14 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
templateBuilder.addPropertyReference("velocityEngine", velocityEngineRef);
// This is duplication but allows the built-in builder to access the parameters if desired.
- final String securityParams =
- StringSupport.trimOrNull(configElement.getAttributeNS(null, "httpClientSecurityParametersRef"));
- if (securityParams != null) {
- templateBuilder.addPropertyReference("httpClientSecurityParameters", securityParams);
+ if (httpClientSecurityParams != null) {
+ templateBuilder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityParams);
+ } else {
+ final String securityParamsRef =
+ StringSupport.trimOrNull(configElement.getAttributeNS(null, "httpClientSecurityParametersRef"));
+ if (securityParamsRef != null) {
+ templateBuilder.addPropertyReference("httpClientSecurityParameters", securityParamsRef);
+ }
}
final List<Element> urlTemplates = ElementSupport.getChildElements(configElement,
@@ -276,6 +293,45 @@ public class HTTPDataConnectorParser extends AbstractDataConnectorParser {
return parser.createCache(parserContext);
}
+ /**
+ * Check for manually supplied settings and build {@link HttpClientSecurityParameters} instance.
+ *
+ * @param id connector ID
+ *
+ * @return a bean definition if applicable
+ */
+ @Nullable public BeanDefinition buildHttpClientSecurityParams(@Nullable final String id) {
+ BeanDefinitionBuilder builder = null;
+ final String certificate = StringSupport.trimOrNull(configElement.getAttributeNS(null, "certificate"));
+ if (certificate != null) {
+ log.debug("Auto-configuring connector {} with a server certificate to authenticate", id);
+ builder = BeanDefinitionBuilder.genericBeanDefinition(HttpClientSecurityParameters.class);
+ final BeanDefinitionBuilder explicitTrust =
+ BeanDefinitionBuilder.genericBeanDefinition(StaticExplicitKeyFactoryBean.class);
+ explicitTrust.addPropertyValue("certificates", certificate);
+ builder.addPropertyValue("tLSTrustEngine", explicitTrust.getBeanDefinition());
+ }
+
+ final String certificateAuthority =
+ StringSupport.trimOrNull(configElement.getAttributeNS(null, "certificateAuthority"));
+ if (certificateAuthority != null) {
+ if (builder != null) {
+ log.warn("Ignoring certificateAuthority set on connector {}, superseded by certificate", id);
+ } else {
+ log.debug("Auto-configuring connector {} with a certificate authority to authenticate", id);
+ builder = BeanDefinitionBuilder.genericBeanDefinition(HttpClientSecurityParameters.class);
+ final BeanDefinitionBuilder pkixTrust =
+ BeanDefinitionBuilder.genericBeanDefinition(StaticPKIXFactoryBean.class);
+ // Relies on underlying enhanced TLSSocketFactory hostname verifier to kick in.
+ pkixTrust.addPropertyValue("checkNames", false);
+ pkixTrust.addPropertyValue("certificates", certificateAuthority);
+ builder.addPropertyValue("tLSTrustEngine", pkixTrust.getBeanDefinition());
+ }
+ }
+
+ return builder != null ? builder.getBeanDefinition() : null;
+ }
+
/** The parent parser's log prefix.
* @return the log prefix.
*/
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/HTTPDataConnectorParserTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/HTTPDataConnectorParserTest.java
index c7de646..3422ba0 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/HTTPDataConnectorParserTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/dc/http/HTTPDataConnectorParserTest.java
@@ -166,6 +166,100 @@ public class HTTPDataConnectorParserTest {
Assert.assertTrue(attrs == null || attrs.isEmpty());
}
+ @Test public void v2Certificate() throws Exception {
+
+ final MockPropertySource propSource = singletonPropertySource("serviceURL", TEST_URL);
+ propSource.setProperty("scriptPath", (isV8() ? SCRIPT_PATH_V8 : SCRIPT_PATH) + "test.js");
+ propSource.setProperty("certificate", "/org/opensaml/saml/metadata/resolver/impl/repo-entity.crt");
+
+ final HTTPDataConnector connector =
+ getDataConnector(propSource,
+ "net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-certificate.xml");
+ Assert.assertNotNull(connector);
+
+ final AttributeResolutionContext context =
+ TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
+ TestSources.SP_ENTITY_ID);
+
+ connector.resolve(context);
+
+ final Map<String,IdPAttribute> attrs = connector.resolve(context);
+
+ Assert.assertEquals(attrs.size(), 2);
+
+ Assert.assertEquals(attrs.get("foo").getValues().size(), 1);
+ Assert.assertEquals(attrs.get("foo").getValues().get(0).getValue(), "foo1");
+
+ Assert.assertEquals(attrs.get("bar").getValues().size(), 2);
+ Assert.assertEquals(attrs.get("bar").getValues().get(0).getValue(), "bar1");
+ Assert.assertEquals(attrs.get("bar").getValues().get(1).getValue(), "bar2");
+ }
+
+ @Test(expectedExceptions=ResolutionException.class) public void v2BadCertificate() throws Exception {
+
+ final MockPropertySource propSource = singletonPropertySource("serviceURL", TEST_URL);
+ propSource.setProperty("scriptPath", (isV8() ? SCRIPT_PATH_V8 : SCRIPT_PATH) + "test.js");
+ propSource.setProperty("certificate", "/org/opensaml/saml/metadata/resolver/impl/badKey.crt");
+
+ final HTTPDataConnector connector =
+ getDataConnector(propSource,
+ "net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-certificate.xml");
+ Assert.assertNotNull(connector);
+
+ final AttributeResolutionContext context =
+ TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
+ TestSources.SP_ENTITY_ID);
+
+ connector.resolve(context);
+ }
+
+ @Test public void v2CA() throws Exception {
+
+ final MockPropertySource propSource = singletonPropertySource("serviceURL", TEST_URL);
+ propSource.setProperty("scriptPath", (isV8() ? SCRIPT_PATH_V8 : SCRIPT_PATH) + "test.js");
+ propSource.setProperty("certificateAuthority", "/org/opensaml/saml/metadata/resolver/impl/repo-rootCA.crt");
+
+ final HTTPDataConnector connector =
+ getDataConnector(propSource,
+ "net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-ca.xml");
+ Assert.assertNotNull(connector);
+
+ final AttributeResolutionContext context =
+ TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
+ TestSources.SP_ENTITY_ID);
+
+ connector.resolve(context);
+
+ final Map<String,IdPAttribute> attrs = connector.resolve(context);
+
+ Assert.assertEquals(attrs.size(), 2);
+
+ Assert.assertEquals(attrs.get("foo").getValues().size(), 1);
+ Assert.assertEquals(attrs.get("foo").getValues().get(0).getValue(), "foo1");
+
+ Assert.assertEquals(attrs.get("bar").getValues().size(), 2);
+ Assert.assertEquals(attrs.get("bar").getValues().get(0).getValue(), "bar1");
+ Assert.assertEquals(attrs.get("bar").getValues().get(1).getValue(), "bar2");
+ }
+
+ @Test(expectedExceptions=ResolutionException.class) public void v2BadCA() throws Exception {
+
+ final MockPropertySource propSource = singletonPropertySource("serviceURL", TEST_URL);
+ propSource.setProperty("scriptPath", (isV8() ? SCRIPT_PATH_V8 : SCRIPT_PATH) + "test.js");
+ propSource.setProperty("certificateAuthority", "/org/opensaml/saml/metadata/resolver/impl/badCA.crt");
+
+ final HTTPDataConnector connector =
+ getDataConnector(propSource,
+ "net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-ca.xml");
+ Assert.assertNotNull(connector);
+
+ final AttributeResolutionContext context =
+ TestSources.createResolutionContext(TestSources.PRINCIPAL_ID, TestSources.IDP_ENTITY_ID,
+ TestSources.SP_ENTITY_ID);
+
+ connector.resolve(context);
+ }
+
@Test public void hybridConfig() throws Exception {
final MockPropertySource propSource = singletonPropertySource("serviceURL", TEST_URL);
propSource.setProperty("scriptPath", (isV8() ? SCRIPT_PATH_V8 : SCRIPT_PATH) + "test.js");
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-ca.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-ca.xml
new file mode 100644
index 0000000..5abd7ae
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-ca.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeResolver
+ xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <DataConnector id="myHTTP" xsi:type="HTTP"
+ httpClientRef="TrustEngineHttpClient"
+ certificateAuthority="%{certificateAuthority}">
+
+ <URLTemplate>%{serviceURL}</URLTemplate>
+
+ <ResponseMapping>
+ <ScriptFile>%{scriptPath}</ScriptFile>
+ </ResponseMapping>
+
+ </DataConnector>
+
+</AttributeResolver>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-certificate.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-certificate.xml
new file mode 100644
index 0000000..12f5b53
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/http-attribute-resolver-v2-certificate.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttributeResolver
+ xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
+
+ <DataConnector id="myHTTP" xsi:type="HTTP"
+ httpClientRef="TrustEngineHttpClient"
+ certificate="%{certificate}">
+
+ <URLTemplate>%{serviceURL}</URLTemplate>
+
+ <ResponseMapping>
+ <ScriptFile>%{scriptPath}</ScriptFile>
+ </ResponseMapping>
+
+ </DataConnector>
+
+</AttributeResolver>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/spring-beans.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/spring-beans.xml
index 6c2f273..45c4b20 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/spring-beans.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/http/spring-beans.xml
@@ -8,6 +8,14 @@
<bean id="NoTrustEngineHttpClient"
class="net.shibboleth.idp.profile.spring.relyingparty.metadata.HttpClientFactoryBean" />
+ <bean id="SecurityEnhancedTLSSocketFactory"
+ class="org.opensaml.security.httpclient.impl.SecurityEnhancedHttpClientSupport"
+ factory-method="buildTLSSocketFactory" />
+
+ <bean id="TrustEngineHttpClient"
+ class="net.shibboleth.idp.profile.spring.relyingparty.metadata.HttpClientFactoryBean"
+ p:TLSSocketFactory-ref="SecurityEnhancedTLSSocketFactory" />
+
<bean id="BadProtocolParameters"
class="org.opensaml.security.httpclient.HttpClientSecurityParameters"
p:TLSProtocols="SSLv3" />
diff --git a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index 86de4b7..d7bdbce 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -1260,6 +1260,20 @@
</documentation>
</annotation>
</attribute>
+ <attribute name="certificate" type="string">
+ <annotation>
+ <documentation>
+ Location of certificate to authenticate HTTP server
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="certificateAuthority" type="string">
+ <annotation>
+ <documentation>
+ Location of CA to indirectly authenticate HTTP server
+ </documentation>
+ </annotation>
+ </attribute>
<attribute name="templateEngine" type="string">
<annotation>
<documentation>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list