[java-identity-provider] 03/04: IDP-2140 Move forward Windows Installer to V5

Rod Widdowson rdw at steadingsoftware.com
Tue Jul 11 15:59:07 UTC 2023


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

rdw 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=05ba2a360ec7203b6b964ad14ae94bff94fcb08e

commit 05ba2a360ec7203b6b964ad14ae94bff94fcb08e
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Fri Jul 7 11:31:16 2023 +0100

    IDP-2140 Move forward Windows Installer to V5
    
    https://shibboleth.atlassian.net/browse/IDP-2140
    
    Use a java program not Ant to configure jetty base.
---
 .../idp/installer/impl/FinalizeJettyBase.java      | 201 +++++++++++++++++++++
 idp-installer/src/main/wix/ShibbolethIdP-main.wxs  |  12 +-
 idp-installer/src/main/wix/scripts/ant-jetty.xml   | 117 ------------
 .../src/main/wix/scripts/shib_write_configs.vbs    |  59 ------
 4 files changed, 207 insertions(+), 182 deletions(-)

diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/FinalizeJettyBase.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/FinalizeJettyBase.java
new file mode 100644
index 000000000..64ff64b03
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/FinalizeJettyBase.java
@@ -0,0 +1,201 @@
+/*
+ * 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.installer.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Properties;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.idp.installer.InstallerSupport;
+import net.shibboleth.idp.installer.PropertiesWithComments;
+
+/**
+ * Small class to do the post install work on an embedded jetty-base.
+ * (primarily generated by the windows explorer but not tied to that).
+ */
+public class FinalizeJettyBase {
+
+    /** The IdP Installation dir. */
+    @Nonnull private final Path idpHome;
+
+    /** The jetty-base dir. */
+    @Nonnull private final Path jettyBase;
+
+
+    /** Constructor.
+     * @throws IOException */
+    private FinalizeJettyBase() throws IOException {
+        final String home = System.getProperty("idp.home");
+        if (home == null) {
+            System.err.println("idp.home not specified");
+            throw new IOException("idp.home not specified");
+        }
+        Path p = Path.of(home);
+        assert p!=null;
+        idpHome = p;
+        if (!Files.exists(idpHome) || !Files.isDirectory(idpHome)) {
+            final String msg = "'" + home + "' does not exist or is not a directory";
+            System.err.println(msg);
+            throw new IOException(msg);
+        }
+        p = idpHome.resolve("jetty-base");
+        assert p!=null;
+        jettyBase = p;
+        if (!Files.exists(jettyBase) || !Files.isDirectory(jettyBase)) {
+            final String msg = "'" + home + "/jetty-base' does not exist or is not a directory";
+            System.err.println(msg);
+            throw new IOException(msg);
+        }
+        p = jettyBase.resolve("start.d.dist");
+        if (!Files.exists(p) || !Files.isDirectory(p)) {
+            final String msg = "'" + home + "/jetty-base/start.d.dist' does not exist or is not a directory";
+            System.err.println(msg);
+            throw new IOException(msg);
+        }
+
+    }
+
+    /** Do the work associated with finalizing this install.
+     * @throws IOException if we encounter other issues
+     */
+    private void execute() throws IOException {
+        createDirectories();
+        final Path idpIni = jettyBase.resolve("start.d").resolve("idp.ini");
+        if (Files.exists(idpIni)) {
+            updateIdPini();
+        } else {
+            createP12IdPini();
+        }
+        final Path systemIniSrc = jettyBase.resolve("start.d.dist").resolve("idp-system.ini");
+        final Path dest = jettyBase.resolve("start.d").resolve("idp-system.ini");
+        assert systemIniSrc!=null && dest!=null;
+        copyFile(systemIniSrc, dest);
+        reprotect();
+    }
+
+    /** if they don't exists create
+     * @throws IOException if we failed to create a directory
+     */
+    private void createDirectories() throws IOException {
+        Files.createDirectories(jettyBase.resolve("start.d"));
+        Files.createDirectories(jettyBase.resolve("logs"));
+        Files.createDirectories(idpHome.resolve("static"));
+    }
+
+    /** Create the jetty.sslContext.keyStorePath as a copy
+     * from the idp.backchannel.keyStorePath file.
+     * The create start.d/idp.ini from the start.d.dist/idp.ini.windows
+     * but replacing the two password properties
+     * @throws IOException if we trip up.
+     */
+    private void createP12IdPini() throws IOException {
+        final Path credentials = idpHome.resolve("credentials");
+        final Path backChannelKeyStore = credentials.resolve("idp-backchannel.p12");
+        final Path sslKeyStore = credentials.resolve("idp-userfacing.p12");
+        assert backChannelKeyStore!=null && sslKeyStore!=null;
+
+        if (!Files.exists(backChannelKeyStore)) {
+            final String msg = backChannelKeyStore.toString() + " Does not exist";
+            System.err.println(msg);
+            throw new IOException(msg);
+        }
+        if (Files.exists(sslKeyStore)) {
+            final String msg = sslKeyStore.toString() + " Exists";
+            System.err.println(msg);
+            throw new IOException(msg);
+        }
+
+        copyFile(backChannelKeyStore, sslKeyStore);
+
+        final Properties passwords = new Properties();
+        try (final FileInputStream in = new FileInputStream(credentials.resolve("secrets.properties").toFile())) {
+            passwords.load(in);
+        }
+        final String p12Pass = passwords.getProperty("idp.backchannel.keyStorePassword");
+        final Properties replace = new Properties(2);
+        replace.setProperty("idp.backchannel.keyStorePassword", p12Pass);
+        replace.setProperty("jetty.sslContext.keyStorePassword", p12Pass);
+
+        final PropertiesWithComments idpIni = new PropertiesWithComments();
+        final File inputIni = jettyBase.resolve("start.d.dist").resolve("idp.ini.windows").toFile();
+        final File outputIni = jettyBase.resolve("start.d").resolve("idp.ini").toFile();
+        try (final FileInputStream in = new FileInputStream(inputIni); final FileOutputStream out = new FileOutputStream(outputIni)) {
+            idpIni.load(in);
+            idpIni.replaceProperties(replace);
+            idpIni.store(out);
+        }
+    }
+
+    /** Rewrite any property names needed.
+     * @throws IOException
+     */
+    private void updateIdPini() throws IOException {
+        final PropertiesWithComments props = new PropertiesWithComments();
+        final File idpIni = jettyBase.resolve("start.d").resolve("idp.ini").toFile();
+        final File replacementFile = jettyBase.resolve("start.d.dist").resolve("idp.ini.rewrite.property.names").toFile();
+        try (final FileInputStream in = new FileInputStream(idpIni); final FileInputStream replacementStream = new FileInputStream(replacementFile)) {
+            props.loadNameReplacement(replacementStream);
+            props.load(in);
+        }
+        try (final FileOutputStream out = new FileOutputStream(idpIni)) {
+            props.store(out);
+        }
+    }
+
+    /** Copy one file to another.
+     * @param fromFile from
+     * @param toFile to
+     * @throws IOException if it fails.
+     */
+    private void copyFile(@Nonnull final Path fromFile, @Nonnull final Path toFile) throws IOException {
+        try (final FileOutputStream out = new FileOutputStream(toFile.toFile())) {
+            Files.copy(fromFile, out);
+        }
+    }
+
+    /** lock down the jetty base directory. */
+    private void reprotect() {
+        final Path libDir = jettyBase.resolve("lib");
+        assert libDir!=null;
+        InstallerSupport.setReadOnlyDir(libDir, false);
+        InstallerSupport.setMode(libDir, "444", "*");
+        final Path etcDir = jettyBase.resolve("etc");
+        assert etcDir!=null;
+        InstallerSupport.setReadOnlyDir(etcDir, false);
+        InstallerSupport.setMode(etcDir, "444", "*");
+        final Path webapps = jettyBase.resolve("webapps");
+        assert webapps!=null;
+        InstallerSupport.setReadOnlyDir(webapps, false);
+        InstallerSupport.setMode(webapps, "444", "*");
+    }
+
+    /** Main entry.
+     * @param args As supplied
+     * @throws IOException if there is a problem with the jetty base.
+     */
+    public static void main(String[] args) throws IOException {
+        new FinalizeJettyBase().execute();
+    }
+
+}
diff --git a/idp-installer/src/main/wix/ShibbolethIdP-main.wxs b/idp-installer/src/main/wix/ShibbolethIdP-main.wxs
index 8bcb38ab2..d3320243f 100644
--- a/idp-installer/src/main/wix/ShibbolethIdP-main.wxs
+++ b/idp-installer/src/main/wix/ShibbolethIdP-main.wxs
@@ -162,9 +162,9 @@
         <CustomAction Id="RunIdpInstall" Directory="ProgramFilesFolder" ExeCommand="[QtIdpInstall]" Execute="deferred" Impersonate="no" />
         <CustomAction Id="QtIdpInstall" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" />
 
