[java-shib-attribute] branch main updated: IDP-2054 - Add per-SP salt for computedId connector

Scott Cantor cantor.2 at osu.edu
Wed Dec 14 20:58:44 UTC 2022


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

scantor pushed a commit to branch main
in repository java-shib-attribute.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-attribute.git;a=commit;h=8be58fa90efdc35141090d16a58130ecad27f753

The following commit(s) were added to refs/heads/main by this push:
     new 8be58fa90 IDP-2054 - Add per-SP salt for computedId connector
8be58fa90 is described below

commit 8be58fa90efdc35141090d16a58130ecad27f753
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Wed Dec 14 15:58:41 2022 -0500

    IDP-2054 - Add per-SP salt for computedId connector
    
    https://shibboleth.atlassian.net/browse/IDP-2054
    
    Port up to main branch.
---
 shib-attribute-impl/pom.xml                        |  5 ++
 .../attribute/impl/ComputedPairwiseIdStore.java    | 87 +++++++++++++++++-----
 .../impl/ComputedPairwiseIdStoreTest.java          |  8 ++
 shib-attribute-resolver-spring/pom.xml             |  6 ++
 .../dc/impl/ComputedIdDataConnectorParser.java     | 10 +++
 .../dc/impl/StoredIdDataConnectorParser.java       |  3 +-
 .../schema/shibboleth-attribute-resolver.xsd       | 20 ++++-
 .../idp/attribute/resolver/spring/customBean.xml   | 11 ++-
 .../resolver/spring/dc/resolver/computed.xml       |  1 +
 .../resolver/spring/dc/resolver/stored.xml         |  1 +
 10 files changed, 131 insertions(+), 21 deletions(-)

diff --git a/shib-attribute-impl/pom.xml b/shib-attribute-impl/pom.xml
index 494be4406..c39028f55 100644
--- a/shib-attribute-impl/pom.xml
+++ b/shib-attribute-impl/pom.xml
@@ -57,6 +57,11 @@
         </dependency>
         
         <!-- Provided Dependencies -->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- Runtime Dependencies -->
 
diff --git a/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStore.java b/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStore.java
index e29cd1f83..2b9b58e2d 100644
--- a/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStore.java
+++ b/shib-attribute-impl/src/main/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStore.java
@@ -23,13 +23,16 @@ import java.security.NoSuchAlgorithmException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.BiFunction;
 
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import org.opensaml.profile.context.ProfileRequestContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import jakarta.servlet.http.HttpServletRequest;
 import net.shibboleth.idp.attribute.PairwiseId;
 import net.shibboleth.idp.attribute.PairwiseIdStore;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
@@ -41,6 +44,7 @@ import net.shibboleth.shared.codec.EncodingException;
 import net.shibboleth.shared.component.AbstractInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.NonnullSupplier;
 import net.shibboleth.shared.primitive.StringSupport;
 
 /**
@@ -81,7 +85,13 @@ public class ComputedPairwiseIdStore extends AbstractInitializableComponent impl
     
     /** Override map to block or re-issue identifiers. */
     @Nonnull private Map<String,Map<String,String>> exceptionMap;
+
+    /** Optional source of salt for request. */
+    @Nullable BiFunction<ProfileRequestContext,PairwiseId,String> saltLookupStrategy;
     
+    /** Servlet request supplier. */
+    @Nullable NonnullSupplier<HttpServletRequest> httpServletRequestSupplier;
+        
     /** Constructor. */
     public ComputedPairwiseIdStore() {
         algorithm = "SHA";
@@ -222,13 +232,41 @@ public class ComputedPairwiseIdStore extends AbstractInitializableComponent impl
         }
     }
 
