[java-shib-metadata] 02/02: OSJ-391: Default supported TLS protocols appears too broad

Brent Putman putmanb at georgetown.edu
Fri Feb 9 15:59:37 UTC 2024


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

putmanb pushed a commit to branch main
in repository java-shib-metadata.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-metadata.git;a=commit;h=c6f41739bcc71613df7d384615b1b9cb1d8b69d8

commit c6f41739bcc71613df7d384615b1b9cb1d8b69d8
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Thu Feb 8 17:54:35 2024 -0500

    OSJ-391: Default supported TLS protocols appears too broad
    
    Refactor HTTP resolver support for HttpClientSecurityParams to use new
    factory bean which merges the TLS TrustEngine and security params ref
    inputs.
---
 .../AbstractDynamicHTTPMetadataProviderParser.java | 32 +++------
 .../metadata/HTTPMetadataProviderParser.java       | 36 +++-------
 .../HTTPMetadataProvidersParserSupport.java        | 53 +++++++++++---
 .../DynamicHTTPMetadataProviderParserTest.java     | 33 +++++++++
 .../FileBackedHTTPMetadataProviderParserTest.java  | 28 ++++++++
 .../impl/MetadataResolverTestingSupport.java       | 55 +++++++++++++++
 ...-https-trustEngine-explicitKey-params-merge.xml | 81 ++++++++++++++++++++++
 .../https-trustEngine-explicitKey-params-merge.xml | 78 +++++++++++++++++++++
 8 files changed, 336 insertions(+), 60 deletions(-)

diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/AbstractDynamicHTTPMetadataProviderParser.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/AbstractDynamicHTTPMetadataProviderParser.java
index 5a064b71..1b1f837a 100644
--- a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/AbstractDynamicHTTPMetadataProviderParser.java
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/AbstractDynamicHTTPMetadataProviderParser.java
@@ -58,28 +58,19 @@ public abstract class AbstractDynamicHTTPMetadataProviderParser extends Abstract
     /** Logger. */
     private final Logger log = LoggerFactory.getLogger(AbstractDynamicHTTPMetadataProviderParser.class);
 
-// Checkstyle: CyclomaticComplexity OFF
     /** {@inheritDoc} */
     @Override protected void doNativeParse(@Nonnull final Element element, @Nonnull final ParserContext parserContext,
             @Nonnull final BeanDefinitionBuilder builder) {
         super.doNativeParse(element, parserContext, builder);
 
-        final Element tlsTrustEngine = ElementSupport.getFirstChildElement(element,
-                HTTPMetadataProvidersParserSupport.TLS_TRUST_ENGINE_ELEMENT_NAME);
-        final String httpClientSecurityParametersRef =
-                StringSupport.trimOrNull(element.getAttributeNS(null, "httpClientSecurityParametersRef"));
-        BeanDefinition httpClientSecurityParameters = null;
+        final BeanDefinition httpClientSecurityParameters =
+                HTTPMetadataProvidersParserSupport.buildHttpClientSecurityParameters(
+                        ElementSupport.getFirstChildElement(element,
+                                HTTPMetadataProvidersParserSupport.TLS_TRUST_ENGINE_ELEMENT_NAME),
+                        StringSupport.trimOrNull(element.getAttributeNS(null, "httpClientSecurityParametersRef")),
+                        parserContext);
 
-        if (httpClientSecurityParametersRef != null) {
-            if (tlsTrustEngine != null) {
-                log.warn("httpClientSecurityParametersRef overrides <TrustEngine> subelement");
-            }
-            builder.addPropertyReference("httpClientSecurityParameters", httpClientSecurityParametersRef);
-        } else if (tlsTrustEngine != null) {
-            httpClientSecurityParameters =
-                    HTTPMetadataProvidersParserSupport.parseTLSTrustEngine(tlsTrustEngine, parserContext);
-            builder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityParameters);
-        }
+        builder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityParameters);
 
         if (element.hasAttributeNS(null, "httpClientRef")) {
             builder.addConstructorArgReference(
@@ -98,8 +89,7 @@ public abstract class AbstractDynamicHTTPMetadataProviderParser extends Abstract
                     + "proxyUser and proxyPassword");
             }
         } else {
-            builder.addConstructorArgValue(buildHttpClient(element, parserContext,
-                    httpClientSecurityParametersRef, httpClientSecurityParameters));
+            builder.addConstructorArgValue(buildHttpClient(element, parserContext, httpClientSecurityParameters));
         }
 
         if (element.hasAttributeNS(null, "supportedContentTypes")) {
@@ -108,28 +98,24 @@ public abstract class AbstractDynamicHTTPMetadataProviderParser extends Abstract
             builder.addPropertyValue("supportedContentTypes", listBuilder);
         }
     }
