[java-idp-integration-tests] branch main updated: Add consent test with a Postgres storage service

Tom Zeller tzeller at dragonacea.biz
Thu Oct 3 02:45:37 UTC 2024


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

tzeller pushed a commit to branch main
in repository java-idp-integration-tests.

View the commit online:
http://git.shibboleth.net/view/?p=java-idp-integration-tests.git;a=commit;h=399b603e14cd3030f6ed84d3e997ed2821353375

The following commit(s) were added to refs/heads/main by this push:
     new 399b603  Add consent test with a Postgres storage service
399b603 is described below

commit 399b603e14cd3030f6ed84d3e997ed2821353375
Author: Tom Zeller <tzeller at dragonacea.biz>
AuthorDate: Wed Oct 2 21:45:27 2024 -0500

    Add consent test with a Postgres storage service
    
    https://shibboleth.atlassian.net/browse/IDP-2323
---
 pom.xml                                            |  33 ++++
 .../shibboleth/idp/integration/tests/BaseTest.java | 111 +++++++++++
 .../tests/clientstorage/ClientStorageTest.java     |  46 +----
 .../tests/saml2/PostgresConsentTest.java           | 218 +++++++++++++++++++++
 .../idp/integration/tests/postgres/create-table.sh |   8 +
 .../integration/tests/postgres/docker-compose.yml  |  15 ++
 .../idp/integration/tests/postgres/global.xml      |   9 +
 7 files changed, 399 insertions(+), 41 deletions(-)

diff --git a/pom.xml b/pom.xml
index d5ad865..02c1371 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,6 +51,12 @@
         <!-- Apache Commons Net -->
         <commons-net.version>3.11.1</commons-net.version>
 
+        <!-- PostgreSQL driver -->
+        <postgresql.version>42.7.4</postgresql.version>
+
+        <!-- HikariCP driver -->
+        <hikaricp.version>5.1.0</hikaricp.version>
+
         <!-- Directory where the IdP and Servlet container are unpacked -->
         <test-distributions.directory>${project.basedir}/test-distributions</test-distributions.directory>
 
