[java-identity-provider] branch main updated: IDP-1664 - Support Module service API

Scott Cantor cantor.2 at osu.edu
Wed Sep 2 17:35:06 UTC 2020


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

scantor pushed a commit to branch main
in repository java-identity-provider.

View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=28150d57dcb952e82e0956e27de57e7b2451623c

The following commit(s) were added to refs/heads/main by this push:
       new  28150d57d IDP-1664 - Support Module service API
28150d57d is described below

commit 28150d57dcb952e82e0956e27de57e7b2451623c
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Sep 2 13:34:55 2020 -0400

    IDP-1664 - Support Module service API
    
    https://issues.shibboleth.net/jira/browse/IDP-1664
    
    Add HTTP/HTTPS source support and adjust tests.
---
 idp-admin-api/pom.xml                              | 11 +++++
 .../shibboleth/idp/module/AbstractIdPModule.java   | 55 +++++++++++++++++++++-
 .../net/shibboleth/idp/module/IdPModuleTest.java   | 39 +++++++++++++--
 idp-admin-api/src/test/resources/logback-test.xml  |  2 +-
 .../net/shibboleth/idp/module/module.properties    |  2 +-
 .../net/shibboleth/idp/module/repo-entity.crt      | 39 +++++++++++++++
 6 files changed, 140 insertions(+), 8 deletions(-)

diff --git a/idp-admin-api/pom.xml b/idp-admin-api/pom.xml
index ef6112f69..d5820914d 100644
--- a/idp-admin-api/pom.xml
+++ b/idp-admin-api/pom.xml
@@ -71,6 +71,17 @@
         <!-- Runtime Dependencies -->
 
         <!-- Test Dependencies -->
+        <dependency>
+            <groupId>net.shibboleth.utilities</groupId>
+            <artifactId>java-support</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${opensaml.groupId}</groupId>
+            <artifactId>opensaml-security-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
 
     </dependencies>
 
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
index 2883d073a..94532d1d1 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
@@ -22,6 +22,8 @@ import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
@@ -36,6 +38,11 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.opensaml.security.httpclient.HttpClientSecuritySupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -225,12 +232,56 @@ public abstract class AbstractIdPModule implements IdPModule {
                 throws IOException {
             
             if (source.startsWith("https://") || source.startsWith("http://")) {
-                // TODO http
-                return null;
+                try {
+                    return connect(moduleContext, new URI(source));
+                } catch (final URISyntaxException e) {
+                    throw new IOException(e);
+                }
             }
             return getClass().getResourceAsStream(source);
         }
 
+        /**
+         * Connect to the given URI and return the HTTP response stream.
+         *
+         * @param moduleContext module context
+         * @param uri resource location
+         * 
+         * @return input stream of response
+         * 
+         * @throws IOException on errors
+         */
+        @Nonnull private InputStream connect(@Nonnull final ModuleContext moduleContext, @Nonnull final URI uri)
+                throws IOException {
+            
+            final HttpClientContext clientContext = HttpClientContext.create();
+            HttpClientSecuritySupport.marshalSecurityParameters(clientContext,
+                    moduleContext.getHttpClientSecurityParameters(), true);
+            HttpResponse response = null;
+            try {
+                log.debug("Module {} fetching HTTP resource {}", getId(), uri);
+                final HttpGet request = new HttpGet(uri);
+                response = moduleContext.getHttpClient().execute(request, clientContext);
+                HttpClientSecuritySupport.checkTLSCredentialEvaluated(clientContext, request.getURI().getScheme());
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new IOException("HTTP request was unsuccessful");
+                }
+                
+                // The response socket should be closed after the stream is closed.
+                final InputStream ret = response.getEntity().getContent();
+                response = null;
+                return ret;
+            } finally {
+                if (response != null && CloseableHttpResponse.class.isInstance(response)) {
+                    try {
+                        CloseableHttpResponse.class.cast(response).close();
+                    } catch (final IOException e) {
+                        log.debug("Error closing HttpResponse", e);
+                    }
+                }
+            }
+        }
+        
         /**
          * Access the destination as a stream.
          * 
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
index dbdffd0b7..75a02ee78 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
@@ -17,24 +17,40 @@ package net.shibboleth.idp.module;
  */
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
+import java.net.URISyntaxException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.attribute.BasicFileAttributes;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
 import java.util.Iterator;
 import java.util.Optional;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
 import java.util.ServiceLoader.Provider;
 
+import org.opensaml.security.credential.impl.StaticCredentialResolver;
+import org.opensaml.security.httpclient.HttpClientSecurityParameters;
+import org.opensaml.security.httpclient.impl.SecurityEnhancedHttpClientSupport;
+import org.opensaml.security.trust.TrustEngine;
+import org.opensaml.security.trust.impl.ExplicitKeyTrustEngine;
+import org.opensaml.security.x509.BasicX509Credential;
+import org.opensaml.security.x509.X509Credential;
+import org.opensaml.security.x509.X509Support;
 import org.testng.Assert;
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.google.common.io.ByteStreams;
+
 import net.shibboleth.idp.module.IdPModule.ModuleResource;
