[java-identity-provider] 04/04: IDP-2121 Future Proofing the Module Plugin infrastructure for Future SP use

Rod Widdowson rdw at steadingsoftware.com
Tue Jun 6 14:12:30 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=dcfa25251bc5210e019058b3f8af4ca0d34262df

commit dcfa25251bc5210e019058b3f8af4ca0d34262df
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Tue Jun 6 14:02:23 2023 +0100

    IDP-2121 Future Proofing the Module Plugin infrastructure for Future SP use
    
    https://shibboleth.atlassian.net/browse/IDP-2121
    
    Move the Module stuff down from the IdP to java-shib-profile
    and make appropriatre IdP level changes.  As many classes as possible
    are retained where it makes sense but many of them are deprecated.
---
 .../shibboleth/idp/module/AbstractIdPModule.java   | 564 +--------------------
 .../java/net/shibboleth/idp/module/IdPModule.java  | 188 +------
 .../net/shibboleth/idp/module/ModuleContext.java   | 132 +----
 .../net/shibboleth/idp/module/ModuleException.java |   6 +-
 .../idp/module/PropertyDrivenIdPModule.java        |   2 +
 .../java/net/shibboleth/idp/module/BadModule.java  |   2 +
 .../java/net/shibboleth/idp/module/BadModule2.java |   2 +
 .../net/shibboleth/idp/module/IdPModuleTest.java   |   8 +-
 .../java/net/shibboleth/idp/module/TestModule.java |   2 +
 .../net/shibboleth/idp/plugin/IdPPluginTest.java   |   2 +-
 .../java/net/shibboleth/idp/plugin/TestPlugin.java |   2 +-
 .../idp/admin/impl/LogImplementationDetails.java   |   2 +-
 .../shibboleth/idp/module/impl/CoreIdPModule.java  |   2 +-
 .../idp/module/impl/PluginIdPModule.java           |   2 +-
 idp-cli/pom.xml                                    |   6 +
 .../shibboleth/idp/cli/impl/ModuleManagerCLI.java  |   8 +-
 idp-conf-impl/pom.xml                              |  16 +-
 .../shibboleth/idp/module/admin/impl/Hello.java    |   2 +-
 .../idp/module/admin/impl/UnlockKeys.java          |   2 +-
 .../net/shibboleth/idp/module/authn/impl/Demo.java |   2 +-
 .../net/shibboleth/idp/module/authn/impl/Duo.java  |   2 +-
 .../idp/module/authn/impl/IPAddress.java           |   2 +-
 .../net/shibboleth/idp/module/authn/impl/MFA.java  |   2 +-
 .../shibboleth/idp/module/authn/impl/Password.java |   2 +-
 .../shibboleth/idp/module/authn/impl/SPNEGO.java   |   2 +-
 .../net/shibboleth/idp/module/authn/impl/X509.java |   2 +-
 .../idp/module/core/impl/CommandLine.java          |   2 +-
 .../net/shibboleth/idp/module/core/impl/Core.java  |   4 +-
 .../idp/module/core/impl/EditWebApp.java           |   2 +-
 .../shibboleth/idp/module/core/impl/UserPrefs.java |   2 +-
 .../idp/module/intercept/impl/Consent.java         |   2 +-
 .../idp/module/intercept/impl/ContextCheck.java    |   2 +-
 .../module/intercept/impl/ExpiringPassword.java    |   2 +-
 .../idp/module/intercept/impl/Impersonate.java     |   2 +-
 .../idp/module/intercept/impl/Warning.java         |   2 +-
 .../shibboleth/idp/module/profile/impl/CAS.java    |   2 +-
 .../idp/installer/impl/CurrentInstallState.java    |   2 +-
 .../shibboleth/idp/installer/impl/V5Install.java   |   4 +-
 .../idp/installer/plugin/impl/PluginInstaller.java |   8 +-
 .../plugin/impl/RollbackPluginInstall.java         |   6 +-
 .../idp/installer/plugin/impl/RollbackTester.java  |   4 +-
 .../idp/installer/plugin/impl/TestModule.java      |   4 +-
 42 files changed, 85 insertions(+), 929 deletions(-)

diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
index f29efd1b4..d70aa8689 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/AbstractIdPModule.java
@@ -17,55 +17,18 @@
 
 package net.shibboleth.idp.module;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.FileAlreadyExistsException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.StandardOpenOption;
-import java.security.DigestOutputStream;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Objects;
-
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.commons.lang3.SystemUtils;
-import org.apache.hc.client5.http.classic.methods.HttpGet;
-import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
-import org.apache.hc.client5.http.protocol.HttpClientContext;
-import org.apache.hc.core5.http.ClassicHttpResponse;
-import org.opensaml.security.httpclient.HttpClientSecuritySupport;
-import org.slf4j.Logger;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.util.ResourceUtils;
 
 import net.shibboleth.idp.Version;
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.profile.module.AbstractModule;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.annotation.constraint.NotLive;
-import net.shibboleth.shared.annotation.constraint.Unmodifiable;
-import net.shibboleth.shared.collection.CollectionSupport;
-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.ConnectionClosingInputStream;
 
 /**
  * {@link IdPModule} base class implementing basic file management.
  * 
  * @since 4.1.0
  */