@@ -152,6 +158,33 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- Testcontainers Postgres support : consent storage test -->
+        <dependency>
+            <groupId>org.testcontainers</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${testcontainers.version}</version>
+            <scope>test</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- Postgres JDBC driver : consent storage test -->
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>${postgresql.version}</version>
+            <scope>test</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <!-- HikariCP : consent storage test -->
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+            <version>${hikaricp.version}</version>
+            <scope>test</scope>
+            <optional>true</optional>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/BaseTest.java b/src/test/java/net/shibboleth/idp/integration/tests/BaseTest.java
index 5958d26..5e4e0ca 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/BaseTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/BaseTest.java
@@ -3445,4 +3445,115 @@ public abstract class BaseTest {
     public static boolean isChrome() {
         return System.getProperty("SELENIUM_BROWSER").toLowerCase().equals("chrome");
     }
+
+    /**
+     * Add testbed storage servlet to IdP.
+     * 
+     * @throws IOException
+     *             if an error occurs
+     */
+    public void setUpStorageServlet() throws IOException  {
+
+        final Path pathToEditWebapp = pathToIdPHome.resolve("edit-webapp").toAbsolutePath();
+        log.debug("Path to edit-webapp '{}'", pathToEditWebapp);
+        Assert.assertTrue(pathToEditWebapp.toFile().exists(), "Path to edit-webapp " + pathToEditWebapp + " should exist");
+
+        // Extract web.xml from idp.war
+        if (isWindows()) {
+            logProcess(Runtime.getRuntime().exec("jar -xvf ..\\war\\idp.war WEB-INF\\web.xml", null, pathToEditWebapp.toFile()), "jar :");
+        } else {
+            logProcess(Runtime.getRuntime().exec("jar -xvf ../war/idp.war WEB-INF/web.xml", null, pathToEditWebapp.toFile()), "jar :");
+        }
+
+        final Path pathToCustomWebXML = pathToEditWebapp.resolve("WEB-INF").resolve("web.xml");
+        log.debug("Path to custom web.xml '{}'", pathToCustomWebXML);
+        Assert.assertTrue(pathToCustomWebXML.toFile().exists(), "Path to web.xml " + pathToCustomWebXML + " should exist");
+
+        final String oldText = "</web-app>";
+
+        final StringBuilder newText = new StringBuilder();
+        newText.append("\n");
+        newText.append("<!-- The /storage app space. Interact with storage services via HTTP. -->\n");
+        newText.append("<servlet>\n");
+        newText.append("    <servlet-name>storage</servlet-name>\n");
+        newText.append("    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n");
+        newText.append("    <init-param>\n");
+        newText.append("        <param-name>contextConfigLocation</param-name>\n");
+        newText.append("        <param-value>classpath:/system/conf/storage-context.xml</param-value>\n");
+        newText.append("     </init-param>\n");
+        newText.append("     <load-on-startup>1</load-on-startup>\n");
+        newText.append("</servlet>\n");
+        newText.append("<servlet-mapping>\n");
+        newText.append("    <servlet-name>storage</servlet-name>\n");
+        newText.append("    <url-pattern>/storage/*</url-pattern>\n");
+        newText.append("</servlet-mapping>\n");
+        newText.append("</web-app>\n");
+
+        replaceFile(pathToCustomWebXML, oldText, newText.toString());
+
+        buildWAR();
+    }
+
+    /**
+     * Copy Maven dependency to edit-webapp/WEB-INF/lib.
+     * 
+     * @param groupId
+     *            groupId of Maven dependency
+     * @param artifactId
+     *            artifactId of Maven dependency
+     * @throws IOException
+     *             if an error occurs
+     */
+    public void copyDependency(@Nonnull final String groupId, @Nonnull final String artifactId) throws IOException {
+
+        final Path pathToEditWebappWebInfLib = pathToIdPHome.resolve(Paths.get("edit-webapp", "WEB-INF", "lib"));
+
+        Files.createDirectories(pathToEditWebappWebInfLib);
+
+        final String[] commands = new String[] { //
+                "mvn", //
+                "dependency:copy-dependencies", //
+                "-DincludeGroupIds=" + groupId, //
+                "-DincludeArtifactIds=" + artifactId, //
+                "-DoutputDirectory=" + pathToEditWebappWebInfLib.toAbsolutePath().toString() };
+
+        final Process process = new ProcessBuilder() //
+                .command(commands)
+                .redirectErrorStream(true)
+                .start();
+
+        logProcess(process, "Copy dependency :");
+    }
+
+    /**
+     * Download a Maven artifact to edit-webapp/WEB-INF/lib.
+     * 
+     * @param artifact
+     *            string of the form
+     *            groupId:artifactId:version[:packaging[:classifier]] for example,
+     *            "org.postgresql:postgresql:LATEST"
+     * @throws IOException
+     *             if an error occurs
+     */
+    public void downloadArtifact(@Nonnull final String artifact) throws IOException {
+
+        final Path pathToEditWebappWebInfLib = pathToIdPHome.resolve(Paths.get("edit-webapp", "WEB-INF", "lib"));
+
+        Files.createDirectories(pathToEditWebappWebInfLib);
+
+        final String[] commands = new String[] { //
+                "mvn", //
+                "dependency:copy", //
+                "-Dartifact=" + artifact, //
+                "-Dtransitive=false", //
+                "-DoutputDirectory=" + pathToEditWebappWebInfLib.toAbsolutePath().toString() };
+
+        final Process process = new ProcessBuilder() //
+                .command(commands)
+                .redirectErrorStream(true)
+                .start();
+
+        logProcess(process, "Download artifact :");
+    }
+
 }
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/clientstorage/ClientStorageTest.java b/src/test/java/net/shibboleth/idp/integration/tests/clientstorage/ClientStorageTest.java
index a83960b..432c28d 100644
--- a/src/test/java/net/shibboleth/idp/integration/tests/clientstorage/ClientStorageTest.java
+++ b/src/test/java/net/shibboleth/idp/integration/tests/clientstorage/ClientStorageTest.java
@@ -17,6 +17,7 @@
 
 package net.shibboleth.idp.integration.tests.clientstorage;
 