-        <CustomAction Id="SetJettyAnt" Property="QtJettyAnt" Value=""[JAVA_EXECUTABLE]" -cp "[INSTALLDIR]\bin\lib\*;[INSTALLDIR]\dist\webapp\WEB-INF\lib\*" org.apache.tools.ant.Main -e -f "[INSTALLDIR]\bin\ant-jetty.xml" -Djetty.property.file=jetty.install.properties install" />
-        <CustomAction Id="RunJettyAnt" Directory="INSTALLDIR" ExeCommand="[QtJettyAnt]" Execute="deferred" Impersonate="no" />
-        <CustomAction Id="QtJettyAnt" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" />
+        <CustomAction Id="SetFinalizeJetty" Property="QtFinalizeJetty" Value=""[JAVA_EXECUTABLE]" -cp "[IDPDISTDIR]\bin\lib\*;[IDPDISTDIR]\dist\webapp\WEB-INF\lib\*" -Didp.home=[INSTALLDIR] net.shibboleth.idp.installer.impl.FinalizeJettyBase" />
+        <CustomAction Id="RunFinalizeJetty" Directory="INSTALLDIR" ExeCommand="[QtFinalizeJetty]" Execute="deferred" Impersonate="no" />
+        <CustomAction Id="QtFinalizeJetty" BinaryKey="WixCA" DllEntry="CAQuietExec" Execute="deferred" Impersonate="no" />
 
         <CustomAction Id="SetJavaJvmMx" Property="JAVA_JVMMX" Value="#2048" />
 
