[java-identity-provider] 02/04: IDP-1854 Add a discovery option to the plugin command

Rod Widdowson rdw at steadingsoftware.com
Sun Aug 29 15:08:32 UTC 2021


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=7775ddc47695ba384bb59fcafbc435f5f045be1b

commit 7775ddc47695ba384bb59fcafbc435f5f045be1b
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Sat Aug 28 16:05:10 2021 +0100

    IDP-1854 Add a discovery option to the plugin command
    
    https://shibboleth.atlassian.net/browse/IDP-1854
    
    Phase 3 - add the -L (list available) qualifier.
---
 .../idp/installer/plugin/impl/PluginInfo.java      |   1 -
 .../plugin/impl/PluginInstallerArguments.java      |  29 +++++-
 .../installer/plugin/impl/PluginInstallerCLI.java  | 102 ++++++++++++++++++++-
 .../idp/installer/plugin/impl/PluginCLITest.java   |   4 +
 4 files changed, 132 insertions(+), 4 deletions(-)

diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInfo.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInfo.java
index 52569a6da..b7db0e1b1 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInfo.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInfo.java
@@ -255,7 +255,6 @@ public class PluginInfo {
     public static boolean isSupportedWithIdPVersion(final PluginState.VersionInfo pluginVersionInfo,
             final PluginVersion idPVersion) {
         final int maxCompare = idPVersion.compareTo(pluginVersionInfo.getMaxSupported()); 
-        
         if (maxCompare >= 0) {
             // Exclusive:
             // IdP (test against) Version is GREATER THAN OR EQUAL to our Max
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerArguments.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerArguments.java
index 0a9cdcf27..6df200443 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerArguments.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerArguments.java
@@ -56,6 +56,10 @@ public class PluginInstallerArguments extends AbstractIdPHomeAwareCommandLineArg
     @Parameter(names= {"-l", "--list"})
     @Nullable private boolean list;
 
+    /** Brief info about installed plugins. */
+    @Parameter(names= {"-L", "--list-available"})
+    @Nullable private boolean listAvailable;
+
     /** Override version check. */
     @Parameter(names= {"--noCheck"})
     @Nullable private boolean noCheck;
@@ -72,6 +76,10 @@ public class PluginInstallerArguments extends AbstractIdPHomeAwareCommandLineArg
     @Parameter(names= {"-i", "--input"})
     @Nullable private String input;
 
+    /** What to install. */
+    @Parameter(names= {"-I", "--install-ID"})
+    @Nullable private String installId;
+
     /** Truststore to use for signing. */
     @Parameter(names= {"--truststore"})
     @Nullable private String truststore;
@@ -197,6 +205,20 @@ public class PluginInstallerArguments extends AbstractIdPHomeAwareCommandLineArg
         return fullList;
     }
 
+    /** Are we going to list everything from the remote site?
+     * @return listAvailable.
+     */
+    public boolean isListAvailable() {
+        return listAvailable;
+    }
+    
+    /** Are we going to install from the pluginId?
+     * @return whether the user specified {@link #installId}
+     */
+    public boolean isInstallId() {
+        return StringSupport.trimOrNull(installId) != null;
+    }
+
     /** Are we doing a List?
      * 
      * @return whether we're doing a list
@@ -272,7 +294,7 @@ public class PluginInstallerArguments extends AbstractIdPHomeAwareCommandLineArg
             getLog().error("Unexpected extra arguments {}", output);
             throw new IllegalArgumentException("Unexpected extra arguments");
         }
-        if (list || fullList) {
+        if (list || fullList || listAvailable) {
             operation = OperationType.LIST;
             if (input !=  null || uninstallId != null) {
                 getLog().error("Cannot List and Install or Remove in the same operation.");
@@ -287,7 +309,10 @@ public class PluginInstallerArguments extends AbstractIdPHomeAwareCommandLineArg
                 getLog().error("Cannot Install and Update or Remove in the same operation.");
                 throw new IllegalArgumentException("Cannot List and Update or Remove in the same operation.");
             }
-            operation = decodeInput() ;
+            operation = decodeInput();
+        } else if (installId != null) {
+            operation = OperationType.INSTALLREMOTE;
+            pluginId = installId;
         } else if (updatePluginId != null) {
             if (uninstallId != null) {
                 getLog().error("Cannot Update and Remove in the same operation.");
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerCLI.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerCLI.java
index f41f8e0a7..12cdf9d8d 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerCLI.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerCLI.java
@@ -27,9 +27,12 @@ import java.nio.file.Path;
 import java.security.Security;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Properties;
 import java.util.function.Predicate;
 
 import javax.annotation.Nonnull;
@@ -40,9 +43,11 @@ import org.bouncycastle.jce.provider.BouncyCastleProvider;
 import org.slf4j.Logger;
 import org.springframework.beans.BeansException;
 import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.FileSystemResource;
 import org.springframework.core.io.Resource;
 
 import net.shibboleth.ext.spring.cli.AbstractCommandLine;
+import net.shibboleth.ext.spring.resource.HTTPResource;
 import net.shibboleth.idp.Version;
 import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
 import net.shibboleth.idp.installer.impl.InstallationLogger;
@@ -134,6 +139,9 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
 
             switch (args.getOperation()) {
                 case LIST:
+                    if (args.isListAvailable()) {
+                        return doListAvailable();
+                    }
                     doList(args.isFullList(), args.getPluginId());
                     break;
 
@@ -148,7 +156,11 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
                     if (args.getPluginId() != null) {
                         installer.setPluginId(args.getPluginId());
                     }
-                    installer.installPlugin(args.getInputURL(), args.getInputFileName(), !args.isNoCheck());
+                    if (args.isInstallId()) {
+                        //autoInstallPlugin();
+                    } else {
+                        installer.installPlugin(args.getInputURL(), args.getInputFileName(), !args.isNoCheck());
+                    }
                     break;
 
                 case UPDATE:
@@ -346,6 +358,94 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
         }
     }
 
+    /** Go to the well known url (or the provided one) and list all
+     * the available plugin ids.
+     * @return whether it worked
+     */
+    private int doListAvailable() {
+        final Properties props = loadPluginInfo();
+        if (props == null) {
+            return RC_IO;
+        }
+
+        final Map<String, PluginInfo> plugins = new HashMap<>();
+        final Enumeration<Object> en = props.keys();
+        while (en.hasMoreElements()) {
+            final String key = (String)en.nextElement();
+            if (key.endsWith(".versions")) {
+                final String pluginId = key.substring(0, key.length()-9);
+                plugins.put(pluginId, new PluginInfo(pluginId, props));
+            }
+        }
+
+        for (final Entry<String, PluginInfo> e: plugins.entrySet()) {
+            final PluginVersion nullVersion = new PluginVersion(0, 0, 0);
+            final IdPPlugin existingPlugin = installer.getInstalledPlugin(e.getKey());
+            if (existingPlugin == null) {
+                final PluginVersion version = getBestVersion(nullVersion, e.getValue());
+                if (version == null) {
+                    log.debug("Plugin {} has no version available", e.getKey());
+                } else {
+                    outOrLog(String.format("Plugin %s: version %s available for install", e.getKey(), version));
+                }
+            } else {
+                final PluginVersion existingVersion = new PluginVersion(existingPlugin);
+                final PluginVersion version = getBestVersion(existingVersion, e.getValue());
+                if (version == null) {
+                    outOrLog(String.format("Plugin %s: Installed version %s: No update available",
+                            e.getKey(),
+                            existingVersion));
+                } else {
+                    outOrLog(String.format("Plugin %s: Installed version %s: Update to &s available",
+                            e.getKey(),
+                            existingVersion,
+                            version));
+                }
+            }
+        }
+        return RC_OK;
+    }
+
+    /** Load the property file describing all the plugin we know about from a known location.
+     * @return the property files plugins.
+     */
+    private Properties loadPluginInfo() {
+        final List<URL> urls;
+        final Properties props = new Properties();
+        try {
+            if ((updateURLs == null) || (updateURLs.isEmpty())) {
+                    urls = List.of(
+                            new URL("https://shibboleth.net/downloads/identity-provider/plugins/plugins.properties"),
+                            new URL("http://plugins.shibboleth.net/plugins.properties"));
+            } else {
+                urls = updateURLs;
+            }
+            for (final URL url: urls) {
+                final Resource propertyResource;
+                if ("file".equals(url.getProtocol())) {
+                    propertyResource = new FileSystemResource(url.getPath());
+                } else if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) {
+                    propertyResource = new HTTPResource(getHttpClient(), url);
+                } else {
+                    log.error("Only file and http[s] URLs are allowed");
+                    return null;
+                }
+
+                log.debug("Plugin Listing: Looking for update at {}", propertyResource.getDescription());
+                if (!propertyResource.exists()) {
+                    log.info("{} could not be located", propertyResource.getDescription());
+                    continue;
+                }
+                props.load(propertyResource.getInputStream());
+                break;
+            }
+
+        } catch (final IOException e) {
+            log.error("Could not load update URL", e);
+            return null;
+        }
+        return props;
+    }
 
     /** Find the best update version.  Helper function for {@linkplain #doUpdate(String, PluginVersion, boolean)}.
      * @param pluginVersion The Plugin version
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginCLITest.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginCLITest.java
index 3692a57e2..969d0d8be 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginCLITest.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginCLITest.java
@@ -68,6 +68,10 @@ public class PluginCLITest extends BasePluginTest {
         assertEquals(PluginInstallerCLI.runMain(new String[] { "-fl", } ), AbstractCommandLine.RC_OK);
     }
 
+    @Test(enabled = true) public void testListAvailable() throws IOException {
+        assertEquals(PluginInstallerCLI.runMain(new String[] { "-L", } ), AbstractCommandLine.RC_OK);
+    }
+
     @Test(enabled = true,dependsOnMethods = {/*"testWeb"*/}) public void testListWithOverride() throws IOException {
         ClassPathResource resource = new ClassPathResource("/net/shibboleth/idp/plugin/allPlugins.props");
         String url = resource.getURL().toString();

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


More information about the commits mailing list