+import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.time.Duration;
@@ -69,49 +70,12 @@ public class ClientStorageTest extends BaseTest {
     /**
      * Add testbed storage servlet to IdP.
      * 
-     * @throws Exception if an error occurs
+     * @throws IOException
+     *             if an error occurs
      */
     @BeforeClass(enabled = true, dependsOnMethods = {"setUpIdPPaths"})
-    public void setUpStorageServlet() throws Exception {
-
-        final Path pathToEditWebapp = pathToIdPHome.resolve("edit-webapp").toAbsolutePath();
-        log.debug("Path to edit-webapp '{}'", pathToEditWebapp);
-        Assert.assertTrue(pathToEditWebapp.toFile().exists(), "Path to edit-webapp " + pathToEditWebapp + " should exist");
-
-        // Extract web.xml from idp.war
-        if (isWindows()) {
-            logProcess(Runtime.getRuntime().exec("jar -xvf ..\\war\\idp.war WEB-INF\\web.xml", null, pathToEditWebapp.toFile()), "jar :");
-        } else {
-            logProcess(Runtime.getRuntime().exec("jar -xvf ../war/idp.war WEB-INF/web.xml", null, pathToEditWebapp.toFile()), "jar :");
-        }
-
-        final Path pathToCustomWebXML = pathToEditWebapp.resolve("WEB-INF").resolve("web.xml");
-        log.debug("Path to custom web.xml '{}'", pathToCustomWebXML);
-        Assert.assertTrue(pathToCustomWebXML.toFile().exists(), "Path to web.xml " + pathToCustomWebXML + " should exist");
-
-        final String oldText = "</web-app>";
-
-        final StringBuilder newText = new StringBuilder();
-        newText.append("\n");
-        newText.append("<!-- The /storage app space. Interact with storage services via HTTP. -->\n");
-        newText.append("<servlet>\n");
-        newText.append("    <servlet-name>storage</servlet-name>\n");
-        newText.append("    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>\n");
-        newText.append("    <init-param>\n");
-        newText.append("        <param-name>contextConfigLocation</param-name>\n");
-        newText.append("        <param-value>classpath:/system/conf/storage-context.xml</param-value>\n");
-        newText.append("     </init-param>\n");
-        newText.append("     <load-on-startup>1</load-on-startup>\n");
-        newText.append("</servlet>\n");
-        newText.append("<servlet-mapping>\n");
-        newText.append("    <servlet-name>storage</servlet-name>\n");
-        newText.append("    <url-pattern>/storage/*</url-pattern>\n");
-        newText.append("</servlet-mapping>\n");
-        newText.append("</web-app>\n");
-
-        replaceFile(pathToCustomWebXML, oldText, newText.toString());
-
-        buildWAR();
+    public void setUpStorageServlet() throws IOException  {
+        super.setUpStorageServlet();
     }
 
     /**
diff --git a/src/test/java/net/shibboleth/idp/integration/tests/saml2/PostgresConsentTest.java b/src/test/java/net/shibboleth/idp/integration/tests/saml2/PostgresConsentTest.java
new file mode 100644
index 0000000..5ce4713
--- /dev/null
+++ b/src/test/java/net/shibboleth/idp/integration/tests/saml2/PostgresConsentTest.java
@@ -0,0 +1,218 @@
+/*
+ * 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 net.shibboleth.idp.integration.tests.saml2;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testcontainers.containers.PostgreSQLContainer;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.integration.tests.util.testng.annotation.LinuxOnly;
+
+/** Test consent with a Postgres storage service. */
+public class PostgresConsentTest extends AbstractSAML2IntegrationTest {
+
+    /** Class logger. */
+    @Nonnull
+    private final Logger log = LoggerFactory.getLogger(PostgresConsentTest.class);
+
+    /** Postgres container. */
+    private PostgreSQLContainer<?> postgresContainer;
+
+    @BeforeClass
+    public void setUpURLs() throws Exception {
+
+        startFlowURLPath = "/sp/SAML2/InitSSO/Redirect";
+
+        loginPageURLPath = "/idp/profile/SAML2/Redirect/SSO";
+
+        responsePageURLPath = "/sp/SAML2/POST/ACS";
+
+        isPassiveRequestURLPath = "/sp/SAML2/InitSSO/Passive";
+
+        forceAuthnRequestURLPath = "/sp/SAML2/InitSSO/ForceAuthn";
+
+        idpLogoutURLPath = "/idp/profile/SAML2/Redirect/SLO";
+
+        spLogoutURLPath = "/sp/SAML2/Redirect/SLO";
+
+        logoutTransientIDInputID = "InitSLO_Redirect";
+    }
+
+    /**
+     * Set up Postgres storage service.
+     * 
+     * Install JDBC Plugin.
+     * 
+     * Add testbed storage servlet to the IdP.
+     * 
+     * Add Postgres and HikariCP drivers to the IdP.
+     * 
+     * @throws IOException
+     *             if an error occurs
+     */
+    @BeforeClass
+    public void setUpPostgresStorageService() throws IOException  {
+
+        installPlugin("net.shibboleth.plugin.storage.jdbc");
+
+        setUpStorageServlet();
+
+        downloadPostgresqlDriver();
+
+        downloadHikariCPDriver();
+
+        buildWAR();
+
+        enablePostgresStorageService();
+
+        replaceIdPProperty("idp.consent.StorageService", "my.JDBCStorageService");
+    }
+
+    /**
+     * Download latest Postgres driver to edit-webapp/WEB-INF/lib.
+     * 
+     * @throws IOException
+     *             if an error occurs
+     */
+    public void downloadPostgresqlDriver() throws IOException {
+        copyDependency("org.postgresql", "postgresql");
+    }
+
+    /**
+     * Download latest HikariCP driver to edit-webapp/WEB-INF/lib.
+     * 
+     * @throws IOException
+     *             if an error occurs
+     */
+    public void downloadHikariCPDriver() throws IOException {
+        copyDependency("com.zaxxer", "HikariCP");
+    }
+
+    /**
+     * Enable JDBC storage using Postgres and HikariCP.
+     * 
+     * Enables beans from
+     * "/net/shibboleth/idp/integration/tests/postgres/global.xml".
+     * 
+     * @throws IOException
+     *             if an error occurs
+     * @throws URISyntaxException
+     *             if an error occurs
+     */
+    public void enablePostgresStorageService() throws IOException {
+        try {
+            final Path pathToGlobalXML = pathToIdPHome.resolve(Paths.get("conf", "global.xml"));
+
+            assert pathToGlobalXML.toAbsolutePath().toFile().exists() : "Path to global.xml not found";
+
+            final String oldText = "</beans>";
+
+            final String resourcePath = "/net/shibboleth/idp/integration/tests/postgres/global.xml";
+
+            final Path pathToSnippetForGlobalXML = Paths.get(this.getClass().getResource(resourcePath).toURI());
+
+            final String newText = Files.readString(pathToSnippetForGlobalXML);
+
+            replaceFile(pathToGlobalXML, oldText, newText + "\n" + oldText);
+
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Start Postgres container.
+     * 
+     * Creates "StorageRecords" table.
+     * 
+     * @return the JDBC URL to connect to the Postgres container
+     * @throws IOException 
+     */
+    @BeforeMethod()
+    public String startPostgres() throws IOException {
+
+        final String initScriptPath = "net/shibboleth/idp/integration/tests/postgres/create-table.sh";
+
+        postgresContainer = new PostgreSQLContainer<>("postgres").withInitScript(initScriptPath);
+
+        log.debug("{} Starting Postgres ...");
+        postgresContainer.start();
+        log.debug("{} Started Postgres : '{}'", postgresContainer.getContainerName());
+
+        final String jdbcUrl = postgresContainer.getJdbcUrl();
+        log.info("{} Postgres JDBC URL : '{}'", jdbcUrl);
+
+        replaceIdPHomeFile(Paths.get("conf", "global.xml"), "jdbc:postgresql://localhost:\\d+/test\\?loggerLevel=OFF", jdbcUrl);
+
+        return jdbcUrl;
+    }
+
+    /**
+     * Stop Postgres.
+     */
+    @AfterMethod()
+    public void stopPostgres() {
+        if (postgresContainer != null) {
+            log.debug("{} Stopping Postgres ...");
+            postgresContainer.stop();
+            log.debug("{} Postgres stopped");
+        }
+    }
+
+    @Test
+    @LinuxOnly
+    public void testSSOReleaseAllAttributes() throws Exception {
+        super.testSSOReleaseAllAttributes();
+    }
+
+    @Test
+    @LinuxOnly
+    public void testSSOReleaseOneAttribute() throws Exception {
+        super.testSSOReleaseOneAttribute();
+    }
+
+    @Test
+    @LinuxOnly
+    public void testSSODoNotRememberConsent() throws Exception {
+        super.testSSODoNotRememberConsent();
+    }
+
+    @Test
+    @LinuxOnly
+    public void testSSOGlobalConsent() throws Exception {
+        super.testSSOGlobalConsent();
+    }
+
+    @Test
+    @LinuxOnly
+    public void testSSOTermsOfUse() throws Exception {
+        super.testSSOTermsOfUse();
+    }
+}
diff --git a/src/test/resources/net/shibboleth/idp/integration/tests/postgres/create-table.sh b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/create-table.sh
new file mode 100644
index 0000000..8144735
--- /dev/null
+++ b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/create-table.sh
@@ -0,0 +1,8 @@
+CREATE TABLE StorageRecords (
+  context varchar(255) NOT NULL,
+  id varchar(255) NOT NULL,
+  expires bigint DEFAULT NULL,
+  value text NOT NULL,
+  version bigint NOT NULL,
+  PRIMARY KEY (context, id)
+);
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/idp/integration/tests/postgres/docker-compose.yml b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/docker-compose.yml
new file mode 100644
index 0000000..77cfacf
--- /dev/null
+++ b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/docker-compose.yml
@@ -0,0 +1,15 @@
+services:
+
+  db:
+    image: postgres
+    restart: always
+    # set shared memory limit when using docker-compose
+    shm_size: 128mb
+    environment:
+        POSTGRES_USER: test
+        POSTGRES_PASSWORD: test
+        POSTGRES_DB: test
+    ports:
+        - 5432:5432
+    volumes:
+        - ./create-table.sql:/docker-entrypoint-initdb.d/create-table.sql
\ No newline at end of file
diff --git a/src/test/resources/net/shibboleth/idp/integration/tests/postgres/global.xml b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/global.xml
new file mode 100644
index 0000000..0bb3e75
--- /dev/null
+++ b/src/test/resources/net/shibboleth/idp/integration/tests/postgres/global.xml
@@ -0,0 +1,9 @@
+    <bean id="my.dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close" lazy-init="true"
+       p:jdbcUrl="jdbc:postgresql://localhost:5432/test?loggerLevel=OFF"
+       p:username="test"
+       p:password="test" />
+
+    <bean id="my.JDBCStorageService" parent="shibboleth.JDBCStorageService"
+          p:dataSource-ref="my.dataSource"
+          p:transactionIsolation="4"
+          p:retryableErrors="40001"/>
\ 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