+    /**
+     * Sets an optional function to use to obtain the salt for the request.
+     * 
+     * @param strategy lookup strategy
+     * 
+     * @since 4.3.0
+     */
+    public void setSaltLookupStrategy(@Nullable final BiFunction<ProfileRequestContext,PairwiseId,String> strategy) {
+        checkSetterPreconditions();
+        
+        saltLookupStrategy = strategy;
+    }
+    
+    /**
+     * Sets a supplier for the servlet request by which the {@link ProfileRequestContext} can be obtained.
+     * 
+     * @param supplier request supplier
+     * 
+     * @since 4.3.0
+     */
+    public void setHttpServletRequestSupplier(@Nullable final NonnullSupplier<HttpServletRequest> supplier) {
+        checkSetterPreconditions();
+        
+        httpServletRequestSupplier = supplier;
+    }
+    
     /** {@inheritDoc} */
     @Override
     protected void doInitialize() throws ComponentInitializationException {
         super.doInitialize();
         
         if (null == getSalt()) {
-            throw new ComponentInitializationException("Salt cannot be null");
+            if (saltLookupStrategy == null) {
+                throw new ComponentInitializationException("Global salt and salt lookup strategy cannot both be null");
+            }
         }
 
         if (getSalt().length < 16) {
@@ -248,10 +286,10 @@ public class ComputedPairwiseIdStore extends AbstractInitializableComponent impl
         final String sourceId =
                 Constraint.isNotEmpty(pid.getSourceSystemId(), "Source system ID cannot be null or empty");
     
-        final byte[] effectiveSalt = getEffectiveSalt(principalName, recipientId);
+        final byte[] effectiveSalt = getEffectiveSalt(pid);
         if (effectiveSalt == null) {
-            log.warn("Pairwise ID generation blocked for relying party ({})", recipientId);
-            throw new IOException("Pairwise ID generation blocked by exception rule");
+            log.warn("Pairwise ID generation blocked for relying party ({}), no salt available", pid.getRecipientEntityID());
+            throw new IOException("Pairwise ID generation blocked due to absence of salt");
         }
         
         try {
@@ -282,43 +320,58 @@ public class ComputedPairwiseIdStore extends AbstractInitializableComponent impl
     /**
      * Get the effective salt to apply for a particular principal/RP pair, or null to refuse to generate one.
      * 
-     * @param principalName name of subject
-     * @param relyingPartyId name of relying party scope
+     * @param pid pairwise ID object
      * 
      * @return salt to use
      */
-    @Nullable private byte[] getEffectiveSalt(@Nonnull @NotEmpty final String principalName,
-            @Nonnull @NotEmpty final String relyingPartyId) {
+    @Nullable private byte[] getEffectiveSalt(@Nonnull @NotEmpty final PairwiseId pid) {
         
-        Map<String,String> override = exceptionMap.get(principalName);
+        Map<String,String> override = exceptionMap.get(pid.getPrincipalName());
         if (override == null) {
             override = exceptionMap.get(WILDCARD_OVERRIDE);
         }
         
         if (override != null) {
-            if (override.containsKey(relyingPartyId)) {
-                final String s = override.get(relyingPartyId);
+            if (override.containsKey(pid.getRecipientEntityID())) {
+                final String s = override.get(pid.getRecipientEntityID());
                 if (s != null) {
-                    log.debug("Overriding salt for principal '{}' and relying party '{}'", principalName,
-                            relyingPartyId);
+                    log.debug("Overriding salt for principal '{}' and relying party '{}'", pid.getPrincipalName(),
+                            pid.getRecipientEntityID());
                     return s.getBytes();
                 }
                 log.debug("Blocked generation of ID for principal '{}' for relying party '{}'",
-                        principalName, relyingPartyId);
+                        pid.getPrincipalName(), pid.getRecipientEntityID());
                 return null;
             } else if (override.containsKey(WILDCARD_OVERRIDE)) {
                 final String s = override.get(WILDCARD_OVERRIDE);
                 if (s != null) {
-                    log.debug("Overriding salt for principal '{}' and relying party '{}'", principalName,
-                            relyingPartyId);
+                    log.debug("Overriding salt for principal '{}' and relying party '{}'", pid.getPrincipalName(),
+                            pid.getRecipientEntityID());
                     return s.getBytes();
                 }
                 log.debug("Blocked generation of ID for principal '{}' for relying party '{}'",
-                        principalName, relyingPartyId);
+                        pid.getPrincipalName(), pid.getRecipientEntityID());
                 return null;
             }
         }
         
+        if (saltLookupStrategy != null) {
+            
+            final ProfileRequestContext prc;
+            if (httpServletRequestSupplier != null) {
+                prc = (ProfileRequestContext) httpServletRequestSupplier.get().getAttribute(
+                        ProfileRequestContext.BINDING_KEY);
+            } else {
+                prc = null;
+            }
+            
+            assert saltLookupStrategy != null;
+            final String derivedSalt = saltLookupStrategy.apply(prc, pid);
+            if (derivedSalt != null) {
+                return derivedSalt.getBytes();
+            }
+        }
+        
         return salt;
     }
     
diff --git a/shib-attribute-impl/src/test/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStoreTest.java b/shib-attribute-impl/src/test/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStoreTest.java
index 318845688..56b18715c 100644
--- a/shib-attribute-impl/src/test/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStoreTest.java
+++ b/shib-attribute-impl/src/test/java/net/shibboleth/idp/attribute/impl/ComputedPairwiseIdStoreTest.java
@@ -53,6 +53,8 @@ public class ComputedPairwiseIdStoreTest {
 
     @Nonnull @NotEmpty private static final String salt2 = "thisisaspecialsalt";
     
+    @Nonnull @NotEmpty private static final String saltByFunction = "thisisasaltfromfunction";
+    
     @Nonnull @NotEmpty private static final String INVALID_BASE64_SALT = "AB==";
         
     @Nonnull @NotEmpty public static final String COMMON_ATTRIBUTE_VALUE_STRING = "at1-Data";
@@ -131,6 +133,12 @@ public class ComputedPairwiseIdStoreTest {
     public void testComputedId() throws Exception {
         final ComputedPairwiseIdStore store = new ComputedPairwiseIdStore();
         store.setSalt(salt);
+        store.setSaltLookupStrategy((prc,pid) -> {
+            if ("fooByFunction".equals(pid.getPrincipalName())) {
+                return saltByFunction;
+            }
+            return null;
+        });
         store.initialize();
 
         PairwiseId pid = new PairwiseId();
diff --git a/shib-attribute-resolver-spring/pom.xml b/shib-attribute-resolver-spring/pom.xml
index 1b7693c02..e9c36ead6 100644
--- a/shib-attribute-resolver-spring/pom.xml
+++ b/shib-attribute-resolver-spring/pom.xml
@@ -111,6 +111,11 @@
         </dependency>
 
         <!-- Provided Dependencies -->
+        <dependency>
+            <groupId>jakarta.servlet</groupId>
+            <artifactId>jakarta.servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
 
         <!-- Runtime Dependencies -->
 
@@ -165,6 +170,7 @@
             <artifactId>shib-security</artifactId>
             <scope>test</scope>
         </dependency>
+
         <!-- Needed for Spring wiring in tests. -->
         <dependency>
             <groupId>${shib-shared.groupId}</groupId>
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ComputedIdDataConnectorParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ComputedIdDataConnectorParser.java
index 52b617b50..83d439277 100644
--- a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ComputedIdDataConnectorParser.java
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ComputedIdDataConnectorParser.java
@@ -22,6 +22,7 @@ import javax.xml.namespace.QName;
 
 import net.shibboleth.idp.attribute.impl.ComputedPairwiseIdStore;
 import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.xml.AttributeSupport;
 
 import org.slf4j.Logger;
@@ -40,6 +41,9 @@ public class ComputedIdDataConnectorParser extends PairwiseIdDataConnectorParser
     @Nonnull public static final QName TYPE_NAME_RESOLVER = new QName(AttributeResolverNamespaceHandler.NAMESPACE, 
             "ComputedId");
 
+    /** ID of system bean used to access servlet request. */
+    @Nonnull @NotEmpty public static final String SERVLET_SUPPLIER_ID = "shibboleth.HttpServletRequestSupplier";
+    
     /** Class logger. */
     @Nonnull private final Logger log = LoggerFactory.getLogger(ComputedIdDataConnectorParser.class);
     
@@ -79,6 +83,12 @@ public class ComputedIdDataConnectorParser extends PairwiseIdDataConnectorParser
                     AttributeSupport.getRequiredAttributeValue(config, null, "exceptionMapRef"));
         }
 
+        if (config.hasAttributeNS(null, "saltLookupStrategyRef")) {
+            builder.addPropertyReference("saltLookupStrategy",
+                    AttributeSupport.getRequiredAttributeValue(config, null, "saltLookupStrategyRef"));
+            builder.addPropertyReference("httpServletRequestSupplier", SERVLET_SUPPLIER_ID);
+        }
+        
         final String salt;
         final String encodedSalt;
         if (config.hasAttributeNS(null, "salt")) {
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/StoredIdDataConnectorParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/StoredIdDataConnectorParser.java
index 1560a13b6..0b619cbd6 100644
--- a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/StoredIdDataConnectorParser.java
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/StoredIdDataConnectorParser.java
@@ -107,7 +107,8 @@ public class StoredIdDataConnectorParser extends ComputedIdDataConnectorParser {
                     SpringSupport.getAttributeValueAsList(config.getAttributeNodeNS(null, "retryableErrors")));
         }
 
-        if (config.hasAttributeNS(null, "salt")) {
+        if (config.hasAttributeNS(null, "salt") || config.hasAttributeNS(null, "encodedSalt") ||
+                config.hasAttributeNS(null, "saltLookupStrategyRef")) {
             builder.addPropertyValue("initialValueStore", doComputedPairwiseIdStore(config, parserContext));
         }
         
diff --git a/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index b90a99fb7..1f90cf4b1 100644
--- a/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/shib-attribute-resolver-spring/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -781,7 +781,7 @@
                         </documentation>
                     </annotation>
                 </attribute>
-                <attribute name="exceptionMapRef" type="string">
+                <attribute name="exceptionMapRef" type="resolver:string">
                     <annotation>
                         <documentation>
                             Spring bean reference to a map of overrides that alter salt or suppress generation
@@ -789,6 +789,14 @@
                         </documentation>
                     </annotation>
                 </attribute>
+                <attribute name="saltLookupStrategyRef" type="resolver:string">
+                    <annotation>
+                        <documentation>
+                            Spring bean reference to a BiFunction<ProfileRequestContext,PairwiseId> 
+                            to obtain the salt.
+                        </documentation>
+                    </annotation>
+                </attribute>
             </extension>
         </complexContent>
     </complexType>
@@ -1686,7 +1694,7 @@
                         </documentation>
                     </annotation>
                 </attribute>
-                <attribute name="exceptionMapRef" type="string">
+                <attribute name="exceptionMapRef" type="resolver:string">
                     <annotation>
                         <documentation>
                             Spring bean reference to a map of overrides that alter salt or suppress generation
@@ -1694,6 +1702,14 @@
                         </documentation>
                     </annotation>
                 </attribute>
+                <attribute name="saltLookupStrategyRef" type="resolver:string">
+                    <annotation>
+                        <documentation>
+                            Spring bean reference to a BiFunction<ProfileRequestContext,PairwiseId> 
+                            to obtain the salt.
+                        </documentation>
+                    </annotation>
+                </attribute>
             </extension>
         </complexContent>
     </complexType>
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
index aaabf259d..df9cb4f98 100644
--- a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/customBean.xml
@@ -65,7 +65,16 @@
             </property>
         </bean>
     </util:list>
-
+    
+    <bean id="SaltLookupStrategy" class="net.shibboleth.shared.logic.BiFunctionSupport" factory-method="constant">
+        <constructor-arg>
+            <null/>
+        </constructor-arg>
+    </bean>
+  
+    <bean id="shibboleth.HttpServletRequestSupplier"
+        class="net.shibboleth.shared.servlet.impl.ThreadLocalHttpServletRequestSupplier"/>
+    
 </beans>
 
        
\ No newline at end of file
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/computed.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/computed.xml
index 01945a0f1..a8928678f 100644
--- a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/computed.xml
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/computed.xml
@@ -4,6 +4,7 @@
 	
 	generatedAttributeID="jenny"
 	salt="abcdefghijklmnopqrst "
+    saltLookupStrategyRef="SaltLookupStrategy"
 	algorithm="SHA256"
 	encoding="BASE32"
 	xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
diff --git a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/stored.xml b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/stored.xml
index 77214681c..5081bcb44 100644
--- a/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/stored.xml
+++ b/shib-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/dc/resolver/stored.xml
@@ -8,6 +8,7 @@
     retryableErrors="25000 25001"
 	generatedAttributeID="jenny"
 	salt="abcdefghijklmnopqrst"
+    saltLookupStrategyRef="SaltLookupStrategy"
 	
 	xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
 

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


More information about the commits mailing list