[java-identity-provider] 05/11: IDP-1499 New V4 Installer: Key Management

Rod Widdowson rdw at steadingsoftware.com
Fri Oct 11 11:08:28 EDT 2019


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

rdw pushed a commit to branch master
in repository java-identity-provider.

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

commit ec4ddc2397f862c70728639743f2028c406e5519
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Oct 7 15:52:30 2019 +0100

    IDP-1499 New V4 Installer: Key Management
    
    https://issues.shibboleth.net/jira/browse/IDP-1499
    
    Create (if needed)
     - Sealer keystore
     - backchannel keystore
     - Signing and Encryption keys
---
 .../idp/installer/impl/InstallerProperties.java    |  29 ++++
 .../idp/installer/impl/KeyManagement.java          | 168 +++++++++++++++++++++
 2 files changed, 197 insertions(+)

diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java
index 8cacea3..62c2671 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java
@@ -114,6 +114,9 @@ public class InstallerProperties extends AbstractInitializableComponent {
     /** The sealer alias to use.  */
     public static final String SEALER_ALIAS = "idp.sealer.alias";
 
+    /** The sealer alias to use.  */
+    public static final String KEY_SIZE = "idp.keysize";
+
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(InstallerProperties.class);
 
@@ -161,6 +164,12 @@ public class InstallerProperties extends AbstractInitializableComponent {
     /** Sealer Alias. */
     private String sealerAlias;
 
+    /** Key Size. (for signing, encryption and backchannel). */
+    private int keySize;
+
+    /** Whether the properties file exists.*/
+    private boolean idpPropertiesPresent;
+
     /**
      * Constructor.
      * @param populateDone is this a war build (or a windows installer)? If no we don't need the source dir.
@@ -214,6 +223,13 @@ public class InstallerProperties extends AbstractInitializableComponent {
             srcDir = Path.of(value);
             log.debug("Source directory {}", srcDir.toAbsolutePath());
         }
+
+        if (!installerProperties.contains(KEY_SIZE)) {
+            keySize = 3072;
+        } else {
+            keySize = Integer.parseInt(installerProperties.getProperty(KEY_SIZE));
+        }
+        idpPropertiesPresent = Files.exists(getTargetDir().resolve("conf").resolve("idp.properties"));
     }
 
     /** Lookup a property.  If it isn't defined then ask the user (if we are allowed)
@@ -475,4 +491,17 @@ public class InstallerProperties extends AbstractInitializableComponent {
         }
         return sealerAlias;
     }
+
+    /** Get the key size for signing, encryption and backchannel.
+     * @return the keysize, default is 3072 */
+    public int getKeySize() {
+        return keySize;
+    }
+
+    /** Was idp.properties present in the target file when we started the install?
+     * @return if it was.
+     */
+    public boolean isIdPPropertiesPresent() {
+        return idpPropertiesPresent;
+    }
 }
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/KeyManagement.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/KeyManagement.java
new file mode 100644
index 0000000..5f9d6ec
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/KeyManagement.java
@@ -0,0 +1,168 @@
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
+
+import org.apache.tools.ant.BuildException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.security.BasicKeystoreKeyStrategyTool;
+import net.shibboleth.utilities.java.support.security.SelfSignedCertificateGenerator;
+
+/**
+ * Create (if needs be) all the keys needed by an install.
+ */
+public final class KeyManagement {
+
+    /** Log. */
+    public static final Logger LOG = LoggerFactory.getLogger(KeyManagement.class);
+
+    /** Private Constructor. */
+    private KeyManagement() { }
+
+    /** Create any keys that are needed.
+     * @param ip what drives the install.
+     * @throws BuildException if badness occurs
+     */
+    public static void manageKeys(final InstallerProperties ip) throws BuildException {
+
+        generateKey(ip, "idp-signing");
+        generateKey(ip, "idp-encryption");
+        generateKeyStore(ip);
+        generateSealer(ip);
+    }
+
+    /** Helper method for {@link #manageKeys(InstallerProperties)} to generate a crt and key file.
+     * @param ip the Configuration
+     * @param fileBase the partial file name
+     * @throws BuildException if badness occurrs.
+     */
+    private static void generateKey(final InstallerProperties ip, final String fileBase) throws BuildException {
+        final Path credentials = ip.getTargetDir().resolve("credentials");
+        final Path key = credentials.resolve(fileBase+".key");
+        final Path crt = credentials.resolve(fileBase+".crt");
+
+        if (Files.exists(key) && Files.exists(crt)) {
+            if (!ip.isIdPPropertiesPresent()) {
+                LOG.error("key files {} and {} exist but idp.properties does not", key, crt);
+                throw new BuildException("Invalid key file configuration");
+            }
+            LOG.debug("keys files {} and {} exist.  Not generating", key, crt);
+        } else if (ip.isIdPPropertiesPresent()) {
+            LOG.error("idp.properties exists but key files {} and/or {} do not", key, crt);
+            throw new BuildException("Invalid key file configuration");
+        } else if (Files.exists(key) || Files.exists(crt)) {
+            LOG.error("One of two expected key files {} and {} exist", key, crt);
+            throw new BuildException("Invalid key file configuration");
+        } else {
+          final SelfSignedCertificateGenerator generator = new SelfSignedCertificateGenerator();
+          generator.setCertificateFile(crt.toFile());
+          generator.setPrivateKeyFile(key.toFile());
+          generator.setKeySize(ip.getKeySize());
+          generator.setHostName(ip.getHostName());
+          generator.setURISubjectAltNames(Collections.singletonList(ip.getSubjectAltName()));
+          LOG.info("Creating {}, CN = {} URI = {}", fileBase, ip.getHostName(), ip.getSubjectAltName());
+          try {
+            generator.generate();
+            } catch (final Exception e) {
+                LOG.error("Error building {} files", fileBase, e);
+                throw new BuildException("Error Building Self Signed Cert", e);
+            }
+        }
+    }
+
+    /** Helper method for {@link #manageKeys(InstallerProperties)} to generate the backchannel keystore.
+     * @param ip the Configuration
+     * @throws BuildException if badness occurrs.
+     */
+    private static void generateKeyStore(final InstallerProperties ip) {
+        final Path credentials = ip.getTargetDir().resolve("credentials");
+        final Path keyStore = credentials.resolve("idp-backchannel.p12");
+        final Path crt = credentials.resolve("idp-backchannel.crt");
+
+        if (Files.exists(keyStore) && Files.exists(crt)) {
+            if (!ip.isIdPPropertiesPresent()) {
+                LOG.error("Key store files {} and {} exist but idp.properties does not", keyStore, crt);
+                throw new BuildException("Invalid key file configuration");
+            }
+            LOG.debug("Keys store files {} and {} exist.  Not generating", keyStore, crt);
+        } else if (ip.isIdPPropertiesPresent()) {
+            LOG.error("idp.properties exists but key store files {} and/or {} do not", keyStore, crt);
+            throw new BuildException("Invalid key file configuration");
+        } else if (Files.exists(keyStore) || Files.exists(crt)) {
+            LOG.error("One of two expected key files {} and {} exist", keyStore, crt);
+            throw new BuildException("Invalid key file configuration");
+        } else {
+            final SelfSignedCertificateGenerator generator = new SelfSignedCertificateGenerator();
+            generator.setCertificateFile(crt.toFile());
+            generator.setKeystoreFile(keyStore.toFile());
+            generator.setKeySize(ip.getKeySize());
+            generator.setHostName(ip.getHostName());
+            generator.setURISubjectAltNames(Collections.singletonList(ip.getSubjectAltName()));
+            generator.setKeystorePassword(ip.getKeyStorePassword());
+            LOG.info("Creating backchannel keystore, CN = {} URI = {}", ip.getHostName(), ip.getSubjectAltName());
+            try {
+              generator.generate();
+              } catch (final Exception e) {
+                  LOG.error("Error building backchannel ketsyore files", e);
+                  throw new BuildException("Error Building Backchannel Key Store", e);
+              }
+          }
+    }
+
+    /** Helper method for {@link #manageKeys(InstallerProperties)} to generate the Sealer.
+     * @param ip the Configuration
+     * @throws BuildException if badness occurrs.
+     */
+    private static void generateSealer(final InstallerProperties ip) {
+        final Path credentials = ip.getTargetDir().resolve("credentials");
+        final Path sealer = credentials.resolve("sealer.jks");
+        final Path versionFile = credentials.resolve("sealer.kver");
+
+        if (Files.exists(sealer)  && Files.exists(versionFile)) {
+            if (!ip.isIdPPropertiesPresent()) {
+                LOG.error("Cookie encryption files {} and {} exist but idp.properties does not", sealer, versionFile);
+                throw new BuildException("Invalid Cookie encryption  file configuration");
+            }
+            LOG.debug("Cookie encryption files {} and {} exists.  Not generating.", sealer, versionFile);
+        } else if (ip.isIdPPropertiesPresent()) {
+            LOG.error("idp.properties exists but cookie encryption files {} do not", sealer, versionFile);
+            throw new BuildException("Invalid key file configuration");
+        } else if (Files.exists(sealer) || Files.exists(versionFile)) {
+            LOG.error("One of two expected cookie encryption file {} and {} exist", sealer, versionFile);
+            throw new BuildException("Invalid cookie encryption file configuration");
+        } else {
+            final BasicKeystoreKeyStrategyTool generator = new BasicKeystoreKeyStrategyTool();
+            generator.setKeystoreFile(sealer.toFile());
+            generator.setVersionFile(versionFile.toFile());
+            generator.setKeyAlias(ip.getSealerAlias());
+            generator.setKeystorePassword(ip.getSealerPassword());
+            LOG.info("Creating backchannel keystore, CN = {} URI = {}", ip.getHostName(), ip.getSubjectAltName());
+            try {
+                generator.changeKey();
+            } catch (final Exception e) {
+                LOG.error("Error building cookie encryption files", e);
+                throw new BuildException("Error Building Cookie Encryption", e);
+            }
+        }
+    }
+}

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


More information about the commits mailing list