-public abstract class AbstractIdPModule implements IdPModule {
+public abstract class AbstractIdPModule extends AbstractModule implements IdPModule {
 
     /** Extension for preserving user files. */
     @Nonnull @NotEmpty public static final String IDPSAVE_EXT = ".idpsave";
@@ -73,529 +36,8 @@ public abstract class AbstractIdPModule implements IdPModule {
     /** Base extension for adding new default files. */
     @Nonnull @NotEmpty public static final String IDPNEW_EXT_BASE = ".idpnew";
 
-    /** Class logger. */
-    @Nonnull private Logger log = LoggerFactory.getLogger(AbstractIdPModule.class);
-    
-    /** Module resources. */
-    @Nonnull private Collection<ModuleResource> moduleResources;
-    
-    /** Version-aware extension for new files added. */
-    @Nonnull private String idpNewExt;
-    
-    /** Constructor. */
     public AbstractIdPModule() {
-        moduleResources = CollectionSupport.emptyList();
-        final String version = Version.getVersion();
-        idpNewExt = version != null ? IDPNEW_EXT_BASE + "-" + version.replace(".", "") : IDPNEW_EXT_BASE;
-    }
-    
-    /** {@inheritDoc} */
-    @Nonnull @NotLive @Unmodifiable public Collection<ModuleResource> getResources() {
-        return moduleResources;
-    }
-    
-    /**
-     * Sets the module resources to manage.
-     * 
-     * @param resources resources to manage
-     */
-    public void setResources(@Nullable @NonnullElements final Collection<BasicModuleResource> resources) {
-        if (resources != null) {
-            moduleResources = CollectionSupport.copyToList(resources);
-        } else {
-            moduleResources = CollectionSupport.emptyList();
-        }
-    }
-    
-    /** {@inheritDoc} */
-    public boolean isEnabled(@Nonnull final ModuleContext moduleContext) {
-        
-        log.debug("Module {} checking enabled status", getId());
-        
-        if (moduleResources.isEmpty()) {
-            log.debug("Module {} is always enabled", getId());
-            return true;
-        }
-
-        for (final ModuleResource resource : moduleResources) {
-            
-            if (resource.isOptional()) {
-                continue;
-            }
-
-            if (moduleContext.getInstallLocation().startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
-                final ClassPathResource cp;
-                if (moduleContext.getInstallLocation().equals(ResourceUtils.CLASSPATH_URL_PREFIX)) {
-                    cp = new ClassPathResource(resource.getDestination().toString());
-                } else {
-                    cp = (ClassPathResource) new ClassPathResource(
-                            moduleContext.getInstallLocation().substring(
-                                    ResourceUtils.CLASSPATH_URL_PREFIX.length())).createRelative(
-                                            resource.getDestination().toString());
-                }
-                
-                if (!cp.exists()) {
-                    log.debug("Module {}: resource destination {} missing, module is disabled", getId(),
-                            ResourceUtils.CLASSPATH_URL_PREFIX + cp.getPath());
-                    return false;
-                }
-            } else {
-                final Path resolved = Path.of(moduleContext.getInstallLocation()).resolve(resource.getDestination());
-                if (SystemUtils.IS_OS_WINDOWS && resource.isWindows() && !resolved.toFile().exists()) {
-                    log.debug("Module {}: resource destination {} missing, module is disabled", getId(), resolved);
-                    return false;
-                }
-                if (!SystemUtils.IS_OS_WINDOWS && resource.isNonWindows() && !resolved.toFile().exists()) {
-                    log.debug("Module {}: resource destination {} missing, module is disabled", getId(), resolved);
-                    return false;
-                }
-            }
-        }
-        
-        log.debug("Module {} is enabled", getId());
-        return true;
+        super(Version.getVersion(), IDPNEW_EXT_BASE, IDPSAVE_EXT);
     }
     
-    /** {@inheritDoc} */
-    @Nonnull @NonnullElements public Map<ModuleResource, ResourceResult> enable(
-            @Nonnull final ModuleContext moduleContext) throws ModuleException {
-        
-        if (moduleContext.getInstallLocation().startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
-            throw new ModuleException("IdP location is a classpath");
-        }
-        
-        if (isHttpClientRequired() && moduleContext.getHttpClient() == null) {
-            throw new ModuleException("HTTP client required but not available");
-        }
-        
-        log.debug("Module {} enabling", getId());
-        
-        final Map<ModuleResource,ResourceResult> results;
-        
-        if (!moduleResources.isEmpty()) {
-            results = new LinkedHashMap<>(moduleResources.size());
-
-            for (final ModuleResource resource : moduleResources) {
-                if (SystemUtils.IS_OS_WINDOWS) {
-                    if (resource.isWindows()) {
-                        results.put(resource, ((BasicModuleResource) resource).enable(moduleContext));
-                    } else {
-                        log.debug("Module {}: skipping non-Windows resource {}", getId(), resource);
-                    }
-                } else {
-                    if (resource.isNonWindows()) {
-                        results.put(resource, ((BasicModuleResource) resource).enable(moduleContext));
-                    } else {
-                        log.debug("Module {}: skipping Windows resource {}", getId(), resource);
-                    }
-                }
-            }
-        } else {
-            results = CollectionSupport.emptyMap();
-        }
-        
-        log.debug("Module {} enabled", getId());
-        assert results != null;
-        return results;
-    }
-
-    /** {@inheritDoc} */
-    @Nonnull @NonnullElements public Map<ModuleResource, ResourceResult> disable(
-            @Nonnull final ModuleContext moduleContext, final boolean clean) throws ModuleException {
-
-        if (moduleContext.getInstallLocation().startsWith(ResourceUtils.CLASSPATH_URL_PREFIX)) {
-            throw new ModuleException("IdP location is a classpath");
-        }
-
-        log.debug("Module {} disabling", getId());
-
-        final Map<ModuleResource,ResourceResult> results;
-        
-        if (!moduleResources.isEmpty()) {
-            results = new LinkedHashMap<>(moduleResources.size());
-            for (final ModuleResource resource : moduleResources) {
-                if (SystemUtils.IS_OS_WINDOWS) {
-                    if (resource.isWindows()) {
-                        results.put(resource, ((BasicModuleResource) resource).disable(moduleContext, clean));
-                    }
-                } else {
-                    if (resource.isNonWindows()) {
-                        results.put(resource, ((BasicModuleResource) resource).disable(moduleContext, clean));
-                    }
-                }
-            }
-        } else {
-            results = CollectionSupport.emptyMap();
-        }
-        
-        log.debug("Module {} disabled", getId());
-        assert results != null;
-        return results;
-    }
-
-    /** {@inheritDoc} */
-    @Override
-    public boolean equals(final Object obj) {
-        return obj instanceof IdPModule && Objects.equals(getId(), ((IdPModule) obj).getId());
-    }
-
-
-    /** {@inheritDoc} */
-    @Override
-    public int hashCode() {
-        return Constraint.isNotNull(getId(), "ID cannot be null").hashCode();
-    }
-    
-    /** {@inheritDoc} */
-    @Override
-    public String toString() {
-        return "IdPModule " + getId();
-    }
-
-    /**
-     * Models a specific resource managed by a module.
-     */
-    class BasicModuleResource implements ModuleResource {
-        
-        /** Source. */
-        @Nonnull @NotEmpty private final String source;
-        
-        /** Destination. */
-        @Nonnull private final Path destination;
-        
-        /** Replacement criteria. */
-        private final boolean replace;
-
-        /** Optional criteria. */
-        private final boolean optional;
-
-        /** Executable criteria. */
-        private final boolean executable;
-        
-        /** Process on Windows? */
-        private final boolean windows;
-
-        /** Process on non-Windows? */
-        private final boolean nonwindows;
-
-        /**
-         * Constructor.
-         *
-         * @param src source
-         * @param dest destination
-         * @param shouldReplace whether to replace when enabling
-         * @param isOptional whether the resource is optional
-         * @param isExecutable whether the resource is executable
-         * @param isWindows whether the resource should be processed on Windows
-         * @param isNonWindows whether the resource should be processed on non-Windows platforms
-         */
-        public BasicModuleResource(@Nonnull @NotEmpty final String src, @Nonnull final Path dest,
-                final boolean shouldReplace, final boolean isOptional, final boolean isExecutable,
-                final boolean isWindows, final boolean isNonWindows) {
-            source = Constraint.isNotNull(StringSupport.trimOrNull(src), "Source cannot be null");
-            destination = Constraint.isNotNull(dest, "Destination cannot be null");
-            replace = shouldReplace;
-            optional = isOptional;
-            executable = isExecutable;
-            windows = isWindows;
-            nonwindows = isNonWindows;
-        }
-
-        /** {@inheritDoc} */
-        public int hashCode() {
-            return source.hashCode();
-        }
-
-        /** {@inheritDoc} */
-        public boolean equals(final Object obj) {
-            if (obj instanceof ModuleResource) {
-                return source.equals(((ModuleResource) obj).getSource()) &&
-                        destination.equals(((ModuleResource) obj).getDestination());
-            }
-            return false;
-        }
-
-        /** {@inheritDoc} */
-        @Nonnull public String getSource() {
-            return source;
-        }
-        
-        /** {@inheritDoc} */
-        @Nonnull public Path getDestination() {
-            return destination;
-        }
-        
-        /** {@inheritDoc} */
-        public boolean isReplace() {
-            return replace;
-        }
-
-        /** {@inheritDoc} */
-        public boolean isOptional() {
-            return optional;
-        }
-
-        /** {@inheritDoc} */
-        public boolean isExecutable() {
-            return executable;
-        }
-
-        /** {@inheritDoc} */
-        public boolean isWindows() {
-            return windows;
-        }
-
-        /** {@inheritDoc} */
-        public boolean isNonWindows() {
-            return nonwindows;
-        }
-
-        /**
-         * Gets whether the resource has been altered at its destination from the source material.
-         * 
-         * @param moduleContext context for module operations
-         * 
-         * @return true iff the resource has been changed
-         */
-        public boolean hasChanged(@Nonnull final ModuleContext moduleContext) {
-
-            try (final InputStream dest = getDestinationStream(moduleContext)) {
-                if (dest != null) {
-                    final byte[] destHash;
-                    
-                    final MessageDigest digest = MessageDigest.getInstance("SHA1");
-                    try (final OutputStream destSink = OutputStream.nullOutputStream();
-                            final DigestOutputStream destDigest = new DigestOutputStream(destSink, digest)) {
-                        dest.transferTo(destDigest);
-                        destHash = digest.digest();
-                    }
-                    
-                    try (final InputStream src = getSourceStream(moduleContext)) {
-                        if (src != null) {
-                            try (final OutputStream srcSink = OutputStream.nullOutputStream();
-                                    final DigestOutputStream srcDigest = new DigestOutputStream(srcSink, digest)) {
-                                src.transferTo(srcDigest);
-                                return !Arrays.equals(destHash, digest.digest());
-                            }
-                        }
-                        log.debug("Module {} resource {} does not exist at source", getId(), source);
-                        return true;
-                    }
-                }
-                
-                log.debug("Module {} resource {} does not exist at destination", getId(), source);
-                return false;
-            } catch (final IOException e) {
-                log.error("Module {} resource {} raised error while checking contents", getId(), source, e);
-                return true;
-            } catch (final NoSuchAlgorithmException e) {
-                log.error("Module {} resource {} raised error while checking contents", getId(), source, e);
-                return true;
-            }
-        }
-        
-        /**
-         * Access the source as a stream.
-         * 
-         * @param moduleContext context for module operations
-         * 
-         * @return a stream or null if the source does not exist
-         * 
-         * @throws IOException on failure
-         */
-        @Nullable private InputStream getSourceStream(@Nonnull final ModuleContext moduleContext)
-                throws IOException {
-            
-            if (source.startsWith("https://") || source.startsWith("http://")) {
-                try {
-                    return connect(moduleContext, new URI(source));
-                } catch (final URISyntaxException e) {
-                    throw new IOException(e);
-                }
-            }
-            return AbstractIdPModule.this.getClass().getResourceAsStream(source);
-        }
-
-        /**
-         * Connect to the given URI and return the HTTP response stream.
-         *
-         * @param moduleContext module context
-         * @param uri resource location
-         * 
-         * @return input stream of response
-         * 
-         * @throws IOException on errors
-         */
-        @Nonnull private InputStream connect(@Nonnull final ModuleContext moduleContext, @Nonnull final URI uri)
-                throws IOException {
-            
-            final HttpClientContext clientContext = HttpClientContext.create();
-            assert clientContext != null;
-            HttpClientSecuritySupport.marshalSecurityParameters(clientContext,
-                    moduleContext.getHttpClientSecurityParameters(), true);
-            ClassicHttpResponse response = null;
-            try {
-                log.debug("Module {} fetching HTTP resource {}", getId(), uri);
-                final HttpGet request = new HttpGet(uri);
-                response = Constraint.isNotNull(
-                        moduleContext.getHttpClient(), "HttpClient cannot be null").executeOpen(null, request, clientContext);
-                HttpClientSecuritySupport.checkTLSCredentialEvaluated(clientContext, request.getScheme());
-                if (response.getCode() != 200) {
-                    throw new IOException("HTTP request was unsuccessful");
-                }
-                
-                // The response socket should be closed after the stream is closed.
-                final InputStream ret = new ConnectionClosingInputStream(response);
-                response = null;
-                return ret;
-            } finally {
-                if (response != null && CloseableHttpResponse.class.isInstance(response)) {
-                    try {
-                        CloseableHttpResponse.class.cast(response).close();
-                    } catch (final IOException e) {
-                        log.debug("Error closing HttpResponse", e);
-                    }
-                }
-            }
-        }
-        
-        /**
-         * Access the destination as a stream.
-         * 
-         * @param moduleContext context for module operations
-         * 
-         * @return a stream or null if the destination does not exist
-         * 
-         * @throws IOException on failure
-         */
-        @Nullable private InputStream getDestinationStream(@Nonnull final ModuleContext moduleContext)
-                throws IOException {
-            
-            final Path destPath = Path.of(moduleContext.getInstallLocation()).resolve(destination);
-            if (Files.exists(destPath)) {
-                try {
-                    return Files.newInputStream(destPath, StandardOpenOption.READ);
-                } catch (final IOException e) {
-                    log.error("Module {} unable to read destination resource {}", getId(), destPath, e);
-                }
-            }
-            
-            return null;
-        }
-
-        /**
-         * Enable the supplied resource.
-         * 
-         * @param moduleContext module context
-         * 
-         * @return result of operation
-         * 
-         * @throws ModuleException if an error occurs
-         */
-        @Nonnull private ResourceResult enable(@Nonnull final ModuleContext moduleContext) throws ModuleException {
-            log.debug("Module {} enabling resource {}", getId(), source);
-
-            final boolean hasChanged = hasChanged(moduleContext);
-            
-            try (final InputStream srcStream = getSourceStream(moduleContext)) {
-                if (srcStream == null) {
-                    throw new IOException("Source stream was null");
-                }
-
-                final Path destPath;
-                final ResourceResult result;
-                
-                if (hasChanged) {
-                    if (isReplace()) {
-                        destPath = Path.of(moduleContext.getInstallLocation()).resolve(destination);
-                        final Path savedPath = destPath.resolveSibling(destPath.getFileName() + IDPSAVE_EXT);
-                        if (savedPath.toFile().exists()) {
-                            throw new IOException(savedPath + " exists, aborting");
-                        }
-                        Files.copy(destPath, savedPath, StandardCopyOption.REPLACE_EXISTING);
-                        log.debug("Module {} preserved {}", getId(), destPath);
-                        result = ResourceResult.REPLACED;
-                    } else {
-                        final Path basePath = Path.of(moduleContext.getInstallLocation()).resolve(destination);
-                        destPath = basePath.resolveSibling(basePath.getFileName() + idpNewExt);
-                        result = ResourceResult.ADDED;
-                    }
-                    
-                } else {
-                    destPath = Path.of(moduleContext.getInstallLocation()).resolve(destination);
-                    result = ResourceResult.CREATED;
-                }
-                
-                if (!destPath.startsWith(moduleContext.getInstallLocation())) {
-                    log.error("Module {} attempted to create file outside of IdP installation: {}", getId(), destPath);
-                    throw new ModuleException("Module asked to create file outside of IdP installation");
-                }
-
-                try {
-                    Files.createDirectories(destPath.getParent());
-                } catch (final IOException e) {
-                    if (e instanceof FileAlreadyExistsException) {
-                        log.info("Path {} existed but not directory, assuming symlink", destPath.getParent());
-                    } else {
-                        throw e;
-                    }
-                }
-                Files.copy(srcStream, destPath, StandardCopyOption.REPLACE_EXISTING);
-                if (isExecutable()) {
-                    destPath.toFile().setExecutable(true);
-                }
-                log.debug("Module {} created {}", getId(), destPath);
-                return result;
-            } catch (final IOException e) {
-                log.error("Module {} unable to enable resource {}", getId(), source);
-                throw new ModuleException(e);
-            }
-        }
-
-        /**
-         * Disable the supplied resource, either removing or renaming.
-         * 
-         * @param moduleContext module context
-         * @param clean true iff resource should be removed
-         * 
-         * @return result of operation
-         * 
-         * @throws ModuleException if an error occurs
-         */
-        @Nonnull private ResourceResult disable(@Nonnull final ModuleContext moduleContext, final boolean clean)
-                throws ModuleException {
-            
-            final ResourceResult result;
-            final Path resolved = Path.of(moduleContext.getInstallLocation()).resolve(destination);
-            log.debug("Module {} resolved resource destination {}", getId(), resolved);
-            if (Files.exists(resolved)) {
-                try {
-                    if (clean || !hasChanged(moduleContext)) {
-                        log.debug("Module {} removing resource {}", getId(), resolved);
-                        Files.delete(resolved);
-                        result = ResourceResult.REMOVED;
-                    } else {
-                        log.debug("Module {} backing up resource {}", getId(), resolved);
-                        Files.move(resolved, resolved.resolveSibling(resolved.getFileName() + IDPSAVE_EXT),
-                                StandardCopyOption.REPLACE_EXISTING);
-                        result = ResourceResult.SAVED;
-                    }
-                    final Path idpnewVersion = resolved.resolveSibling(resolved.getFileName() + idpNewExt);
-                    if (Files.exists(idpnewVersion)) {
-                        Files.delete(idpnewVersion);
-                    }
-                } catch (final IOException e) {
-                    log.error("Module {} failed to disable {}", getId(), resolved);
-                    throw new ModuleException(e);
-                }
-            } else {
-                log.debug("Module {} resource {} missing, ignoring", getId(), resolved);
-                result = ResourceResult.MISSING;
-            }
-            
-            return result;
-        }
-        
-    }
-
 }
\ No newline at end of file
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
index 5528dba35..6fcce6131 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/IdPModule.java
@@ -17,195 +17,11 @@
 
 package net.shibboleth.idp.module;
 
-import java.nio.file.Path;
-import java.util.Collection;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.annotation.constraint.NotLive;
-import net.shibboleth.shared.annotation.constraint.Unmodifiable;
-import net.shibboleth.shared.component.IdentifiedComponent;
+import net.shibboleth.profile.module.Module;
 
 /**
  * This interface is exported (via the service API) by every IdP module.
  * 
  * @since 4.1.0
  */
-public interface IdPModule extends IdentifiedComponent {
-    
-    /**
-     * Gets module name.
-     * 
-     * @param moduleContext optional context for supplying i18n input
-     * 
-     * @return a human-readable name for the module
-     */
-    @Nonnull @NotEmpty String getName(@Nullable final ModuleContext moduleContext);
-    
-    /**
-     * Gets module description.
-     * 
-     * @param moduleContext optional context for supplying i18n input
-     * 
-     * @return a human-readable description for the module
-     */
-    @Nullable @NotEmpty String getDescription(@Nullable final ModuleContext moduleContext);
-
-    /**
-     * Gets module URL.
-     * 
-     * @return a URL for obtaining additional information about the module
-     */
-    @Nullable @NotEmpty String getURL();
-    
-    /**
-     * Gets the plugin name of the module's owner, if the module is provided by a plugin.
-     * 
-     * @return plugin ID, if any
-     */
-    @Nullable @NotEmpty String getOwnerId();
-    
-    /**
-     * Gets whether module enablement requires access to an {@link org.apache.hc.client5.http.classic.HttpClient}.
-     * 
-     * @return true iff enabling the module requires HTTP client
-     */
-    boolean isHttpClientRequired();
-
-    /**
-     * Gets resources managed by this module.
-     * 
-     * @return resources managed by this module
-     */
-    @Nonnull @NonnullElements @NotLive @Unmodifiable public Collection<ModuleResource> getResources();
-    
-    /**
-     * Gets whether the module is enabled.
-     * 
-     * <p>The status of "enabled" is meant to reflect whether a deployer has previously
-     * or implicitly enabled the module, not necessarily whether the module is fully or
-     * properly configured or in use.</p>
-     * 
-     * @param moduleContext module context
-     * 
-     * @return true iff the module is enabled
-     */
-    boolean isEnabled(@Nonnull final ModuleContext moduleContext);
-    
-    /**
-     * Enable the module.
-     * 
-     * <p>This operation MUST be idempotent.</p>
-     * 
-     * @param moduleContext module context
-     * 
-     * @return summary of resource results
-     * 
-     * @throws ModuleException if not successful 
-     */
-    @Nonnull @NonnullElements Map<ModuleResource,ResourceResult> enable(@Nonnull final ModuleContext moduleContext)
-            throws ModuleException;
-
-    /**
-     * Disable the module.
-     * 
-     * <p>This operation MUST be idempotent with respect to the value of the input parameter.</p>
-     * 
-     * @param moduleContext module context
-     * @param clean if true, the module should attempt to fully remove traces of previous
-     *  use in a potentially destructive fashion
-     * 
-     * @return summary of resource results
-     * 
-     * @throws ModuleException if not successful 
-     */
-    @Nonnull @NonnullElements Map<ModuleResource,ResourceResult> disable(@Nonnull final ModuleContext moduleContext,
-            final boolean clean) throws ModuleException;
-    
-    /**
-     * Interface to a resource managed by the module.
-     */
-    interface ModuleResource {
-        
-        /**
-         * Gets the source location of the resource.
-         * 
-         * <p>This may be a URL or a local path that will be assumed a classpath.</p>
-         * 
-         * @return source location
-         */
-        @Nonnull public String getSource();
-        
-        /**
-         * Gets the destination for the resource.
-         * 
-         * @return destination path
-         */
-        @Nonnull public Path getDestination();
-        
-        /**
-         * Gets whether the resource should be config(replace) or config(noreplace) in RPM specfile parlance.
-         * 
-         * @return true iff the resource should be replaced with the original preserved
-         */
-        public boolean isReplace();
-
-        /**
-         * Gets whether the resource, if missing, should not act as a module-disabled signal.
-         * 
-         * @return true iff the resource may be removed by a deployer without disabling the module
-         */
-        public boolean isOptional();
-
-        /**
-         * Gets whether the resource should be marked executable where applicable.
-         * 
-         * @return true iff the resource should be marked executable
-         */
-        public boolean isExecutable();
-
-        /**
-         * Gets whether the resource should be processed on Windows.
-         * 
-         * @return true iff the resource should be processed on Windows
-         * 
-         * @since 5.0.0
-         */
-        public boolean isWindows();
-
-        /**
-         * Gets whether the resource should be processed on non-Windows platforms.
-         * 
-         * @return true iff the resource should be processed on non-Windows platforms
-         * 
-         * @since 5.0.0
-         */
-        public boolean isNonWindows();
-    }
- 
-    /** Resource management outcome. */
-    public enum ResourceResult {
-        /** Resource was created. */
-        CREATED,
-        
-        /** Resource was created and old resource saved. */
-        REPLACED,
-        
-        /** Resource was created alongside original. */
-        ADDED,
-        
-        /** Resource was removed. */
-        REMOVED,
-        
-        /** Old resource was preserved. */
-        SAVED,
-        
-        /** Resource was missing. */
-        MISSING,
-    };
-    
-}
\ No newline at end of file
+public interface IdPModule extends Module {}
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
index f80a77a25..51ca771f8 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleContext.java
@@ -17,142 +17,20 @@
 
 package net.shibboleth.idp.module;
 
-import java.io.PrintStream;
-import java.util.List;
-import java.util.Locale.LanguageRange;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-
-import org.apache.hc.client5.http.classic.HttpClient;
-import org.opensaml.security.httpclient.HttpClientSecurityParameters;
-
-import net.shibboleth.shared.annotation.constraint.NonnullElements;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.annotation.constraint.NotLive;
-import net.shibboleth.shared.annotation.constraint.Unmodifiable;
-import net.shibboleth.shared.collection.CollectionSupport;
-import net.shibboleth.shared.logic.Constraint;
-
 /**
  * Information required to perform some module operations.
  * 
  * @since 4.1.0
  */
-public final class ModuleContext {
-
-    /** IdP installation root. */
-    @Nonnull private String idpHome;
-    
-    /** HttpClient if needed. */
-    @Nullable private HttpClient httpClient;
-    
-    /** HTTP security parameters. */
-    @Nullable private HttpClientSecurityParameters httpClientSecurityParams;
-    
-    /** Language expressions to use for i18n. */
-    @Nonnull @NonnullElements private List<LanguageRange> languageRanges;
-    
-    /** Output stream for sending output to the module consumer. */
-    @Nullable private PrintStream messageStream;
+ at Deprecated(forRemoval = true, since = "5.0.0")
+public final class ModuleContext extends net.shibboleth.profile.module.ModuleContext {
 
     /**
      * Constructor.
      *
-     * @param home location of IdP install
-     */
-    public ModuleContext(@Nonnull @NotEmpty final String home) {
-        idpHome = Constraint.isNotEmpty(home, "Home location cannot be null or empty");
-        languageRanges = CollectionSupport.emptyList();
-    }
-    
-    /**
-     * Gets software installation location.
-     * 
-     * @return install path
-     * 
-     * @since 4.2.0
-     */
-    @Nonnull @NotEmpty public String getInstallLocation() {
-        return idpHome;
-    }
-    
-    /**
-     * Gets an {@link HttpClient} instance to use if available.
-     * 
-     * @return HTTP client instance
-     */
-    @Nullable public HttpClient getHttpClient() {
-        return httpClient;
-    }
-    
-    /**
-     * Sets an {@link HttpClient} instance to use.
-     * 
-     * @param client client to use
-     */
-    public void setHttpClient(@Nullable final HttpClient client) {
-        httpClient = client;
-    }
-
-    /**
-     * Gets {@link HttpClient} security parameters, if any.
-     * 
-     * @return HTTP client security parameters to use
-     */
-    @Nullable public HttpClientSecurityParameters getHttpClientSecurityParameters() {
-        return httpClientSecurityParams;
-    }
-
-    /**
-     * Sets {@link HttpClient} security parameters to use.
-     * 
-     * @param params security parameters
-     */
-    public void setHttpClientSecurityParameters(@Nullable final HttpClientSecurityParameters params) {
-        httpClientSecurityParams = params;
-    }
-    
-    /**
-     * Gets the language ranges to use for i18n.
-     * 
-     * @return language ranges
-     */
-    @Nonnull @NonnullElements @NotLive @Unmodifiable public List<LanguageRange> getLanguageRanges() {
-        return languageRanges;
-    }
-    
-    /**
-     * Sets the language ranges to use for i18n.
-     * 
-     * @param ranges language ranges
-     */
-    public void setLanguageRanges(@Nullable @NonnullElements final List<LanguageRange> ranges) {
-        if (ranges != null) {
-            languageRanges = CollectionSupport.copyToList(ranges);
-        } else {
-            languageRanges = CollectionSupport.emptyList();
-        }
-    }
-
-    /**
-     * Gets the output stream to receive any instructions or additional information after
-     * performing operations.
-     * 
-     * @return output stream, or null
-     */
-    @Nullable public PrintStream getMessageStream() {
-        return messageStream;
-    }
-    
-    /**
-     * Sets the output stream to receive any instructions or additional information after
-     * performing operations.
-     * 
-     * @param stream output stream
+     * @param home
      */
-    public void setMessageStream(@Nullable final PrintStream stream) {
-        messageStream = stream;
+    public ModuleContext(String home) {
+        super(home);
     }
-    
 }
\ No newline at end of file
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleException.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleException.java
index a198e1e98..79bdfbe98 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleException.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/ModuleException.java
@@ -26,14 +26,14 @@ import javax.annotation.concurrent.ThreadSafe;
  * @since 4.1.0
  */
 @ThreadSafe
-public class ModuleException extends Exception {
+ at Deprecated(forRemoval = true, since = "5.0.0")
+public class ModuleException extends net.shibboleth.profile.module.ModuleException {
 
     /** Serial number. */
     private static final long serialVersionUID = 2811724801157828005L;
 
     /** Constructor. */
     public ModuleException() {
-        
     }
 
     /**
@@ -63,5 +63,5 @@ public class ModuleException extends Exception {
     public ModuleException(@Nullable final String message, @Nullable final Exception wrappedException) {
         super(message, wrappedException);
     }
-    
+ 
 }
\ No newline at end of file
diff --git a/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java b/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
index 4ed170efa..bff03880a 100644
--- a/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
+++ b/idp-admin-api/src/main/java/net/shibboleth/idp/module/PropertyDrivenIdPModule.java
@@ -35,6 +35,8 @@ import org.slf4j.Logger;
 
 import com.google.common.base.Strings;
 
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule.java
index 153ebec94..bd5052b8b 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule.java
@@ -19,6 +19,8 @@ package net.shibboleth.idp.module;
 
 import java.io.IOException;
 
+import net.shibboleth.profile.module.ModuleException;
+
 /**
  * Test {@link IdPModule} implementation.
  */
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule2.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule2.java
index d5ef778f8..40622d35f 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule2.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/BadModule2.java
@@ -19,6 +19,8 @@ package net.shibboleth.idp.module;
 
 import java.io.IOException;
 
+import net.shibboleth.profile.module.ModuleException;
+
 /**
  * Test {@link IdPModule} implementation.
  */
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
index 896022d5f..8968c176d 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/IdPModuleTest.java
@@ -57,7 +57,9 @@ import org.testng.annotations.Test;
 import com.google.common.io.ByteStreams;
 
 import net.shibboleth.idp.Version;
-import net.shibboleth.idp.module.IdPModule.ModuleResource;
+import net.shibboleth.profile.module.Module;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.httpclient.HttpClientBuilder;
 import net.shibboleth.shared.testing.RepositorySupport;
 
@@ -169,10 +171,10 @@ public class IdPModuleTest {
         assert url != null;
         Assert.assertEquals(url, "https://wiki.shibboleth.net/confluence/display/IDP4/Home");
         
-        final Iterator<ModuleResource> resources = testModule.getResources().iterator();
+        final Iterator<Module.ModuleResource> resources = testModule.getResources().iterator();
         Assert.assertEquals(testModule.getResources().size(), 2);
         
-        ModuleResource resource = resources.next();
+        net.shibboleth.profile.module.Module.ModuleResource resource = resources.next();
         Assert.assertEquals(resource.getSource(), "/net/shibboleth/idp/module/test.xml");
         Assert.assertEquals(resource.getDestination(), Path.of("conf/test.xml"));
         
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/module/TestModule.java b/idp-admin-api/src/test/java/net/shibboleth/idp/module/TestModule.java
index 9df5cf0e0..232738137 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/module/TestModule.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/module/TestModule.java
@@ -19,6 +19,8 @@ package net.shibboleth.idp.module;
 
 import java.io.IOException;
 
+import net.shibboleth.profile.module.ModuleException;
+
 /**
  * Test {@link IdPModule} implementation.
  */
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/IdPPluginTest.java b/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/IdPPluginTest.java
index e6181dd65..f2df7f4e4 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/IdPPluginTest.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/IdPPluginTest.java
@@ -28,8 +28,8 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.TestModule;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
diff --git a/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/TestPlugin.java b/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/TestPlugin.java
index 10035d8bd..80dca1ab3 100644
--- a/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/TestPlugin.java
+++ b/idp-admin-api/src/test/java/net/shibboleth/idp/plugin/TestPlugin.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.plugin;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.TestModule;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.collection.CollectionSupport;
 
 /**
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/LogImplementationDetails.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/LogImplementationDetails.java
index db7bbae65..95e7641c3 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/LogImplementationDetails.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/admin/impl/LogImplementationDetails.java
@@ -29,8 +29,8 @@ import com.google.common.base.StandardSystemProperty;
 
 import net.shibboleth.idp.Version;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
 import net.shibboleth.idp.plugin.IdPPlugin;
+import net.shibboleth.profile.module.ModuleContext;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.primitive.LoggerFactory;
 
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/CoreIdPModule.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/CoreIdPModule.java
index ad91a9bfd..3b0416ef4 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/CoreIdPModule.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/CoreIdPModule.java
@@ -22,8 +22,8 @@ import java.io.IOException;
 import javax.annotation.Nonnull;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.PropertyDrivenIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 
 /**
diff --git a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/PluginIdPModule.java b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/PluginIdPModule.java
index e97f9421a..891822364 100644
--- a/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/PluginIdPModule.java
+++ b/idp-admin-impl/src/main/java/net/shibboleth/idp/module/impl/PluginIdPModule.java
@@ -22,8 +22,8 @@ import java.io.IOException;
 import javax.annotation.Nonnull;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.PropertyDrivenIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 
 /**
diff --git a/idp-cli/pom.xml b/idp-cli/pom.xml
index 940cb59aa..783f9739c 100644
--- a/idp-cli/pom.xml
+++ b/idp-cli/pom.xml
@@ -45,6 +45,12 @@
             <scope>provided</scope>
         </dependency>
 
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>idp-profile-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
         <dependency>
             <groupId>${shib-shared.groupId}</groupId>
             <artifactId>shib-cli</artifactId>
diff --git a/idp-cli/src/main/java/net/shibboleth/idp/cli/impl/ModuleManagerCLI.java b/idp-cli/src/main/java/net/shibboleth/idp/cli/impl/ModuleManagerCLI.java
index 2df54d925..870776a14 100644
--- a/idp-cli/src/main/java/net/shibboleth/idp/cli/impl/ModuleManagerCLI.java
+++ b/idp-cli/src/main/java/net/shibboleth/idp/cli/impl/ModuleManagerCLI.java
@@ -43,10 +43,10 @@ import com.google.common.base.Strings;
 import net.shibboleth.idp.Version;
 import net.shibboleth.idp.cli.AbstractIdPHomeAwareCommandLine;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.IdPModule.ModuleResource;
-import net.shibboleth.idp.module.IdPModule.ResourceResult;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
+import net.shibboleth.profile.module.Module.ModuleResource;
+import net.shibboleth.profile.module.Module.ResourceResult;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.annotation.constraint.NonnullElements;
 import net.shibboleth.shared.annotation.constraint.NotLive;
 import net.shibboleth.shared.annotation.constraint.Unmodifiable;
diff --git a/idp-conf-impl/pom.xml b/idp-conf-impl/pom.xml
index e50c70280..026eb38a1 100644
--- a/idp-conf-impl/pom.xml
+++ b/idp-conf-impl/pom.xml
@@ -37,6 +37,16 @@
             <artifactId>idp-core</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>idp-profile-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>net.shibboleth</groupId>
+            <artifactId>shib-profile-api</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>${shib-shared.groupId}</groupId>
@@ -130,12 +140,6 @@
             <scope>runtime</scope>
         </dependency>
 
-        <dependency>
-            <groupId>net.shibboleth</groupId>
-            <artifactId>shib-profile-api</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-
         <dependency>
             <groupId>net.shibboleth</groupId>
             <artifactId>shib-metadata-spring</artifactId>
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/Hello.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/Hello.java
index 66ee65aaa..cbbb65217 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/Hello.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/Hello.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.admin.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/UnlockKeys.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/UnlockKeys.java
index 90f362365..9f6840a3f 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/UnlockKeys.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/admin/impl/UnlockKeys.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.admin.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Demo.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Demo.java
index 56cf41bd7..56eb919fa 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Demo.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Demo.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Duo.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Duo.java
index 68236e927..e09ab833c 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Duo.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Duo.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/IPAddress.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/IPAddress.java
index d3d129ccd..341b3e5b1 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/IPAddress.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/IPAddress.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/MFA.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/MFA.java
index 0f19f76e3..30e8489d1 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/MFA.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/MFA.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Password.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Password.java
index 0aec7a533..2ad29f2ec 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Password.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/Password.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/SPNEGO.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/SPNEGO.java
index f79b9b637..32fe80c26 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/SPNEGO.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/SPNEGO.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/X509.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/X509.java
index 106d2b360..166c2fdda 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/X509.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/authn/impl/X509.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.authn.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/CommandLine.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/CommandLine.java
index d7989080b..b54925c6b 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/CommandLine.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/CommandLine.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.core.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/Core.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/Core.java
index 140525ca7..a3abad571 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/Core.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/Core.java
@@ -28,9 +28,9 @@ import javax.annotation.Nonnull;
 import org.springframework.util.ResourceUtils;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/EditWebApp.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/EditWebApp.java
index 0d66a0412..8eda93332 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/EditWebApp.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/EditWebApp.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.core.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/UserPrefs.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/UserPrefs.java
index ceee3b812..7116f9c64 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/UserPrefs.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/core/impl/UserPrefs.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.core.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Consent.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Consent.java
index 06bbb4600..f11390d29 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Consent.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Consent.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.intercept.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ContextCheck.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ContextCheck.java
index 5f0d717cd..47fd98b59 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ContextCheck.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ContextCheck.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.intercept.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ExpiringPassword.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ExpiringPassword.java
index 525527509..e8cf7ad03 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ExpiringPassword.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/ExpiringPassword.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.intercept.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Impersonate.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Impersonate.java
index 0d6c02d2f..bfd084d90 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Impersonate.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Impersonate.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.intercept.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Warning.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Warning.java
index cc0f949ac..d9c3fc3c5 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Warning.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/intercept/impl/Warning.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.intercept.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/profile/impl/CAS.java b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/profile/impl/CAS.java
index 26107ebfd..911491926 100644
--- a/idp-conf-impl/src/main/java/net/shibboleth/idp/module/profile/impl/CAS.java
+++ b/idp-conf-impl/src/main/java/net/shibboleth/idp/module/profile/impl/CAS.java
@@ -20,8 +20,8 @@ package net.shibboleth.idp.module.profile.impl;
 import java.io.IOException;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.module.impl.CoreIdPModule;
+import net.shibboleth.profile.module.ModuleException;
 
 /**
  * {@link IdPModule} implementation.
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CurrentInstallState.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CurrentInstallState.java
index 97d832945..0c6d56ed5 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CurrentInstallState.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CurrentInstallState.java
@@ -47,7 +47,7 @@ import org.slf4j.Logger;
 
 import net.shibboleth.idp.installer.InstallerSupport;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleContext;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.AbstractInitializableComponent;
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/V5Install.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/V5Install.java
index f9bbe311f..ffa786c47 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/V5Install.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/V5Install.java
@@ -56,11 +56,11 @@ import net.shibboleth.idp.installer.metadata.impl.MetadataGenerator;
 import net.shibboleth.idp.installer.metadata.impl.MetadataGeneratorParameters;
 import net.shibboleth.idp.installer.plugin.impl.PluginState;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.plugin.IdPPlugin;
 import net.shibboleth.idp.plugin.InstallableComponentVersion;
 import net.shibboleth.idp.spring.IdPPropertiesApplicationContextInitializer;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.component.UninitializedComponentException;
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 e7342e9e6..09ba84cb6 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
@@ -70,12 +70,12 @@ import net.shibboleth.idp.installer.InstallerSupport;
 import net.shibboleth.idp.installer.impl.BuildWar;
 import net.shibboleth.idp.installer.plugin.impl.TrustStore.Signature;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.IdPModule.ModuleResource;
-import net.shibboleth.idp.module.IdPModule.ResourceResult;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
 import net.shibboleth.idp.plugin.IdPPlugin;
 import net.shibboleth.idp.plugin.InstallableComponentVersion;
+import net.shibboleth.profile.module.Module.ModuleResource;
+import net.shibboleth.profile.module.Module.ResourceResult;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/RollbackPluginInstall.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/RollbackPluginInstall.java
index 076d2c1d1..9540e2f8f 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/RollbackPluginInstall.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/plugin/impl/RollbackPluginInstall.java
@@ -35,10 +35,10 @@ import javax.annotation.Nonnull;
 import org.slf4j.Logger;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.IdPModule.ModuleResource;
-import net.shibboleth.idp.module.IdPModule.ResourceResult;
-import net.shibboleth.idp.module.ModuleContext;
 import net.shibboleth.idp.plugin.IdPPlugin;
+import net.shibboleth.profile.module.Module.ModuleResource;
+import net.shibboleth.profile.module.Module.ResourceResult;
+import net.shibboleth.profile.module.ModuleContext;
 import net.shibboleth.shared.annotation.constraint.Live;
 import net.shibboleth.shared.collection.CollectionSupport;
 import net.shibboleth.shared.collection.Pair;
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 3fcb6c9bf..54819995a 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
@@ -31,8 +31,8 @@ import org.testng.annotations.Test;
 
 import net.shibboleth.idp.installer.InstallerSupport;
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.collection.Pair;
 
 /** Tests for {@link RollbackPluginInstall}. */
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TestModule.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TestModule.java
index cfff1fcf4..de4a9716b 100644
--- a/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TestModule.java
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/plugin/impl/TestModule.java
@@ -24,8 +24,8 @@ import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
 import net.shibboleth.idp.module.IdPModule;
-import net.shibboleth.idp.module.ModuleContext;
-import net.shibboleth.idp.module.ModuleException;
+import net.shibboleth.profile.module.ModuleContext;
+import net.shibboleth.profile.module.ModuleException;
 import net.shibboleth.shared.collection.CollectionSupport;
 
 @SuppressWarnings("javadoc")

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


More information about the commits mailing list