[java-identity-provider] branch main updated: IDP-1671 - Eliminate need to manually identify standard property sources

Scott Cantor cantor.2 at osu.edu
Thu Sep 3 16:24:25 UTC 2020


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

scantor 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=fab47356d096d730e3302e37c54b4202fe1b5cc8

The following commit(s) were added to refs/heads/main by this push:
       new  fab47356d IDP-1671 - Eliminate need to manually identify standard property sources
fab47356d is described below

commit fab47356d096d730e3302e37c54b4202fe1b5cc8
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Thu Sep 3 12:24:15 2020 -0400

    IDP-1671 - Eliminate need to manually identify standard property sources
    
    https://issues.shibboleth.net/jira/browse/IDP-1671
---
 idp-conf/src/main/resources/conf/idp.properties    |  8 +-
 .../{main => test}/resources/conf/idp.properties   |  4 +
 ...IdPPropertiesApplicationContextInitializer.java | 87 ++++++++++++++++------
 3 files changed, 74 insertions(+), 25 deletions(-)

diff --git a/idp-conf/src/main/resources/conf/idp.properties b/idp-conf/src/main/resources/conf/idp.properties
index 29ecb51bb..6c2cc29ed 100644
--- a/idp-conf/src/main/resources/conf/idp.properties
+++ b/idp-conf/src/main/resources/conf/idp.properties
@@ -1,5 +1,9 @@
-# Load any additional property resources from a comma-delimited list
-idp.additionalProperties = /conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/admin/admin.properties, /conf/authn/authn.properties, /conf/authn/duo.properties, /credentials/secrets.properties
+# Auto-load all files matching conf/**/*.properties
+# Disable if you want to manually maintain a list of sources.
+idp.searchForProperties = true
+
+# Load any "outside-tree" property sources from a comma-delimited list
+idp.additionalProperties = /credentials/secrets.properties
 
 # In most cases (and unless noted in the surrounding comments) the
 # commented settings in the distributed files document default behavior.
diff --git a/idp-conf/src/main/resources/conf/idp.properties b/idp-conf/src/test/resources/conf/idp.properties
similarity index 98%
copy from idp-conf/src/main/resources/conf/idp.properties
copy to idp-conf/src/test/resources/conf/idp.properties
index 29ecb51bb..faf48156f 100644
--- a/idp-conf/src/main/resources/conf/idp.properties
+++ b/idp-conf/src/test/resources/conf/idp.properties
@@ -1,3 +1,7 @@
+# Auto-load all files matching conf/**/*.properties
+# Disable if you want to manually maintain a list of sources.
+#idp.searchForProperties = false
+
 # Load any additional property resources from a comma-delimited list
 idp.additionalProperties = /conf/ldap.properties, /conf/saml-nameid.properties, /conf/services.properties, /conf/admin/admin.properties, /conf/authn/authn.properties, /conf/authn/duo.properties, /credentials/secrets.properties
 
diff --git a/idp-core/src/main/java/net/shibboleth/idp/spring/IdPPropertiesApplicationContextInitializer.java b/idp-core/src/main/java/net/shibboleth/idp/spring/IdPPropertiesApplicationContextInitializer.java
index 3d21a4100..a928651c8 100644
--- a/idp-core/src/main/java/net/shibboleth/idp/spring/IdPPropertiesApplicationContextInitializer.java
+++ b/idp-core/src/main/java/net/shibboleth/idp/spring/IdPPropertiesApplicationContextInitializer.java
@@ -19,10 +19,20 @@ package net.shibboleth.idp.spring;
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Properties;
 import java.util.TreeSet;