-// Checkstyle: CyclomaticComplexity ON
 
     /**
      * Build the definition of the HTTPClientBuilder which contains all our configuration.
      * 
      * @param element the HTTPMetadataProvider parser.
      * @param parserContext the context
-     * @param httpClientSecurityParametersRef the client security parameters ref to be used
      * @param httpClientSecurityParameters the client security parameters to be used
      * @return the bean definition with the parameters.
      * 
      * Either httpClientSecurityParametersRef or httpClientSecurityParameters can be present, not both.
      */
     @Nonnull private BeanDefinition buildHttpClient(@Nonnull final Element element,
-            @Nonnull final ParserContext parserContext, @Nullable final String httpClientSecurityParametersRef,
-            @Nullable final BeanDefinition httpClientSecurityParameters) {
+            @Nonnull final ParserContext parserContext, @Nullable final BeanDefinition httpClientSecurityParameters) {
 
         final BeanDefinitionBuilder clientBuilder = 
                 HTTPMetadataProvidersParserSupport.buildCommonClientBuilder(element,
                         parserContext,
                         DEFAULT_CACHING_CLASS ,
-                        httpClientSecurityParametersRef,
                         httpClientSecurityParameters);
 
         // Set up non standard defaults
diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProviderParser.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProviderParser.java
index 9bf37083..4da68421 100644
--- a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProviderParser.java
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProviderParser.java
@@ -40,29 +40,20 @@ public abstract class HTTPMetadataProviderParser extends AbstractReloadingMetada
     /** Logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(HTTPMetadataProviderParser.class);
 
-// Checkstyle: CyclomaticComplexity OFF
     /** {@inheritDoc} */
     @Override protected void doNativeParse(@Nonnull final Element element, @Nonnull final ParserContext parserContext,
             @Nonnull final BeanDefinitionBuilder builder) {
         
         super.doNativeParse(element, parserContext, builder);
 
-        final Element tlsTrustEngine = ElementSupport.getFirstChildElement(element,
-                HTTPMetadataProvidersParserSupport.TLS_TRUST_ENGINE_ELEMENT_NAME);
-        final String httpClientSecurityParametersRef =
-                StringSupport.trimOrNull(element.getAttributeNS(null, "httpClientSecurityParametersRef"));
-        BeanDefinition httpClientSecurityParameters = null;
+        final BeanDefinition httpClientSecurityParameters =
+                HTTPMetadataProvidersParserSupport.buildHttpClientSecurityParameters(
+                        ElementSupport.getFirstChildElement(element,
+                                HTTPMetadataProvidersParserSupport.TLS_TRUST_ENGINE_ELEMENT_NAME),
+                        StringSupport.trimOrNull(element.getAttributeNS(null, "httpClientSecurityParametersRef")),
+                        parserContext);
 
-        if (httpClientSecurityParametersRef != null) {
-            if (tlsTrustEngine != null) {
-                log.warn("httpClientSecurityParametersRef overrides <TrustEngine> subelement");
-            }
-            builder.addPropertyReference("httpClientSecurityParameters", httpClientSecurityParametersRef);
-        } else if (tlsTrustEngine != null)  {
-            httpClientSecurityParameters =
-                    HTTPMetadataProvidersParserSupport.parseTLSTrustEngine(tlsTrustEngine, parserContext);
-            builder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityParameters);
-        }
+        builder.addPropertyValue("httpClientSecurityParameters", httpClientSecurityParameters);
 
         if (element.hasAttributeNS(null, "httpClientRef")) {
             builder.addConstructorArgReference(
@@ -78,32 +69,25 @@ public abstract class HTTPMetadataProviderParser extends AbstractReloadingMetada
                     + " proxyHost, proxyPort, proxyUser and proxyPassword");
             }
         } else {
-            builder.addConstructorArgValue(buildHttpClient(element, parserContext,
-                    httpClientSecurityParametersRef, httpClientSecurityParameters));
+            builder.addConstructorArgValue(buildHttpClient(element, parserContext, httpClientSecurityParameters));
         }
         builder.addConstructorArgValue(StringSupport.trimOrNull(element.getAttributeNS(null,
                 HTTPMetadataProvidersParserSupport.METADATA_URL)));
     }