@@ -257,9 +257,9 @@
             <Custom Action="SetIdpInstall3" After="SetIdpInstall2">NOT Installed</Custom>
             <Custom Action="RunIdpInstall" After="SetIdpInstall3">(NOT Installed) AND DEBUG_INSTALL</Custom>
             <Custom Action="QtIdpInstall" After="SetIdpInstall3">(NOT Installed) AND (NOT DEBUG_INSTALL)</Custom>
-            <Custom Action="SetJettyAnt" After="RunIdpInstall">(NOT Installed) AND INSTALL_JETTY</Custom>
-            <Custom Action="RunJettyAnt" After="SetJettyAnt">(NOT Installed) AND INSTALL_JETTY AND DEBUG_INSTALL</Custom>
-            <Custom Action="QtJettyAnt" After="SetJettyAnt">(NOT Installed) AND INSTALL_JETTY AND (NOT DEBUG_INSTALL)</Custom>
+            <Custom Action="SetFinalizeJetty" After="RunIdpInstall">(NOT Installed) AND INSTALL_JETTY</Custom>
+            <Custom Action="RunFinalizeJetty" After="SetFinalizeJetty">(NOT Installed) AND INSTALL_JETTY AND DEBUG_INSTALL</Custom>
+            <Custom Action="QtFinalizeJetty" After="SetFinalizeJetty">(NOT Installed) AND INSTALL_JETTY AND (NOT DEBUG_INSTALL)</Custom>
 
         </InstallExecuteSequence>
 