+import java.util.function.BiPredicate;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
@@ -45,7 +55,8 @@ import net.shibboleth.utilities.java.support.primitive.StringSupport;
  * An {@link ApplicationContextInitializer} which appends properties to the application context's environment.
  * 
  * Properties are loaded from {@link #IDP_PROPERTIES} as well as additional property files specified by
- * {@link #IDP_ADDITIONAL_PROPERTY}.
+ * {@link #IDP_ADDITIONAL_PROPERTY} if set, or if absent, by locating all files under idp.home/conf/ that
+ * end in ".properties".
  * 
  * The {@link #IDP_PROPERTIES} file is searched for in the well location returned by {@link #getSearchLocation()}.
  * 
@@ -64,6 +75,9 @@ public class IdPPropertiesApplicationContextInitializer
     /** Property that points to more property sources. */
     @Nonnull @NotEmpty public static final String IDP_ADDITIONAL_PROPERTY = "idp.additionalProperties";
 
+    /** Property that controls auto-search for property sources. */
+    @Nonnull @NotEmpty public static final String IDP_AUTOSEARCH_PROPERTY = "idp.searchForProperties";
+
     /** Target resource to be searched for. */
     @Nonnull public static final String IDP_PROPERTIES = "/conf/idp.properties";
 
@@ -212,42 +226,69 @@ public class IdPPropertiesApplicationContextInitializer
      */
     public void loadAdditionalPropertySources(@Nonnull final ConfigurableApplicationContext applicationContext,
             @Nonnull final String searchLocation, @Nonnull final Properties properties) {
+        
+        final Collection<String> sources = new ArrayList<>();
+        
+        final Boolean autosearch = Boolean.valueOf(properties.getProperty(IDP_AUTOSEARCH_PROPERTY, "false"));
+        if (autosearch) {
+            final Path searchRoot = Path.of(searchLocation).resolve("conf");
+            if (searchRoot.toFile().isDirectory()) {
+                try (final Stream<Path> paths = Files.find(searchRoot, Integer.MAX_VALUE,
+                        new BiPredicate<Path,BasicFileAttributes>() {
+                                public boolean test(final Path t, final BasicFileAttributes u) {
+                                    if (u.isRegularFile() && t.getFileName().toString().endsWith(".properties")) {
+                                        log.debug("Including auto-located properties in {}", t);
+                                        return true;
+                                    }
+                                    return false;
+                                }
+                        }, FileVisitOption.FOLLOW_LINKS)) {
+                    
+                    sources.addAll(paths.map(Path::toString).collect(Collectors.toUnmodifiableList()));
+                } catch (final IOException e) {
+                    log.error("Error searching for additional properties", e);
+                }
+            }
+        }
+        
         final String additionalSources = properties.getProperty(IDP_ADDITIONAL_PROPERTY);
         if (additionalSources != null) {
-            final String[] sources = additionalSources.split(",");
-            for (final String source : sources) {
-                final String trimmedSource = StringSupport.trimOrNull(source);
-                if (trimmedSource == null) {
-                    continue;
-                }
-                log.debug("Attempting to load properties from resource '{}'", trimmedSource);
-                final String pathifiedSource = searchLocation + trimmedSource;
-                final Resource additionalResource = applicationContext.getResource(pathifiedSource);
-                if (additionalResource.exists()) {
-                    log.debug("Found resource '{}' at search path '{}'", additionalResource, pathifiedSource);
-                    if (loadProperties(properties, additionalResource) == null) {
-                        if (isFailFast(applicationContext)) {
-                            log.error("Unable to load properties from resource '{}'", additionalResource);
-                            throw new ConstraintViolationException("Unable to load properties from resource");
-                        }
-                        log.warn("Unable to load properties from resource '{}'", additionalResource);
-                        continue;
+            sources.addAll(Arrays.asList(additionalSources.split(",")));
+        }
+        
+        for (final String source : sources) {
+            final String trimmedSource = StringSupport.trimOrNull(source);
+            if (trimmedSource == null) {
+                continue;
+            }
+            log.debug("Attempting to load properties from resource '{}'", trimmedSource);
+            final String pathifiedSource = searchLocation + trimmedSource;
+            final Resource additionalResource = applicationContext.getResource(pathifiedSource);
+            if (additionalResource.exists()) {
+                log.debug("Found resource '{}' at search path '{}'", additionalResource, pathifiedSource);
+                if (loadProperties(properties, additionalResource) == null) {
+                    if (isFailFast(applicationContext)) {
+                        log.error("Unable to load properties from resource '{}'", additionalResource);
+                        throw new ConstraintViolationException("Unable to load properties from resource");
                     }
-                } else {
-                    log.warn("Unable to find resource '{}'", additionalResource);
+                    log.warn("Unable to load properties from resource '{}'", additionalResource);
+                    continue;
                 }
+            } else {
+                log.warn("Unable to find resource '{}'", additionalResource);
             }
         }
     }
 
     /**
-     * Log property names and values at debug level, suppressing properties whose name matches 'password'.
+     * Log property names and values at debug level, suppressing properties whose name matches 'password',
+     * 'credential', 'secret', or 'salt'.
      * 
      * @param properties the properties to log
      */
     public void logProperties(@Nonnull final Properties properties) {
         if (log.isDebugEnabled()) {
-            final Pattern pattern = Pattern.compile("password|credential", Pattern.CASE_INSENSITIVE);
+            final Pattern pattern = Pattern.compile("password|credential|secret|salt", Pattern.CASE_INSENSITIVE);
             for (final String name : new TreeSet<>(properties.stringPropertyNames())) {
                 final Object value = pattern.matcher(name).find() ? "<suppressed>" : properties.get(name);
                 log.debug("Loaded property '{}'='{}'", name, value);

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


More information about the commits mailing list