+import net.shibboleth.utilities.java.support.httpclient.HttpClientBuilder;
+import net.shibboleth.utilities.java.support.repository.RepositorySupport;
 
 /**
  * Unit tests exercising module code.
@@ -51,7 +67,7 @@ public class IdPModuleTest {
     private ModuleContext context;
     
     @BeforeMethod
-    public void setUp() throws IOException {
+    public void setUp() throws Exception {
         final ServiceLoader<IdPModule> loader = ServiceLoader.load(IdPModule.class);
         final Optional<Provider<IdPModule>> opt =
                 loader.stream().filter(p -> TestModule.class.equals(p.type())).findFirst();
@@ -61,6 +77,14 @@ public class IdPModuleTest {
         
         testHome = Files.createTempDirectory("test-idp-home-");
         context = new ModuleContext(testHome);
+        
+        final HttpClientBuilder builder = new HttpClientBuilder();
+        builder.setTLSSocketFactory(SecurityEnhancedHttpClientSupport.buildTLSSocketFactory(true, false));
+        context.setHttpClient(builder.buildClient());
+        
+        final HttpClientSecurityParameters params = new HttpClientSecurityParameters();
+        params.setTLSTrustEngine(buildExplicitKeyTrustEngine());
+        context.setHttpClientSecurityParameters(params);
     }
     
     @AfterMethod
@@ -92,7 +116,6 @@ public class IdPModuleTest {
     
     @Test
     public void testBadModules() {
-        
         final ServiceLoader<IdPModule> loader = ServiceLoader.load(IdPModule.class);
 
         Optional<Provider<IdPModule>> opt =
@@ -117,7 +140,6 @@ public class IdPModuleTest {
     
     @Test
     public void testModule() {
-        
         Assert.assertEquals(testModule.getId(), TestModule.class.getName());
         Assert.assertEquals(testModule.getName(), "Test module");
         Assert.assertEquals(testModule.getURL().toString(), "https://wiki.shibboleth.net/confluence/display/IDP4/Home");
@@ -130,7 +152,8 @@ public class IdPModuleTest {
         Assert.assertEquals(resource.getDestination(), Path.of("conf/test.xml"));
         
         resource = resources.next();
-        Assert.assertEquals(resource.getSource(), "/net/shibboleth/idp/module/test.vm");
+        Assert.assertEquals(resource.getSource(),
+                RepositorySupport.buildHTTPSResourceURL("java-identity-provider", "idp-admin-api/src/test/resources/net/shibboleth/idp/module/test.vm"));
         Assert.assertEquals(resource.getDestination(), Path.of("views/test.vm"));
     }
 
@@ -226,4 +249,12 @@ public class IdPModuleTest {
         Assert.assertEquals(vel, VEL_DATA);
     }
     
+    private static TrustEngine<? super X509Credential> buildExplicitKeyTrustEngine() throws URISyntaxException, CertificateException, IOException {
+        
+        final InputStream certStream = IdPModuleTest.class.getResourceAsStream("/net/shibboleth/idp/module/repo-entity.crt");
+        final X509Certificate entityCert = X509Support.decodeCertificate(ByteStreams.toByteArray(certStream));
+        final X509Credential entityCredential = new BasicX509Credential(entityCert);
+        return new ExplicitKeyTrustEngine(new StaticCredentialResolver(entityCredential));
+        
+    }
 }
\ No newline at end of file
diff --git a/idp-admin-api/src/test/resources/logback-test.xml b/idp-admin-api/src/test/resources/logback-test.xml
index 8f891b483..ec68238c5 100644
--- a/idp-admin-api/src/test/resources/logback-test.xml
+++ b/idp-admin-api/src/test/resources/logback-test.xml
@@ -10,7 +10,7 @@
     </appender>
 
     <root>
-        <level value="DEBUG" />
+        <level value="INFO" />
         <appender-ref ref="STDOUT" />
     </root>
     
diff --git a/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
index ad2b75892..feff89f4a 100644
--- a/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
+++ b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/module.properties
@@ -10,7 +10,7 @@ net.shibboleth.idp.module.TestModule.1.src = /net/shibboleth/idp/module/test.xml
 net.shibboleth.idp.module.TestModule.1.dest = conf/test.xml
 net.shibboleth.idp.module.TestModule.1.replace = true
 
-net.shibboleth.idp.module.TestModule.2.src = /net/shibboleth/idp/module/test.vm
+net.shibboleth.idp.module.TestModule.2.src = https://test.shibboleth.net/git/view/?p=java-identity-provider.git&a=blob_plain&f=idp-admin-api/src/test/resources/net/shibboleth/idp/module/test.vm&hb=HEAD
 net.shibboleth.idp.module.TestModule.2.dest = views/test.vm
 
 # Broken modules due to dangerous resources
diff --git a/idp-admin-api/src/test/resources/net/shibboleth/idp/module/repo-entity.crt b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/repo-entity.crt
new file mode 100644
index 000000000..b9834258f
--- /dev/null
+++ b/idp-admin-api/src/test/resources/net/shibboleth/idp/module/repo-entity.crt
@@ -0,0 +1,39 @@
+## This is the current *.shibboleth.net wildcard cert, expires Jan 2019.
+
+-----BEGIN CERTIFICATE-----
+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
+-----END CERTIFICATE-----

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


More information about the commits mailing list