[java-identity-provider] 04/04: IDP-2117, IDP-2122, IDP-2073 Plugin Installer fixes
Rod Widdowson
rdw at steadingsoftware.com
Sun May 28 15:05:06 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=5ab838affc71ec21b5173baa6b3c3d9cba80d577
commit 5ab838affc71ec21b5173baa6b3c3d9cba80d577
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Sun May 28 15:52:14 2023 +0100
IDP-2117, IDP-2122, IDP-2073 Plugin Installer fixes
https://shibboleth.atlassian.net/browse/IDP-2122
https://shibboleth.atlassian.net/browse/IDP-2117
https://shibboleth.atlassian.net/browse/IDP-2073
Add a lot of nullability annotations
IDP-2112 Fix Plugin Verion.equals method
IDP-2117 Correctly pass the security handler down for download
IDP-2073 Start to exbend some function that the command line update
program can use
---
.../idp/installer/impl/IdPInstallerCLI.java | 1 -
.../idp/installer/plugin/impl/PluginInstaller.java | 42 ++----
.../installer/plugin/impl/PluginInstallerCLI.java | 130 +++----------------
.../plugin/impl/PluginInstallerSupport.java | 141 +++++++++++++++++++++
.../idp/installer/plugin/impl/PluginState.java | 4 +-
.../shibboleth/idp/installer/TestInstallerCLI.java | 49 ++++++-
.../idp/installer/plugin/impl/PluginStateTest.java | 5 +-
.../idp/installer/plugin/impl/RollbackTester.java | 7 +-
.../idp/installer/plugin/impl/TrustStoreTest.java | 30 +++--
9 files changed, 249 insertions(+), 160 deletions(-)
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/IdPInstallerCLI.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/IdPInstallerCLI.java
index 762edfe5f..bfcb4da7a 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/IdPInstallerCLI.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/IdPInstallerCLI.java
@@ -50,7 +50,6 @@ public class IdPInstallerCLI extends AbstractCommandLine<IdPInstallerArguments>
@Override
@Nonnull
protected Class<IdPInstallerArguments> getArgumentClass() {
- // TODO Auto-generated method stub
return IdPInstallerArguments.class;
}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstaller.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstaller.java
index 17e61b6ac..520785f09 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstaller.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstaller.java
@@ -67,7 +67,6 @@ import org.slf4j.Logger;
import net.shibboleth.idp.Version;
import net.shibboleth.idp.installer.InstallerSupport;
-import net.shibboleth.idp.installer.ProgressReportingOutputStream;
import net.shibboleth.idp.installer.impl.BuildWar;
import net.shibboleth.idp.installer.plugin.impl.TrustStore.Signature;
import net.shibboleth.idp.module.IdPModule;
@@ -86,7 +85,6 @@ import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.logic.PredicateSupport;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.primitive.StringSupport;
-import net.shibboleth.shared.resource.Resource;
import net.shibboleth.shared.spring.httpclient.resource.HTTPResource;
/**
@@ -335,6 +333,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
public void uninstall() throws BuildException {
String moduleId = null;
+ assert pluginId != null;
description = getInstalledPlugin(pluginId);
if (description == null) {
LOG.warn("Description for {} not found", pluginId);
@@ -673,14 +672,15 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
*/
private void download(@Nonnull final URL baseURL, @Nonnull final String fileName) throws BuildException {
try {
- downloadDirectory = Files.createTempDirectory("plugin-installer-download");
+ final Path dir = downloadDirectory = Files.createTempDirectory("plugin-installer-download");
+ assert dir != null;
final HTTPResource baseResource = new HTTPResource(httpClient, baseURL);
final HttpClientSecurityContextHandler handler = new HttpClientSecurityContextHandler();
handler.setHttpClientSecurityParameters(securityParams);
handler.initialize();
baseResource.setHttpClientContextHandler(handler);
- download(baseResource, fileName);
- download(baseResource, fileName + ".asc");
+ PluginInstallerSupport.download(baseResource, handler, dir, fileName);
+ PluginInstallerSupport.download(baseResource, handler, dir, fileName + ".asc");
} catch (final IOException | ComponentInitializationException e) {
LOG.error("Error in download", e);
throw new BuildException(e);
@@ -740,21 +740,6 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
}
}
- /** Download helper method.
- * @param baseResource where to go for the file
- * @param fileName the file name
- * @throws IOException as required
- */
- private void download(final Resource baseResource, @Nonnull final String fileName) throws IOException {
- final Resource fileResource = baseResource.createRelativeResource(fileName);
- final Path filePath = downloadDirectory.resolve(fileName);
- LOG.info("Downloading from {}", fileResource.getDescription());
- LOG.debug("Downloading to {}", filePath);
- try (final OutputStream fileOut = new ProgressReportingOutputStream(new FileOutputStream(filePath.toFile()))) {
- fileResource.getInputStream().transferTo(fileOut);
- }
- }
-
/** Method to unpack a zip or tgz file into out {{@link #unpackDirectory}.
* @param base Where the zip/tgz file is
* @param fileName the name.
@@ -839,7 +824,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
* @return the the appropriate {@link ArchiveInputStream}
* @throws IOException if we trip over an unpack
*/
- private ArchiveInputStream getStreamFor(final Path fullName, final boolean isZip) throws IOException {
+ @Nonnull private ArchiveInputStream getStreamFor(final Path fullName, final boolean isZip) throws IOException {
final InputStream inStream = new BufferedInputStream(new FileInputStream(fullName.toFile()));
if (isZip) {
return new ZipArchiveInputStream(inStream);
@@ -881,7 +866,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
* @param fileName the name.
* @throws BuildException if badness is detected.
*/
- private void checkSignature(final Path base, final String fileName) throws BuildException {
+ private void checkSignature(@Nonnull final Path base, @Nonnull final String fileName) throws BuildException {
try (final InputStream sigStream = new BufferedInputStream(
new FileInputStream(base.resolve(fileName + ".asc").toFile()))) {
final TrustStore trust = new TrustStore();
@@ -955,7 +940,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
* @return an appropriate loader
* @throws BuildException if a directory traversal fails.
*/
- private synchronized URLClassLoader getInstalledPluginsLoader() throws BuildException {
+ @Nonnull private synchronized URLClassLoader getInstalledPluginsLoader() throws BuildException {
if (installedPluginsLoader != null) {
return installedPluginsLoader;
@@ -1001,7 +986,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
* @return an appropriate loader
* @throws BuildException if a directory traversal fails.
*/
- private synchronized URLClassLoader getDistributionLoader() throws BuildException {
+ @Nonnull private synchronized URLClassLoader getDistributionLoader() throws BuildException {
if (installingPluginLoader!= null) {
return installingPluginLoader;
}
@@ -1027,18 +1012,17 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
* @return All the plugins.
* @throws BuildException if loafing the classpath fails.
*/
- public List<IdPPlugin> getInstalledPlugins() throws BuildException {
+ @Nonnull public List<IdPPlugin> getInstalledPlugins() throws BuildException {
final Stream<Provider<IdPPlugin>> loaderStream =
ServiceLoader.load(IdPPlugin.class, getInstalledPluginsLoader()).stream();
- return loaderStream.map(ServiceLoader.Provider::get).collect(Collectors.toList());
+ return loaderStream.map(ServiceLoader.Provider::get).collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
/** Find the {@link IdPPlugin} with the provided Id.
* @param name what to find
* @return the {@link IdPPlugin} or null if not found.
*/
- @Nullable public IdPPlugin getInstalledPlugin(final String name) {
- Constraint.isNotNull(name, "Plugin Name must not be null");
+ @Nullable public IdPPlugin getInstalledPlugin(@Nonnull final String name) {
final List<IdPPlugin> plugins = getInstalledPlugins();
for (final IdPPlugin plugin: plugins) {
if (plugin.getPluginId().equals(name)) {
@@ -1075,7 +1059,7 @@ public final class PluginInstaller extends AbstractInitializableComponent implem
/** Return a version we can use in a test proof manner.
* @return the IdP version or a fixed value
*/
- protected static PluginVersion getIdPVersion() {
+ @Nonnull protected static PluginVersion getIdPVersion() {
final String version = Version.getVersion();
if (version == null) {
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 12df2d90a..c3a6ff09a 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
@@ -40,18 +40,15 @@ import javax.annotation.Nullable;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.tools.ant.BuildException;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
-import org.opensaml.security.httpclient.HttpClientSecurityContextHandler;
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.idp.Version;
import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
import net.shibboleth.idp.installer.plugin.impl.PluginState.VersionInfo;
import net.shibboleth.idp.plugin.IdPPlugin;
-import net.shibboleth.idp.plugin.PluginSupport.SupportLevel;
import net.shibboleth.idp.plugin.PluginVersion;
import net.shibboleth.shared.annotation.constraint.NonnullElements;
import net.shibboleth.shared.cli.AbstractCommandLine;
@@ -60,7 +57,6 @@ import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
import net.shibboleth.shared.primitive.StringSupport;
-import net.shibboleth.shared.spring.httpclient.resource.HTTPResource;
/**
* Command line for Plugin Installation.
@@ -74,7 +70,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
@Nullable private PluginInstaller installer;
/** Update URLs. */
- private List<URL> updateURLs;
+ @Nonnull private List<URL> updateURLs = CollectionSupport.emptyList();
/**
* Constrained Constructor.
@@ -116,7 +112,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
/** {@inheritDoc} */
//CheckStyle: CyclomaticComplexity|MethodLength OFF
protected int doRun(@Nonnull final PluginInstallerArguments args) {
-
+
if (args.getHttpClientName() == null) {
args.setHttpClientName("shibboleth.InternalHttpClient");
}
@@ -140,8 +136,6 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
log.error("Could not convert update URL {}", args.getUpdateURL(), e);
return RC_INIT;
}
- } else {
- updateURLs = CollectionSupport.emptyList();
}
try (final PluginInstaller inst = new PluginInstaller(Constraint.isNotNull(getHttpClient(), "HJttpClient cannot be non null (by construction"))) {
@@ -394,7 +388,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
* @return whether it worked
*/
private int doListAvailable() {
- final Properties props = loadPluginInfo();
+ final Properties props = PluginInstallerSupport.loadPluginInfo(updateURLs, this);
if (props == null) {
return RC_IO;
}
@@ -412,27 +406,30 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
}
}
- for (final Entry<String, PluginInfo> e: plugins.entrySet()) {
+ for (final Entry<String, PluginInfo> entry: plugins.entrySet()) {
final PluginVersion nullVersion = new PluginVersion(0, 0, 0);
+ final String key = entry.getKey();
+ final PluginInfo value = entry.getValue();
+ assert key!=null && value !=null;
assert installer != null;
- final IdPPlugin existingPlugin = installer.getInstalledPlugin(e.getKey());
+ final IdPPlugin existingPlugin = installer.getInstalledPlugin(key);
if (existingPlugin == null) {
- final PluginVersion version = getBestVersion(nullVersion, e.getValue());
+ final PluginVersion version = PluginInstallerSupport.getBestVersion(nullVersion, value);
if (version == null) {
- log.debug("Plugin {} has no version available", e.getKey());
+ log.debug("Plugin {} has no version available", entry.getKey());
} else {
- outOrLog(String.format("Plugin %s: version %s available for install", e.getKey(), version));
+ outOrLog(String.format("Plugin %s: version %s available for install", entry.getKey(), version));
}
} else {
final PluginVersion existingVersion = new PluginVersion(existingPlugin);
- final PluginVersion version = getBestVersion(existingVersion, e.getValue());
+ final PluginVersion version = PluginInstallerSupport.getBestVersion(existingVersion, value);
if (version == null) {
outOrLog(String.format("Plugin %s: Installed version %s: No update available",
- e.getKey(),
+ entry.getKey(),
existingVersion));
} else {
outOrLog(String.format("Plugin %s: Installed version %s: Update to %s available",
- e.getKey(),
+ entry.getKey(),
existingVersion,
version));
}
@@ -441,59 +438,6 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
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;
- }
- } catch (final IOException e) {
- log.error("Could not load update URLs", e);
- return null;
- }
- for (final URL url: urls) {
- final Resource propertyResource;
- try {
- if ("file".equals(url.getProtocol())) {
- final String path =url.getPath();
- assert path != null;
- propertyResource = new FileSystemResource(path);
- } else if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) {
- final HttpClient client = getHttpClient();
- assert client != null;
- final HTTPResource httpResource;
- propertyResource = httpResource = new HTTPResource(client , url);
- final HttpClientSecurityContextHandler handler = new HttpClientSecurityContextHandler();
- handler.setHttpClientSecurityParameters(getHttpClientSecurityParameters());
- handler.initialize();
- httpResource.setHttpClientContextHandler(handler);
- } else {
- log.error("Only file and http[s] URLs are allowed");
- continue;
- }
- 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());
- return props;
- } catch (final IOException | ComponentInitializationException e) {
- log.error("Could not open Update URL {} :", url, e);
- continue;
- }
- }
- log.error("Could not locate any active update servers");
- return null;
- }
/** Given the pluginId find the best version and install.
* If already installed whine
@@ -509,7 +453,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
log.error("Plugin {} is already installed", pluginId);
return RC_INIT;
}
- final Properties props = loadPluginInfo();
+ final Properties props = PluginInstallerSupport.loadPluginInfo(updateURLs, this);
if (props == null) {
log.error("AutoInstall not possible");
return RC_INIT;
@@ -519,7 +463,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
log.error("Plugin {}: Information not found", pluginId);
return RC_INIT;
}
- final PluginVersion versionToInstall = getBestVersion(new PluginVersion(0,0,0), info);
+ final PluginVersion versionToInstall = PluginInstallerSupport.getBestVersion(new PluginVersion(0,0,0), info);
if (versionToInstall == null) {
log.error("Plugin {}: No version available to install", pluginId);
return RC_INIT;
@@ -532,46 +476,6 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
return RC_OK;
}
-
-
- /** Find the best update version. Helper function for {@linkplain #doUpdate(String, PluginVersion, boolean)}.
- * @param pluginVersion The Plugin version
- * @param pluginInfo all about the plugin
- * @return the best version (or null)
- */
- @Nullable private PluginVersion getBestVersion(final PluginVersion pluginVersion , final PluginInfo pluginInfo) {
-
- final PluginVersion idPVersion = PluginInstaller.getIdPVersion();
-
- final List<PluginVersion> availableVersions = new ArrayList<>(pluginInfo.getAvailableVersions().keySet());
- availableVersions.sort(null);
- log.debug("Considering versions: {}", availableVersions);
-
- for (int i = availableVersions.size()-1; i >= 0; i--) {
- final PluginVersion version = availableVersions.get(i);
- if (version.compareTo(pluginVersion) <= 0) {
- log.debug("Version {} is less than or the same as {}. All done", version, pluginVersion);
- return null;
- }
- final VersionInfo versionInfo = pluginInfo.getAvailableVersions().get(version);
- if (versionInfo.getSupportLevel() != SupportLevel.Current) {
- log.debug("Version {} has support level {}, ignoring", version, versionInfo.getSupportLevel());
- continue;
- }
- if (!pluginInfo.isSupportedWithIdPVersion(version, idPVersion)) {
- log.debug("Version {} is not supported with idpVersion {}", version, idPVersion);
- continue;
- }
- log.debug("Version {} is supported with idpVersion {}", version, idPVersion);
- if (pluginInfo.getUpdateURL(version) == null || pluginInfo.getUpdateBaseName(version) == null) {
- log.debug("Version {} is does not have update information", version);
- continue;
- }
- return version;
- }
- return null;
- }
-
/** Update the plugin.
* @param pluginId the pluginId or null.
* @param pluginVersion (optionally) the version to update to.
@@ -603,7 +507,7 @@ public final class PluginInstallerCLI extends AbstractIdPHomeAwareCommandLine<Pl
}
final PluginVersion installVersion;
if (pluginVersion == null) {
- installVersion = getBestVersion(new PluginVersion(plugin), state.getPluginInfo());
+ installVersion = PluginInstallerSupport.getBestVersion(new PluginVersion(plugin), state.getPluginInfo());
if (installVersion == null) {
log.info("No suitable update version available");
return;
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerSupport.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerSupport.java
index bb185e548..76ca64ff2 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerSupport.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginInstallerSupport.java
@@ -18,25 +18,41 @@
package net.shibboleth.idp.installer.plugin.impl;
import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URL;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Properties;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.tools.ant.BuildException;
+import org.opensaml.security.httpclient.HttpClientSecurityContextHandler;
import org.slf4j.Logger;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
import net.shibboleth.idp.installer.InstallerSupport;
+import net.shibboleth.idp.installer.ProgressReportingOutputStream;
+import net.shibboleth.idp.installer.plugin.impl.PluginState.VersionInfo;
+import net.shibboleth.idp.plugin.PluginSupport.SupportLevel;
+import net.shibboleth.idp.plugin.PluginVersion;
import net.shibboleth.shared.annotation.constraint.Live;
import net.shibboleth.shared.collection.Pair;
+import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.spring.httpclient.resource.HTTPResource;
/**
* Support for copying files during plugin manipulation.
@@ -222,4 +238,129 @@ public final class PluginInstallerSupport {
return FileVisitResult.CONTINUE;
}
}
+
+ /** Find the best update version (plugin or IdP).
+ * @param pluginVersion The Plugin version
+ * @param pluginInfo all about the plugin
+ * @return the best version (or null)
+ */
+ @Nullable static public PluginVersion getBestVersion(@Nonnull final PluginVersion pluginVersion, @Nonnull final PluginInfo pluginInfo) {
+ return getBestVersion(PluginInstaller.getIdPVersion(), pluginVersion, pluginInfo);
+ }
+
+ /** Find the best update version (plugin or IdP).
+ * @param idPVersion The IdP version to check.
+ * @param pluginVersion The Plugin version
+ * @param pluginInfo all about the plugin
+ * @return the best version (or null)
+ */
+ @Nullable static public PluginVersion getBestVersion(@Nonnull final PluginVersion idPVersion,
+ @Nonnull final PluginVersion pluginVersion, @Nonnull final PluginInfo pluginInfo) {
+
+ final List<PluginVersion> availableVersions = new ArrayList<>(pluginInfo.getAvailableVersions().keySet());
+ availableVersions.sort(null);
+ LOG.debug("Considering versions: {}", availableVersions);
+
+ for (int i = availableVersions.size()-1; i >= 0; i--) {
+ final PluginVersion version = availableVersions.get(i);
+ if (version.compareTo(pluginVersion) <= 0) {
+ LOG.debug("Version {} is less than or the same as {}. All done", version, pluginVersion);
+ return null;
+ }
+ final VersionInfo versionInfo = pluginInfo.getAvailableVersions().get(version);
+ if (versionInfo.getSupportLevel() != SupportLevel.Current) {
+ LOG.debug("Version {} has support level {}, ignoring", version, versionInfo.getSupportLevel());
+ continue;
+ }
+ if (!pluginInfo.isSupportedWithIdPVersion(version, idPVersion)) {
+ LOG.debug("Version {} is not supported with idpVersion {}", version, idPVersion);
+ continue;
+ }
+ LOG.debug("Version {} is supported with idpVersion {}", version, idPVersion);
+ if (pluginInfo.getUpdateURL(version) == null || pluginInfo.getUpdateBaseName(version) == null) {
+ LOG.debug("Version {} is does not have update information", version);
+ continue;
+ }
+ return version;
+ }
+ return null;
+ }
+
+ /** Load the property file describing all the plugin we know about from a known location.
+ * @param updateURLs where to look
+ * @param commandLine the programming calling us.
+ * @return the property files plugins.
+ */
+ @Nullable public static Properties loadPluginInfo(@Nonnull final List<URL> updateURLs,
+ @Nonnull final AbstractIdPHomeAwareCommandLine<?> commandLine) {
+ final List<URL> urls;
+ final Properties props = new Properties();
+ try {
+ if (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;
+ }
+ } catch (final IOException e) {
+ LOG.error("Could not load update URLs", e);
+ return null;
+ }
+ for (final URL url: urls) {
+ final Resource propertyResource;
+ try {
+ if ("file".equals(url.getProtocol())) {
+ final String path =url.getPath();
+ assert path != null;
+ propertyResource = new FileSystemResource(path);
+ } else if ("http".equals(url.getProtocol()) || "https".equals(url.getProtocol())) {
+ final HttpClient client = commandLine.getHttpClient();
+ assert client != null;
+ final HTTPResource httpResource;
+ propertyResource = httpResource = new HTTPResource(client , url);
+ final HttpClientSecurityContextHandler handler = new HttpClientSecurityContextHandler();
+ handler.setHttpClientSecurityParameters(commandLine.getHttpClientSecurityParameters());
+ handler.initialize();
+ httpResource.setHttpClientContextHandler(handler);
+ } else {
+ LOG.error("Only file and http[s] URLs are allowed");
+ continue;
+ }
+ 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());
+ return props;
+ } catch (final IOException | ComponentInitializationException e) {
+ LOG.error("Could not open Update URL {} :", url, e);
+ continue;
+ }
+ }
+ LOG.error("Could not locate any active update servers");
+ return null;
+ }
+
+ /** Download helper method.
+ * @param baseResource where to go for the file
+ * @param handler HttpClientSecurityContextHandler to use
+ * @param downloadDirectory where to download to
+ * @param fileName the file name
+ * @throws IOException as required
+ */
+ public static void download(@Nonnull final HTTPResource baseResource,
+ @Nonnull final HttpClientSecurityContextHandler handler,
+ @Nonnull final Path downloadDirectory,
+ @Nonnull final String fileName) throws IOException {
+ final HTTPResource httpResource = baseResource.createRelative(fileName, handler);
+ final Path filePath = downloadDirectory.resolve(fileName);
+ LOG.info("Downloading from {}", httpResource.getDescription());
+ LOG.debug("Downloading to {}", filePath);
+ try (final OutputStream fileOut = new ProgressReportingOutputStream(new FileOutputStream(filePath.toFile()))) {
+ httpResource.getInputStream().transferTo(fileOut);
+ }
+ }
+
}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginState.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginState.java
index f21384c32..93e960562 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginState.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/PluginState.java
@@ -85,7 +85,9 @@ public class PluginState extends AbstractInitializableComponent {
/** get our PluginInfo.
* @return our PluginInfo.
*/
- public PluginInfo getPluginInfo() {
+ @Nonnull public PluginInfo getPluginInfo() {
+ checkComponentActive();
+ assert myPluginInfo!=null;
return myPluginInfo;
}
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/TestInstallerCLI.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/TestInstallerCLI.java
index c80b36613..ff757e7ac 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/TestInstallerCLI.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/TestInstallerCLI.java
@@ -21,25 +21,68 @@ import org.testng.annotations.Test;
import net.shibboleth.idp.installer.impl.IdPInstallerCLI;
import net.shibboleth.idp.installer.impl.InstallerProperties;
+import net.shibboleth.idp.installer.impl.UpdateIdPCLI;
/**
*
*/
public class TestInstallerCLI {
- @Test(enabled = true)
+ @Test(enabled = false)
public void install() {
System.setProperty(InstallerProperties.KEY_STORE_PASSWORD, "p1");
System.setProperty(InstallerProperties.SEALER_PASSWORD, "p1");
System.setProperty(InstallerProperties.HOST_NAME, "machine.org.uk");
+ System.setProperty(InstallerProperties.TARGET_DIR, "h:\\downloads\\idp");
// System.setProperty(InstallerProperties.SEALER_KEYSIZE, "256");
IdPInstallerCLI.runMain(new String[] {
"-s",
"h:\\Perforce\\Juno\\V5\\java-identity-provider\\idp-distribution\\target\\shibboleth-identity-provider-5.0.0-SNAPSHOT",
"--home", "classpath:/net/shibboleth/idp/module",
- "-t",
- "h:\\downloads\\idp",
"-hc", "shibboleth.InternalHttpClient"
});
}
+
+ @Test(enabled = false)
+ public void updateList430() {
+ UpdateIdPCLI.runMain(new String[] {
+ "-l",
+ "--pretendVersion","4.3.0",
+ "--updateURL", "file:C:\\Users\\rdw\\Desktop\\logs\\plugins.properties",
+ "--home", "H:\\Downloads\\idp"});
+ }
+
+ @Test(enabled = false)
+ public void updateList431() {
+ UpdateIdPCLI.runMain(new String[] {
+ "-l",
+ "--pretendVersion","4.3.1",
+ "--updateURL", "file:C:\\Users\\rdw\\Desktop\\logs\\plugins.properties",
+ "--home", "H:\\Downloads\\idp"});
+ }
+
+ @Test(enabled = false)
+ public void check430() {
+ UpdateIdPCLI.runMain(new String[] {
+ "--pretendVersion","4.3.0",
+ "--updateURL", "file:C:\\Users\\rdw\\Desktop\\logs\\plugins.properties",
+ "--home", "H:\\Downloads\\idp"});
+ }
+
+ @Test(enabled = false)
+ public void check431() {
+ UpdateIdPCLI.runMain(new String[] {
+ "--pretendVersion","4.3.1",
+ "--updateURL", "file:C:\\Users\\rdw\\Desktop\\logs\\plugins.properties",
+ "--home", "H:\\Downloads\\idp"});
+ }
+
+ @Test(enabled = false)
+ public void download430() {
+ UpdateIdPCLI.runMain(new String[] {
+ "-d", "H:\\downloads\\idp",
+ "--pretendVersion","4.3.0",
+ "--updateURL", "file:C:\\Users\\rdw\\Desktop\\logs\\plugins.properties",
+ "--home", "H:\\Downloads\\idp"});
+ }
}
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginStateTest.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginStateTest.java
index 65f0569a7..021f01569 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginStateTest.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/PluginStateTest.java
@@ -25,7 +25,6 @@ import static org.testng.Assert.fail;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.List;
import javax.annotation.Nonnull;
@@ -112,7 +111,9 @@ public class PluginStateTest {
@Override
public @Nonnull java.util.List<URL> getUpdateURLs() {
try {
- return List.of(new URL("http://example.org/dir"), super.getUpdateURLs().get(0));
+ final URL u = super.getUpdateURLs().get(0);
+ assert u != null;
+ return CollectionSupport.listOf(new URL("http://example.org/dir"), u);
} catch (final MalformedURLException e) {
fail(e.toString());
return super.getUpdateURLs();
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/RollbackTester.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/RollbackTester.java
index 41674b6fc..603df2b76 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/RollbackTester.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/RollbackTester.java
@@ -66,7 +66,10 @@ public class RollbackTester {
final IdPModule enabled2 = new TestModule("enabled2", null, new ModuleException());
final IdPModule disabled1 = new TestModule("disabled1", null, null);
final IdPModule disabled2 = new TestModule("disablde2", new ModuleException(), null);
- final ModuleContext ctx = new ModuleContext(mc.toString());
+ final String mcs = mc.toString();
+ final String parentString = parent.toString();
+ assert mcs!=null && parentString!=null;
+ final ModuleContext ctx = new ModuleContext(mcs);
try {
assertFalse(from.toFile().exists());
@@ -82,7 +85,7 @@ public class RollbackTester {
assertFalse(disabled1.isEnabled(ctx));
assertFalse(disabled2.isEnabled(ctx));
- try (final RollbackPluginInstall rp = new RollbackPluginInstall(new ModuleContext(parent.toString()), new HashMap<>())) {
+ try (final RollbackPluginInstall rp = new RollbackPluginInstall(new ModuleContext(parentString), new HashMap<>())) {
rp.getFilesCopied().add(copied);
rp.getFilesRenamedAway().add(renamed);
rp.getModulesDisabled().add(disabled1);
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TrustStoreTest.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TrustStoreTest.java
index 05979b9cf..e7923c56e 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TrustStoreTest.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TrustStoreTest.java
@@ -30,6 +30,8 @@ import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.Security;
+import javax.annotation.Nonnull;
+
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
@@ -37,6 +39,7 @@ import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import net.shibboleth.idp.installer.plugin.impl.TrustStore.Signature;
+import net.shibboleth.shared.annotation.constraint.NonnullBeforeTest;
import net.shibboleth.shared.component.ComponentInitializationException;
@SuppressWarnings("javadoc")
@@ -44,7 +47,7 @@ public class TrustStoreTest {
private final static String pluginId = "net.shibboleth.plugin.test";
- private Path dir;
+ @NonnullBeforeTest private Path dir;
@BeforeClass public void setup() throws IOException {
@@ -76,12 +79,18 @@ public class TrustStoreTest {
Files.deleteIfExists(dir.resolve("credentials").resolve(pluginId).resolve("truststore.asc"));
}
+ @Nonnull private Path getDir() {
+ assert dir != null;
+ return dir;
+ }
+
@Test public void signatureAbsentTest() throws ComponentInitializationException, IOException {
final TrustStore ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setPluginId(pluginId);
ts.initialize();
try (InputStream sigStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico.asc")) {
+ assert sigStream!=null;
final Signature signature = TrustStore.signatureOf(sigStream);
assertFalse(ts.contains(signature));
}
@@ -97,10 +106,11 @@ public class TrustStoreTest {
@Test public void signaturePresentTest() throws ComponentInitializationException, IOException {
populateKeyStore();
final TrustStore ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setPluginId(pluginId);
ts.initialize();
- try( final InputStream sigStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico.asc")) {
+ try(final InputStream sigStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico.asc")) {
+ assert sigStream!=null;
final Signature signature = TrustStore.signatureOf(sigStream);
assertTrue(ts.contains(signature));
}
@@ -109,7 +119,7 @@ public class TrustStoreTest {
@Test public void signingTest() throws ComponentInitializationException, IOException {
populateKeyStore();
final TrustStore ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setPluginId(pluginId);
ts.initialize();
try( final InputStream sigStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico.asc");
@@ -117,7 +127,8 @@ public class TrustStoreTest {
final InputStream dataStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico");
final InputStream dataStream2 = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico")) {
- Signature badSig = TrustStore.signatureOf(badSigStream);
+ assert badSigStream!= null && sigStream != null;
+ final Signature badSig = TrustStore.signatureOf(badSigStream);
assertTrue(ts.contains(badSig));
assertFalse(ts.checkSignature(dataStream, badSig));
assertTrue(ts.checkSignature(dataStream2, TrustStore.signatureOf(sigStream)));
@@ -128,23 +139,24 @@ public class TrustStoreTest {
populateKeyStore();
final Signature signature;
try( final InputStream sigStream = TrustStoreTest.class.getResourceAsStream("/net/shibboleth/idp/installer/plugin/shib.ico.asc")) {
+ assert sigStream!=null;
signature = TrustStore.signatureOf(sigStream);
}
TrustStore ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setPluginId(pluginId);
ts.initialize();
assertTrue(ts.contains(signature));
ts.saveStore();
ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setPluginId(pluginId);
ts.initialize();
assertTrue(ts.contains(signature));
ts = new TrustStore();
- ts.setIdpHome(dir);
+ ts.setIdpHome(getDir());
ts.setTrustStore(dir.resolve("credentials").resolve(pluginId).resolve("truststore.asc").toString());
ts.setPluginId(pluginId);
ts.initialize();
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list