-// Checkstyle: CyclomaticComplexity ON
 
     /**
      * Build the definition of the HTTPClientBuilder which contains all our configuration.
      * 
      * @param element the HTTPMetadataProvider parser.
      * @param parserContext context
-     * @param httpClientSecurityParametersRef the client security parameters ref to be used
      * @param httpClientSecurityParameters the client security parameters to be used
      * @return the bean definition with the parameters.
-     * 
-     * Either httpClientSecurityParametersRef or httpClientSecurityParameters can be present, not both.
      */
     @Nonnull private BeanDefinition buildHttpClient(@Nonnull final Element element,
-            @Nonnull final ParserContext parserContext, @Nullable final String httpClientSecurityParametersRef,
-            @Nullable final BeanDefinition httpClientSecurityParameters) {
+            @Nonnull final ParserContext parserContext, @Nullable final BeanDefinition httpClientSecurityParameters) {
 
         return HTTPMetadataProvidersParserSupport.buildCommonClientBuilder(element, parserContext,
-                HTTPMetadataProviderParser.DEFAULT_CLIENT_CLASS, httpClientSecurityParametersRef,
-                httpClientSecurityParameters).getBeanDefinition();
+                HTTPMetadataProviderParser.DEFAULT_CLIENT_CLASS, httpClientSecurityParameters).getBeanDefinition();
     }
     
 }
\ No newline at end of file
diff --git a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProvidersParserSupport.java b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProvidersParserSupport.java
index 10230270..e57dd2df 100644
--- a/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProvidersParserSupport.java
+++ b/shib-metadata-spring/src/main/java/net/shibboleth/spring/metadata/HTTPMetadataProvidersParserSupport.java
@@ -14,15 +14,21 @@
 
 package net.shibboleth.spring.metadata;
 
+import java.util.List;
+
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.xml.namespace.QName;
 
 import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.opensaml.spring.httpclient.HttpClientSecurityParametersMergingFactoryBean;
 import org.opensaml.spring.tls.TLSSocketFactoryFactoryBean;
 import org.slf4j.Logger;
+import org.springframework.beans.BeanMetadataElement;
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedList;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.w3c.dom.Element;
 