diff --git a/idp-installer/src/main/wix/scripts/ant-jetty.xml b/idp-installer/src/main/wix/scripts/ant-jetty.xml
deleted file mode 100644
index 8a4b315b0..000000000
--- a/idp-installer/src/main/wix/scripts/ant-jetty.xml
+++ /dev/null
@@ -1,117 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project name="Shibboleth IdP V3 - Jetty Container" basedir=".." default="install">
-
-    <!--  This file is for automatic configuration of Jetty, primarily from the MSI installer.
-
-        Names and APIS *may* change in the future, please enter an RFI if you wish to use this
-        in production outside the MSI installer.
-
-        TARGETS:
-
-                The only top level target is "install".  This in turn calls subsidiary targets.
-
-        PROPERTIES:
-
-            The following properties are used.  They have to be provided on the command line or
-            via the property file.
-
-            jetty.property.file: Name of a file to fill in all or some of the below. This file is deleted after processing.
-            jetty.merge.properties: The name of a property file to merge with idp.ini.  This file is deleted after processing.
-            idp.host.name: The host name.
-            idp.uri.subject.alt.name: If we are creating certificates.
-            idp.target.dir: where to install to.
-
-            idp.keystore.password: password to use on the PKCS12 file for a user-facing TLS credential,
-                which will be created if one does not already exist either in JKS or PKCS12 form.
-                This value must also have been written to the merge properties file as
-                jetty.browser.keystore.password.
-
-            jetty.no.tidy: Do not delete the two above files (debug only)
-
-    -->
-
-    <taskdef resource="net/shibboleth/idp/installer/ant.xml" />
-
-    <target name="install" depends="init, properties, keystores, directories, copyinis, reprotect, tidy" />
-
-    <target name="init">
-        <tstamp />
-        <hostinfo />
-    </target>
-
-    <target name="properties">
-        <property file="${jetty.property.file}" />
-        <available property="idp.ini.present" file="${idp.target.dir}/jetty-base/start.d/idp.ini" />
-        <available property="idp.jks.present" file="${idp.target.dir}/credentials/idp.jks" />
-        <available property="idp.userfacing.p12.present" file="${idp.target.dir}/credentials/idp-userfacing.p12" />
-        <condition property="generate.userfacing.p12">
-            <!-- Generate the pkcs12 keystore if neither the JKS nor the P12 exist -->
-            <not>
-                <or>
-                    <istrue value="${idp.jks.present}" />
-                    <istrue value="${idp.userfacing.p12.present}" />
-                </or>
-            </not>
-        </condition>
-    </target>
-
-    <!-- Handle keystores -->
-    <target name="keystores" depends="jks, gen-userfacing" />
-
-    <target name="jks" if="idp.jks.present">
-        <!-- Note that this password is the old default for QI.  This will overwrite what we may have put in when the merge file was created. -->
-        <echo file="${jetty.merge.properties}" append="yes">
-                jetty.backchannel.keystore.type=JKS
-                jetty.browser.keystore.type=JKS
-                jetty.backchannel.keystore.password= SeCrEt
-                jetty.browser.keystore.password= SeCrEt
-                jetty.backchannel.keystore.path= ${idp.target.dir}/credentials/idp.jks
-                jetty.browser.keystore.path= ${idp.target.dir}/credentials/idp.jks
-        </echo>
-    </target>
-
-    <target name="gen-userfacing" if="generate.userfacing.p12">
-        <selfsignedcert hostname="${idp.host.name}" keystoreFile="${idp.target.dir}/credentials/idp-userfacing.p12" keystorePassword="${idp.keystore.password}" uriSubjectAltNames="${idp.uri.subject.alt.name}" />
-    </target>
-
-    <target name="directories">
-        <mkdir dir="jetty-base/start.d" />
-        <mkdir dir="jetty-base/logs" />
-        <mkdir dir="static" />
-    </target>
-
-    <target name="copyinis" depends="properties, directories, copyidpini, rewriteidpini">
-        <copy file="${idp.target.dir}/jetty-base/start.d.dist/idp-system.ini" toFile="${idp.target.dir}/jetty-base/start.d/idp-system.ini" overwrite="true" force="true" />
-     </target>
-
-    <target name="copyidpini" depends="directories" unless="idp.ini.present">
-        <mergeproperties inFile="${idp.target.dir}/jetty-base/start.d.dist/idp.ini.windows" outFile="${idp.target.dir}/jetty-base/start.d/idp.ini" mergeFile="${jetty.merge.properties}" />
-    </target>
-
-    <target name="rewriteidpini" depends="directories" if="idp.ini.present">
-        <rewriteproperties inFile="${idp.target.dir}/jetty-base/start.d/idp.ini" outFile="${idp.target.dir}/jetty-base/start.d/idp.ini" propertyNameFile="${idp.target.dir}/jetty-base/start.d.dist/idp.ini.rewrite.property.names" />
-    </target>
-
-
-   <target name="reprotect">
-       <chmod perm="600" dir="jetty-base/start.d" includes="**/*.key"/>
-       <chmod perm="444" dir="jetty-base/etc" includes="**/*"/>
-       <chmod perm="444" dir="jetty-base/lib" includes="**/*"/>
-       <chmod perm="444" dir="jetty-base/webapps" includes="**/*"/>
-       <attrib readonly="true">
-           <fileset dir="jetty-base/etc" includes="**/*"/>
-       </attrib>
-        <attrib readonly="true">
-                <fileset dir="jetty-base/lib" includes="**/*"/>
-        </attrib>
-        <attrib readonly="true">
-                <fileset dir="jetty-base/webapps" includes="**/*"/>
-        </attrib>
-    </target>
-
-    <target name="tidy" unless="jetty.no.tidy">
-        <delete file="${jetty.merge.properties}" failonerror="false" />
-        <delete file="${jetty.property.file}" failonerror="false" />
-    </target>
-
-</project>
diff --git a/idp-installer/src/main/wix/scripts/shib_write_configs.vbs b/idp-installer/src/main/wix/scripts/shib_write_configs.vbs
index 040751468..41bd25a0b 100644
--- a/idp-installer/src/main/wix/scripts/shib_write_configs.vbs
+++ b/idp-installer/src/main/wix/scripts/shib_write_configs.vbs
@@ -48,10 +48,6 @@ LogFile.WriteLine "Domain " & Domain
 LogFile.WriteLine "Scope " & IdPScope
 LogFile.WriteLine "IntallJetty" & InstallJetty
 
