[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