@@ -53,20 +59,51 @@ public final class HTTPMetadataProvidersParserSupport {
     private HTTPMetadataProvidersParserSupport() {
     }
     
+    /**
+     * Build the definition of the HttpClientSecurityParameters as a factory bean which merges the inline TLS TrustEngine
+     * and parameters ref inputs.
+     * 
+     * @param tlsTrustEngine the element defining the inline TLS TrustEngine
+     * @param parametersRef the security parameters bean reference
+     * @param parserContext context
+     * @return the bean definition with the parameters.
+     */
+    @Nonnull protected static BeanDefinition buildHttpClientSecurityParameters(@Nullable final Element tlsTrustEngine,
+            @Nullable final String parametersRef, @Nonnull final ParserContext parserContext) {
+        
+        final BeanDefinitionBuilder factoryBuilder =
+                BeanDefinitionBuilder.genericBeanDefinition(HttpClientSecurityParametersMergingFactoryBean.class);
+        
+        final List<BeanMetadataElement> factoryInputs = new ManagedList<>(2);
+
+        // First order-of-precedence
+        if (tlsTrustEngine != null)  {
+            final BeanDefinition trustEngineParams = parseTLSTrustEngine(tlsTrustEngine, parserContext);
+            if (trustEngineParams != null) {
+                factoryInputs.add(trustEngineParams);
+            }
+        }
+
+        // Second order-of-precedence
+        if (parametersRef != null) {
+            factoryInputs.add(new RuntimeBeanReference(parametersRef));
+        }
+
+        factoryBuilder.addPropertyValue("parameters", factoryInputs);
+        
+        return factoryBuilder.getBeanDefinition();
+    }
+    
     /**
      * Build the definition of the HTTPClientBuilder which contains all our configuration.
      * 
      * @param element the HTTPMetadataProvider parser.
      * @param parserContext context
-     * @param httpClientSecurityParametersRef a reference,
      * @param httpClientSecurityParameters a bean definition
      * @return the bean definition with the parameters.
-     * 
-     * Either httpClientSecurityParametersRef or httpClientSecurityParameters can be present, not both.
      */
     @Nonnull protected static BeanDefinition buildTLSSocketFactory(
             @Nonnull final Element element, @Nonnull final ParserContext parserContext,
-            @Nullable final String httpClientSecurityParametersRef,
             @Nullable final BeanDefinition httpClientSecurityParameters) {
 
         Constraint.isNotNull(LOG, "LOG must be present");
@@ -78,10 +115,6 @@ public final class HTTPMetadataProvidersParserSupport {
                     StringSupport.trimOrNull(element.getAttributeNS(null, "disregardTLSCertificate")));
         }
 
-        if (httpClientSecurityParametersRef != null) {
-            tlsSocketFactoryBuilder.addPropertyReference("httpClientSecurityParameters", 
-                    httpClientSecurityParametersRef);
-        }
         if (httpClientSecurityParameters != null) {
             tlsSocketFactoryBuilder.addPropertyValue("httpClientSecurityParameters", 
                     httpClientSecurityParameters);
@@ -133,14 +166,12 @@ public final class HTTPMetadataProvidersParserSupport {
      * @param element the configuration
      * @param parserContext context
      * @param clientBuildClass the type of builder to create.
-     * @param httpClientSecurityParametersRef the client security parameters ref to be used
      * @param httpClientSecurityParameters the client security parameters to be used
      * 
      * @return an appropriate builder
      */
     @Nonnull protected static BeanDefinitionBuilder buildCommonClientBuilder(@Nonnull final Element element,
             @Nonnull final ParserContext parserContext, @Nonnull final Class<?> clientBuildClass,
-            @Nullable final String httpClientSecurityParametersRef,
             @Nullable final BeanDefinition httpClientSecurityParameters) {
 
         final BeanDefinitionBuilder clientBuilder = BeanDefinitionBuilder.genericBeanDefinition(clientBuildClass);
@@ -161,7 +192,7 @@ public final class HTTPMetadataProvidersParserSupport {
 
         clientBuilder.addPropertyValue("tLSSocketFactory",
                 HTTPMetadataProvidersParserSupport.buildTLSSocketFactory(
-                        element, parserContext, httpClientSecurityParametersRef, httpClientSecurityParameters));
+                        element, parserContext, httpClientSecurityParameters));
 
         if (element.hasAttributeNS(null, "proxyHost")) {
             clientBuilder.addPropertyValue("connectionProxyHost",
diff --git a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/DynamicHTTPMetadataProviderParserTest.java b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/DynamicHTTPMetadataProviderParserTest.java
index 543fd7da..e74d48fa 100644
--- a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/DynamicHTTPMetadataProviderParserTest.java
+++ b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/DynamicHTTPMetadataProviderParserTest.java
@@ -30,9 +30,11 @@ import org.opensaml.saml.criterion.ArtifactCriterion;
 import org.opensaml.saml.metadata.resolver.impl.AbstractDynamicMetadataResolver;
 import org.opensaml.saml.metadata.resolver.impl.FunctionDrivenDynamicHTTPMetadataResolver;
 import org.opensaml.saml.metadata.resolver.impl.HTTPEntityIDRequestURLBuilder;
+import org.opensaml.saml.metadata.resolver.impl.MetadataResolverTestingSupport;
 import org.opensaml.saml.saml2.binding.artifact.SAML2ArtifactType0004;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
 import org.opensaml.security.crypto.JCAConstants;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
 import org.springframework.context.ApplicationContext;
 import org.springframework.mock.env.MockPropertySource;
 import org.testng.Assert;
@@ -439,6 +441,37 @@ public class DynamicHTTPMetadataProviderParserTest extends AbstractMetadataParse
         Assert.assertEquals(ed.getEntityID(), entityID);
     }
     
+    @Test
+    public void testHTTPSTrustEngineExplicitKeyViaParamsMerge() throws Exception {
+        MockPropertySource propSource = singletonPropertySource(PROP_MDURL, 
+                RepositorySupport.buildHTTPSResourceURL(REPO_OPENSAML, TEMPLATE_URL));
+        
+        final FunctionDrivenDynamicHTTPMetadataResolver resolver = getBean(FunctionDrivenDynamicHTTPMetadataResolver.class, 
+                propSource, "dynamic-https-trustEngine-explicitKey-params-merge.xml", "beans.xml");
+        
+        //Test the merged security params instance
+        assert resolver != null;
+        final HttpClientSecurityParameters securityParams = MetadataResolverTestingSupport.getHttpClientSecurityParameters(resolver);
+        assert securityParams != null;
+        Assert.assertNotNull(securityParams);
+        Assert.assertNotNull(securityParams.getTLSTrustEngine());
+        final List<String> protocols = securityParams.getTLSProtocols();
+        assert protocols != null;
+        Assert.assertNotNull(securityParams.getTLSProtocols());
+        Assert.assertEquals(protocols.size(), 2);
+        Assert.assertTrue(protocols.contains("TLSv1.3"));
+        Assert.assertTrue(protocols.contains("TLSv1.2"));
+        
+        final String entityID = "https://www.example.org/sp";
+        
+        final CriteriaSet criteriaSet = new CriteriaSet( new EntityIdCriterion(entityID));
+        
+        final EntityDescriptor ed = resolver.resolveSingle(criteriaSet);
+        Assert.assertNotNull(ed);
+        assert ed != null;
+        Assert.assertEquals(ed.getEntityID(), entityID);
+    }
+    
     @Test
     public void testHTTPSTrustEngineInvalidKey() throws Exception {
         MockPropertySource propSource = singletonPropertySource(PROP_MDURL, 
diff --git a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/FileBackedHTTPMetadataProviderParserTest.java b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/FileBackedHTTPMetadataProviderParserTest.java
index 93411d2c..d66448b3 100644
--- a/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/FileBackedHTTPMetadataProviderParserTest.java
+++ b/shib-metadata-spring/src/test/java/net/shibboleth/spring/metadata/FileBackedHTTPMetadataProviderParserTest.java
@@ -18,13 +18,17 @@ import static org.testng.Assert.*;
 
 import java.time.Duration;
 import java.util.Iterator;
+import java.util.List;
 
 import org.opensaml.saml.metadata.resolver.MetadataResolver;
 import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver;
 import org.opensaml.saml.metadata.resolver.impl.HTTPMetadataResolver;
+import org.opensaml.saml.metadata.resolver.impl.MetadataResolverTestingSupport;
 import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
 import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.mock.env.MockPropertySource;
+import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import net.shibboleth.shared.testing.RepositorySupport;
@@ -193,6 +197,30 @@ public class FileBackedHTTPMetadataProviderParserTest extends AbstractMetadataPa
         assertNotNull(resolver.resolveSingle(criteriaFor(IDP_ID)));
     }
     
+    @Test public void httpsTrustEngineExplicitKeyParamsMerge() throws Exception {
+        MockPropertySource propSource = singletonPropertySource(PROP_MDURL, 
+                RepositorySupport.buildHTTPSResourceURL(REPO_IDP, ENTITY_XML));
+
+        HTTPMetadataResolver resolver = getBean(HTTPMetadataResolver.class, propSource, "https-trustEngine-explicitKey-params-merge.xml", "beans.xml");
+
+        //Test the merged security params instance
+        assert resolver != null;
+        final HttpClientSecurityParameters securityParams = MetadataResolverTestingSupport.getHttpClientSecurityParameters(resolver);
+        assert securityParams != null;
+        Assert.assertNotNull(securityParams);
+        Assert.assertNotNull(securityParams.getTLSTrustEngine());
+        final List<String> protocols = securityParams.getTLSProtocols();
+        assert protocols != null;
+        Assert.assertNotNull(securityParams.getTLSProtocols());
+        Assert.assertEquals(protocols.size(), 2);
+        Assert.assertTrue(protocols.contains("TLSv1.3"));
+        Assert.assertTrue(protocols.contains("TLSv1.2"));
+        
+        assertEquals(resolver.getId(), "HTTPSEntity");
+        
+        assertNotNull(resolver.resolveSingle(criteriaFor(IDP_ID)));
+    }
+    
     @Test(expectedExceptions=BeanCreationException.class) public void httpsTrustEngineInvalidKey() throws Exception {
         MockPropertySource propSource = singletonPropertySource(PROP_MDURL, 
                 RepositorySupport.buildHTTPSResourceURL(REPO_IDP, ENTITY_XML));
diff --git a/shib-metadata-spring/src/test/java/org/opensaml/saml/metadata/resolver/impl/MetadataResolverTestingSupport.java b/shib-metadata-spring/src/test/java/org/opensaml/saml/metadata/resolver/impl/MetadataResolverTestingSupport.java
new file mode 100644
index 00000000..8de787a1
--- /dev/null
+++ b/shib-metadata-spring/src/test/java/org/opensaml/saml/metadata/resolver/impl/MetadataResolverTestingSupport.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed 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.saml.metadata.resolver.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.saml.metadata.resolver.MetadataResolver;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+
+/**
+ * Testing support for metadata resolvers.
+ */
+public final class MetadataResolverTestingSupport {
+    
+    /**
+     * Get the configured {@link HttpClientSecurityParameters} instance of the resolver, if applicable and available.
+     * 
+     * <p>
+     * This is necessary because the getter for this property is declared 'protected' on the resolver. This class
+     * is located in the same package so as to facilitate access for external callers.
+     * </p>
+     * 
+     * @param resolver the resolver to process
+     * 
+     * @return the security parameters instance, or null
+     */
+    @Nullable
+    public static HttpClientSecurityParameters getHttpClientSecurityParameters(
+            @Nonnull final MetadataResolver resolver) {
+
+        if (resolver instanceof HTTPMetadataResolver httpResolver) {
+            return httpResolver.getHttpClientSecurityParameters();
+        }
+
+        if (resolver instanceof AbstractDynamicHTTPMetadataResolver httpResolver) {
+            return httpResolver.getHttpClientSecurityParameters();
+        }
+        
+        return null;
+    }
+
+}
diff --git a/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/dynamic-https-trustEngine-explicitKey-params-merge.xml b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/dynamic-https-trustEngine-explicitKey-params-merge.xml
new file mode 100644
index 00000000..e9e36f0b
--- /dev/null
+++ b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/dynamic-https-trustEngine-explicitKey-params-merge.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:util="http://www.springframework.org/schema/util"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:c="http://www.springframework.org/schema/c"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:metadata="urn:mace:shibboleth:2.0:metadata"
+    xmlns:security="urn:mace:shibboleth:2.0:security"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+                           urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd
+                           urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd"
+                           
+    default-init-method="initialize" default-destroy-method="destroy" default-lazy-init="true">
+
+    <metadata:MetadataProvider
+        id="dynamicHttpsTrustEngineExplicitKey"
+        xsi:type="metadata:DynamicHTTPMetadataProvider" 
+        httpClientSecurityParametersRef="metadata.HttpClientSecurityParametersWithProtocols">
+        
+        <metadata:TLSTrustEngine>
+            <security:TrustEngine id="trustEngine" xsi:type="security:StaticExplicitKey">
+                <security:Credential xsi:type="security:X509Inline" id="shibboleth.net">
+                    <security:Certificate>
+<!-- The projects LLSS cert -->
+MIIGazCCBFOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMx
+DTALBgNVBAgMBE9oaW8xHjAcBgNVBAoMFVNoaWJib2xldGggQ29uc29ydGl1bTEr
+MCkGA1UEAwwiU2hpYmJvbGV0aCBQcm9qZWN0IEludGVybWVkaWF0ZSBDQTAeFw0x
+ODEyMTExNTE5NDlaFw0zODEyMDYxNTE5NDlaMFoxCzAJBgNVBAYTAlVTMQ0wCwYD
+VQQIDARPaGlvMR4wHAYDVQQKDBVTaGliYm9sZXRoIENvbnNvcnRpdW0xHDAaBgNV
+BAMME3Rlc3Quc2hpYmJvbGV0aC5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDI39TBFEbOkf0Bb2h/qnG4bbJRF5Ga9OBgSAxPsx2PNgVmf1cvJYlq
+uRCzATu3O4PPclomow5VU7hB+umpk2s03FHejUtO8w85qQx7bkSeyfLpMYloX3SD
+AWDFSpw54Tg2Dfja6jYLnE0aYWUCTXjcFJEIrT0QP1Azdk8b9PeKLqGIagECUMzC
+UjmJxEcyqhbe6mB7tdSsBng+R4DRdVdouN4rtHknNuEyAc5eEppGxY33KXhElYol
+4IK6YxAqXI6iQIDdcVxrH061/iKh7qT1bCAEmzeeoS4st4v4oyIhxUk7yUxYOuFc
+NhYUd5U93Ws4P8xPFzcPhD2TIZDAS/bnm2EJ+JxLG6Gp1jhBN5qTpdTPWiG9+Tmm
+HFuYOrSefgZk0edkJhe0dycfV/FWFX2fNrmkpQhyPQzb3ZyZ5mACn020TXDaF5o3
+fX8ndLl4RghTORJs5n51TuLX85DEeZWkJe5f8Hsip1mpmxlMTl9QMqHrN70n5gBi
+uCYo9g/Jw5xoropCq7Jri9K9FWtbORncUIXutsTVo+fXeHZ6IDRoovR004gHHEJ7
+ks46fZQYNbd8bB/mPlCdYiFyJnfUiOu89O5aLqvhrJNgPUhMt/gmhSV7zw+/3/cd
+o7pwWH2h2ObuS8v8gVUZAE04tefqRJZEB0YsWA3DASDT7nVqndOp2QIDAQABo4IB
+KjCCASYwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgEN
+BCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUG3Vg4ubsJVaylBUCPtqVc9mHWfYwgYwGA1UdIwSBhDCBgYAUELzfpij2mkrs
+9B4CEsXYmoN6cKuhZaRjMGExCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARPaGlvMR4w
+HAYDVQQKDBVTaGliYm9sZXRoIENvbnNvcnRpdW0xIzAhBgNVBAMMGlNoaWJib2xl
+dGggUHJvamVjdCBUZXN0IENBggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAww
+CgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAFZQF7KzKGSPieV2eQWbFt30
+kVZzVe/T5UAvrr8n7mRqMfye4QtHHOVM3MHvZv93AXVUQU4PH9KPGtv7poEtwNWk
+7hNbq74z5x5tSvE0EYYI9UMolDL6il+QR5AgLw7YqgMmPPhtm+crmLg8+uMoQDyU
+uSH8ej4rMrdhL2xKlgvL/rhWycpYu1cFLmeolljOZGqr7ITwWJ06BQsLtt4/cyYj
+WiVldHQRZMGAuHLHlX+ukaEg7Gc/N7o936bS5d7AqXwtmtkXiA8An5q5rhncEK1G
+kwUUQN2y5iyx/nD4B2k1IcgFlu/bM4iXZQtmMUtLptUqRssuxS45ukiweiM9UU8n
+WxyxJMzFTctJJ2f/y4Bg5ggsr4WQU/YhoDaQVYxyjXiBt3oT+7eqsoep9HK9xwbG
+xriLzrlao+K3EcKA3vjKGYh15gpEDUbn0Cr5V74TUSdkHjhG7ocaJ5u9/vCS4+AR
+iU5ge2zN6QcwoZKT8+8XGKeXqVc/3hXeXTn3FyvMitPDZsmg8wUhnb/pq5MyKqUA
+bNse4a7oGAeAUGkLf4Q+eLCLSZmL5udrGXdHIffFYqZVcZS+zVWQ1TRfodTDPkFb
+KTz1mcr4KjLNCtplu4CfFpHwC20uk3hPEslOUd+ugj0+HGNH93L7H0WL1GDQoCPh
+RcdRISVwORcD/dit15zD
+                    </security:Certificate>
+                </security:Credential>
+            </security:TrustEngine>
+        </metadata:TLSTrustEngine>
+        
+        <!-- Note: use of the transformRef here is mostly just to facilitate testing. -->
+        <metadata:Template transformRef="digester.SHA1HexLower">
+            %{metadataURL}
+        </metadata:Template>
+
+    </metadata:MetadataProvider>
+    
+    <bean id="metadata.HttpClientSecurityParametersWithProtocols" destroy-method=""
+        class="org.opensaml.security.httpclient.HttpClientSecurityParameters"
+        p:TLSProtocols="#{ {'TLSv1.3', 'TLSv1.2'} }">
+    </bean>
+
+</beans>
+                                   
\ No newline at end of file
diff --git a/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/https-trustEngine-explicitKey-params-merge.xml b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/https-trustEngine-explicitKey-params-merge.xml
new file mode 100644
index 00000000..5ec47115
--- /dev/null
+++ b/shib-metadata-spring/src/test/resources/net/shibboleth/spring/metadata/https-trustEngine-explicitKey-params-merge.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:util="http://www.springframework.org/schema/util"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:c="http://www.springframework.org/schema/c"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:metadata="urn:mace:shibboleth:2.0:metadata"
+    xmlns:security="urn:mace:shibboleth:2.0:security"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
+                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
+                           urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd
+                           urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd"
+                           
+    default-init-method="initialize" default-destroy-method="destroy" default-lazy-init="true">
+
+    <metadata:MetadataProvider
+        id="HTTPSEntity"
+        xsi:type="metadata:FileBackedHTTPMetadataProvider"
+        httpClientSecurityParametersRef="metadata.HttpClientSecurityParametersWithProtocols"
+        backingFile="%{DIR}/spoolhttpstrustengineexplicitkey-params-merge.xml" 
+        metadataURL="%{metadataURL}"> 
+        
+        <metadata:TLSTrustEngine>
+            <security:TrustEngine id="trustEngine" xsi:type="security:StaticExplicitKey">
+                <security:Credential xsi:type="security:X509Inline" id="shibboleth.net">
+                    <security:Certificate>
+<!-- The projects LLSS cert -->
+MIIGazCCBFOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwaTELMAkGA1UEBhMCVVMx
+DTALBgNVBAgMBE9oaW8xHjAcBgNVBAoMFVNoaWJib2xldGggQ29uc29ydGl1bTEr
+MCkGA1UEAwwiU2hpYmJvbGV0aCBQcm9qZWN0IEludGVybWVkaWF0ZSBDQTAeFw0x
+ODEyMTExNTE5NDlaFw0zODEyMDYxNTE5NDlaMFoxCzAJBgNVBAYTAlVTMQ0wCwYD
+VQQIDARPaGlvMR4wHAYDVQQKDBVTaGliYm9sZXRoIENvbnNvcnRpdW0xHDAaBgNV
+BAMME3Rlc3Quc2hpYmJvbGV0aC5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDI39TBFEbOkf0Bb2h/qnG4bbJRF5Ga9OBgSAxPsx2PNgVmf1cvJYlq
+uRCzATu3O4PPclomow5VU7hB+umpk2s03FHejUtO8w85qQx7bkSeyfLpMYloX3SD
+AWDFSpw54Tg2Dfja6jYLnE0aYWUCTXjcFJEIrT0QP1Azdk8b9PeKLqGIagECUMzC
+UjmJxEcyqhbe6mB7tdSsBng+R4DRdVdouN4rtHknNuEyAc5eEppGxY33KXhElYol
+4IK6YxAqXI6iQIDdcVxrH061/iKh7qT1bCAEmzeeoS4st4v4oyIhxUk7yUxYOuFc
+NhYUd5U93Ws4P8xPFzcPhD2TIZDAS/bnm2EJ+JxLG6Gp1jhBN5qTpdTPWiG9+Tmm
+HFuYOrSefgZk0edkJhe0dycfV/FWFX2fNrmkpQhyPQzb3ZyZ5mACn020TXDaF5o3
+fX8ndLl4RghTORJs5n51TuLX85DEeZWkJe5f8Hsip1mpmxlMTl9QMqHrN70n5gBi
+uCYo9g/Jw5xoropCq7Jri9K9FWtbORncUIXutsTVo+fXeHZ6IDRoovR004gHHEJ7
+ks46fZQYNbd8bB/mPlCdYiFyJnfUiOu89O5aLqvhrJNgPUhMt/gmhSV7zw+/3/cd
+o7pwWH2h2ObuS8v8gVUZAE04tefqRJZEB0YsWA3DASDT7nVqndOp2QIDAQABo4IB
+KjCCASYwCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgEN
+BCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4E
+FgQUG3Vg4ubsJVaylBUCPtqVc9mHWfYwgYwGA1UdIwSBhDCBgYAUELzfpij2mkrs
+9B4CEsXYmoN6cKuhZaRjMGExCzAJBgNVBAYTAlVTMQ0wCwYDVQQIDARPaGlvMR4w
+HAYDVQQKDBVTaGliYm9sZXRoIENvbnNvcnRpdW0xIzAhBgNVBAMMGlNoaWJib2xl
+dGggUHJvamVjdCBUZXN0IENBggIQADAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAww
+CgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggIBAFZQF7KzKGSPieV2eQWbFt30
+kVZzVe/T5UAvrr8n7mRqMfye4QtHHOVM3MHvZv93AXVUQU4PH9KPGtv7poEtwNWk
+7hNbq74z5x5tSvE0EYYI9UMolDL6il+QR5AgLw7YqgMmPPhtm+crmLg8+uMoQDyU
+uSH8ej4rMrdhL2xKlgvL/rhWycpYu1cFLmeolljOZGqr7ITwWJ06BQsLtt4/cyYj
+WiVldHQRZMGAuHLHlX+ukaEg7Gc/N7o936bS5d7AqXwtmtkXiA8An5q5rhncEK1G
+kwUUQN2y5iyx/nD4B2k1IcgFlu/bM4iXZQtmMUtLptUqRssuxS45ukiweiM9UU8n
+WxyxJMzFTctJJ2f/y4Bg5ggsr4WQU/YhoDaQVYxyjXiBt3oT+7eqsoep9HK9xwbG
+xriLzrlao+K3EcKA3vjKGYh15gpEDUbn0Cr5V74TUSdkHjhG7ocaJ5u9/vCS4+AR
+iU5ge2zN6QcwoZKT8+8XGKeXqVc/3hXeXTn3FyvMitPDZsmg8wUhnb/pq5MyKqUA
+bNse4a7oGAeAUGkLf4Q+eLCLSZmL5udrGXdHIffFYqZVcZS+zVWQ1TRfodTDPkFb
+KTz1mcr4KjLNCtplu4CfFpHwC20uk3hPEslOUd+ugj0+HGNH93L7H0WL1GDQoCPh
+RcdRISVwORcD/dit15zD
+                    </security:Certificate>
+                </security:Credential>
+            </security:TrustEngine>
+        </metadata:TLSTrustEngine>
+
+    </metadata:MetadataProvider>
+
+    <bean id="metadata.HttpClientSecurityParametersWithProtocols" destroy-method=""
+        class="org.opensaml.security.httpclient.HttpClientSecurityParameters"
+        p:TLSProtocols="#{ {'TLSv1.3', 'TLSv1.2'} }">
+    </bean>
+
+</beans>
+                                   
\ No newline at end of file

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


More information about the commits mailing list