-KeyStorePassword=left(CreateObject("Scriptlet.TypeLib").Guid, 38)
-SealerPassword=left(CreateObject("Scriptlet.TypeLib").Guid, 38)
-SsoStorePassword=left(CreateObject("Scriptlet.TypeLib").Guid, 38)
-
 set AntFile=FileSystemObj.OpenTextFile(InstallDir & "\idp.install.properties" , 2, True)
 if (Err.Number = 0 ) then
     AntFile.WriteLine "#"
@@ -60,8 +56,6 @@ if (Err.Number = 0 ) then
     AntFile.WriteLine "idp.noprompt=yes"
     AntFile.WriteLine "idp.host.name=" & IdpHostName
     AntFile.WriteLine "idp.uri.subject.alt.name=https://" & Domain & "/idp"
-    AntFile.WriteLine "idp.keystore.password=" & KeyStorePassword
-    AntFile.WriteLine "idp.sealer.password=" & SealerPassword
     AntFile.WriteLine "idp.target.dir=" & InstallDirJava 
     AntFile.WriteLine "idp.merge.properties=" & InstallDirJava & "/idp.install.replace.properties"
     if (IdPScope <> "") then
@@ -96,59 +90,6 @@ else
     LogFile.Writeline "PropsFile failed " & Err & "  -  " & PropsFile
 end if
 
-if (InstallJetty <> "") then
-    set JettyAntFile=FileSystemObj.OpenTextFile(InstallDir & "\jetty.install.properties" , 2, True)
-    if (Err.Number = 0 ) then
-	JettyAntFile.WriteLine "#"
-	JettyAntFile.WriteLine "# File with properties for ANT"
-	JettyAntFile.WriteLine "#"
-	JettyAntFile.WriteLine "jetty.merge.properties="& InstallDirJava & "/jetty.install.replace.properties"
-	JettyAntFile.WriteLine "idp.host.name=" & IdpHostName
-	JettyAntFile.WriteLine "idp.keystore.password=" & SsoStorePassword
-	JettyAntFile.WriteLine "idp.uri.subject.alt.name=https://" & Domain & "/idp"
-	JettyAntFile.WriteLine "idp.target.dir=" & InstallDirJava 
-        if (DebugInstall <> "") then
-	    JettyAntFile.WriteLine "jetty.no.tidy=true"
-	else 
-	    JettyAntFile.WriteLine "#jetty.no.tidy=true"
-	end if
-	JettyAntFile.Close
-    else
-	LogFile.Writeline "jettyAnt failed " & Err
-    end if
-
-    set JettyFile=FileSystemObj.OpenTextFile(InstallDir & "\jetty.install.replace.properties" , 2, True)
-    if (Err.Number = 0 ) then
-	JettyFile.WriteLine "#"
-	JettyFile.WriteLine "# File to be merged into jetty's idp.ini file"
-	JettyFile.WriteLine "#"
-
-'
-' Redundant - no longer in idp.ini.windows
-'
-'	JettyFile.WriteLine "jetty.ssl.host=0.0.0.0"
-'	JettyFile.WriteLine "jetty.ssl.port=443"
-'	JettyFile.WriteLine "idp.war.path="../war/idp.war"
-'	JettyFile.WriteLine "jetty.http.host=localhost"
-'	JettyFile.WriteLine "jetty.http.port=80"
-
-'
-' Only these 6 properties are used and only the password need be changed.
-'
-'	JettyFile.WriteLine "jetty.backchannel.keyStorePath=../credentials/idp-backchannel.p12"
-'	JettyFile.WriteLine "jetty.sslContext.keyStorePath=../credentials/idp-userfacing.p12"
-	JettyFile.WriteLine "idp.backchannel.keyStorePassword=" & KeyStorePassword
-	JettyFile.WriteLine "jetty.sslContext.keyStorePassword=" & SsoStorePassword
-'	JettyFile.WriteLine "idp.backchannel.keyStoreType=PKCS12"
-'	JettyFile.WriteLine "jetty.sslContext.keyStoreType=PKCS12"
-
-	JettyFile.Close
-    else
-	LogFile.Writeline "jetty failed " & Err
-    end if
-else
-   LogFile.WriteLine "NoJetty " & InstallJetty
-end if
 
 if ConfigureAd = "true" then
 

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


More information about the commits mailing list