[java-idp-plugin-oidc-op-oidfed] 02/02: Refactored the federation constraints to allow modification of statements
Codeberg
noreply at shibboleth.net
Thu Jan 22 17:41:51 UTC 2026
This is an automated email from the git hooks/post-receive script.
codeberg pushed a commit to branch dev/CACHE-REFACTOR
in repository java-idp-plugin-oidc-op-oidfed.
View the commit online:
https://codeberg.org/Shibboleth/java-idp-plugin-oidc-op-oidfed/commit/76756ae0fa8474f852d3f9512cb7e205a740dcf9
commit 76756ae0fa8474f852d3f9512cb7e205a740dcf9
Author: Henri Mikkonen <henri.mikkonen at iki.fi>
AuthorDate: Thu Jan 22 19:41:20 2026 +0200
Refactored the federation constraints to allow modification of statements
- Moved constraint enforcement from trust chain cache fetcihng part into SWF actions
- AbstractTrustChainResolutionAction serves ResolveTrustChains and ValidateProvidedTrustChain
- The 'allowed_entity_types' may need to remove metadata for specific entity types
- The trust chain handed to FederationPolicyConstraint.validate(..) is marked with @Live-annotation
---
...mbinedMetadataFromTrustChainLookupStrategy.java | 2 +-
...efaultProvidedTrustChainValidationStrategy.java | 11 ---
.../DefaultTrustChainFetchingStrategy.java | 31 ---------
.../constraints/FederationPolicyConstraint.java | 13 ++--
.../FederationPolicyConstraintHelper.java | 53 ++++++++-------
.../impl/AbstractFederationPolicyConstraint.java | 7 +-
.../impl/DefaultAllowedEntityTypesConstraint.java | 58 +++++++++++++++-
.../impl/DefaultMaxPathLengthConstraint.java | 16 +++--
.../impl/DefaultNamingConstraintsConstraint.java | 5 ++
.../impl/AbstractTrustChainResolutionAction.java | 78 ++++++++++++++++++++--
.../oidfed/profile/impl/OidFederationEventIds.java | 6 ++
.../profile/impl/ValidateProvidedTrustChain.java | 2 +-
.../META-INF/net.shibboleth.idp/postconfig.xml | 3 +-
.../oidfed/metadata-lookup-ext-oidfed-beans.xml | 3 +-
.../oidfed/metadata-lookup-ext-oidfed-flow.xml | 2 +
.../idp/flows/oidfed/register/register-beans.xml | 9 +--
.../oidfed/resolve-entity/resolve-entity-beans.xml | 3 +-
.../DefaultTrustChainFetchingStrategyTest.java | 22 +-----
.../profile/flow/oidfed/RegistrationFlowTest.java | 17 +++++
19 files changed, 223 insertions(+), 118 deletions(-)
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultCombinedMetadataFromTrustChainLookupStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultCombinedMetadataFromTrustChainLookupStrategy.java
index 19fc945..9bc61c9 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultCombinedMetadataFromTrustChainLookupStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultCombinedMetadataFromTrustChainLookupStrategy.java
@@ -57,7 +57,7 @@ public class DefaultCombinedMetadataFromTrustChainLookupStrategy extends Abstrac
.map(metadata -> metadata.getAllClaims()).orElse(null);
if (configurationMetadata == null || configurationMetadata.isEmpty()) {
- log.error("Entity configuration for {} doesn't contain metadata", chain.get(0).getSubject());
+ log.debug("Entity configuration for {} doesn't contain metadata", chain.get(0).getSubject());
return null;
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultProvidedTrustChainValidationStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultProvidedTrustChainValidationStrategy.java
index fc38022..2580a24 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultProvidedTrustChainValidationStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/DefaultProvidedTrustChainValidationStrategy.java
@@ -27,7 +27,6 @@ import org.slf4j.Logger;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraintHelper;
import net.shibboleth.oidc.metadata.filter.MetadataFilterContext;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
@@ -114,16 +113,6 @@ public class DefaultProvidedTrustChainValidationStrategy extends AbstractIdentif
log.debug("The trust chain did not pass the signature validation");
return false;
}
- for (int i = 1; i < trustChain.size() - 1; i++) {
- final List<EntityStatement<?>> subChain = trustChain.subList(0, i);
- assert subChain != null;
- if (!FederationPolicyConstraintHelper.verifyPolicyConstraints(
- trustChain.get(i), subChain, getFederationPolicyConstraints())) {
- log.debug("Subordinate statement {} policy constraints validation failed",
- trustChain.get(i).getSubject());
- return false;
- }
- }
return true;
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
index 6fed233..14f72f6 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategy.java
@@ -37,8 +37,6 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEnti
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteSubordinateStatementContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteTrustChainsContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubjectEntityStatementCriterion;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraintHelper;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.util.EntityStatementHelper;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
import net.shibboleth.oidc.metadata.cache.MetadataCacheException;
@@ -78,9 +76,6 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
/** Cache containing local copies of trusted trust anchor keys. */
@NonnullAfterInit private MetadataCache<Map<String, LocalKeyContainer>> localTrustAnchorsCache;
- /** Map of supported federation policy constraints. */
- @NonnullAfterInit private Map<String, FederationPolicyConstraint> federationPolicyConstraints;
-
/** Strategy to fetch lifetime for container with valid contents. */
@NonnullAfterInit private Function<CriteriaSet, Duration> criteriaToValidContainerLifetimeStrategy;
@@ -128,27 +123,6 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
localTrustAnchorsCache = Constraint.isNotNull(cache, "Local Trust Anchor cache cannot be null");
}
- /**
- * Set the map of supported federation policy constraints.
- *
- * @param constraints map of supported federation policy constraints.
- */
- public void setFederationPolicyConstraints(@Nonnull final Map<String, FederationPolicyConstraint> constraints) {
- checkSetterPreconditions();
- federationPolicyConstraints = Constraint.isNotNull(constraints, "Map of policy constraints cannot be null");
- }
-
- /**
- * Get the map of supported federation policy constraints.
- *
- * @return map of supported federation policy constraints.
- */
- @Nonnull public Map<String, FederationPolicyConstraint> getFederationPolicyConstraints() {
- checkComponentActive();
- assert federationPolicyConstraints != null;
- return federationPolicyConstraints;
- }
-
/**
* Set the strategy to fetch lifetime for container with valid contents.
*
@@ -190,9 +164,6 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
if (localTrustAnchorsCache == null) {
throw new ComponentInitializationException("Local Trust Anchor cache cannot be null");
}
- if (federationPolicyConstraints == null) {
- throw new ComponentInitializationException("Map of policy constraints cannot be null");
- }
if (criteriaToValidContainerLifetimeStrategy == null) {
throw new ComponentInitializationException("Criteria to valid container lifetime strategy cannot be null");
}
@@ -324,8 +295,6 @@ public class DefaultTrustChainFetchingStrategy extends AbstractIdentifiableIniti
.filter(id -> !EntityStatementHelper.subjectAlreadyExists(id, chain))
.map(id -> fetchAuthority(entityStatement, id))
.filter(pair -> pair != null && pair.getFirst() != null && pair.getSecond() != null)
- .filter(pair -> FederationPolicyConstraintHelper.verifyPolicyConstraints(
- pair.getSecond(), chain, getFederationPolicyConstraints()))
.toList();
hints = !authorities.isEmpty();
authorities.forEach(authority -> {
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraint.java
index 5bb1f95..f8348ed 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraint.java
@@ -20,6 +20,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.shared.annotation.constraint.Live;
/**
* Interface to be implemented by the federation policy constraints.
@@ -27,11 +29,14 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
public interface FederationPolicyConstraint {
/**
- * Validate whether the given trust chain meets given federation policy constraint value,
+ * Validate whether the given trust chain meets given federation policy constraint value. The trust chain may be
+ * modified by the constraint validators, thus it is required to be modifiable.
*
* @param constraint the constraint value
- * @param trustChain trust chain to be evaluated
- * @return true if the trust chain is valid for this constraint, false otherwise.
+ * @param subordinateStatement subordinate statement that defined the constraint
+ * @param trustChain trust chain to be evaluated and optionally updated: it is required to be modifiable
+ * @return true if the trust chain is valid for this constraint, false otherwise
*/
- public boolean validate(@Nullable final Object constraint, @Nonnull final List<EntityStatement<?>> trustChain);
+ public boolean validate(@Nullable final Object constraint, @Nonnull final SubordinateStatement subordinateStatement,
+ @Nonnull @Live final List<EntityStatement<?>> trustChain);
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
index 75aece5..3c9d8e5 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/FederationPolicyConstraintHelper.java
@@ -18,12 +18,12 @@ import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import org.slf4j.Logger;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.SubordinateStatementPayload;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.shared.annotation.constraint.Live;
import net.shibboleth.shared.primitive.LoggerFactory;
/**
@@ -35,38 +35,41 @@ public class FederationPolicyConstraintHelper {
@Nonnull private final static Logger log = LoggerFactory.getLogger(FederationPolicyConstraintHelper.class);
/**
- * Parses and verifies federation policy constraints set in the given subordinates statement against the given
- * trust chain.
+ * Parses and verifies federation policy constraints in the given trust chain. Optionally the changed values
+ * (for instance with the 'allowed_entity_types' constraint) are enforced to the trust chain.
*
- * @param subordinateStatement subordinate statement containing the constraints
- * @param trustChain trust chain to be verified
+ * @param trustChain trust chain to be verified and optionally modified: it is required to be modifiable
* @param federationPolicyConstraints map of the federation policy constraint implementations
* @return true if trust chain meets the constraints. false otherwise
*/
- public static boolean verifyPolicyConstraints(@Nullable final EntityStatement<?> subordinateStatement,
- @Nonnull final List<EntityStatement<?>> trustChain,
+ public static boolean verifyPolicyConstraints(@Nonnull @Live final List<EntityStatement<?>> trustChain,
@Nonnull Map<String, FederationPolicyConstraint> federationPolicyConstraints) {
- if (subordinateStatement == null) {
+ if (trustChain.size() < 3) {
return true;
}
- final Map<String, Object> constraints =
- subordinateStatement.getParsedPayload() instanceof SubordinateStatementPayload ssp ?
- ssp.getConstraints() : null;
- if (constraints == null || constraints.isEmpty()) {
- log.trace("No constraints found for {}: {}", subordinateStatement.getSubject(), constraints);
- return true;
- }
- for (final String constraint : constraints.keySet()) {
- final FederationPolicyConstraint validator = federationPolicyConstraints.get(constraint);
- if (validator != null) {
- log.trace("Validating federation policy constraint {} with {}", constraint, validator);
- if (!validator.validate(constraints.get(constraint), trustChain)) {
- log.warn("Subordinate statement issued by {} contained constraint {} that failed",
- subordinateStatement.getIssuer(), constraint);
- return false;
+ for (int i = trustChain.size() - 2; i > 0; i--) {
+ if (trustChain.get(i) instanceof SubordinateStatement subordinateStatement) {
+ final Map<String, Object> constraints = subordinateStatement.getParsedPayload().getConstraints();
+ if (constraints == null || constraints.isEmpty()) {
+ log.trace("No constraints found for {}: {}", subordinateStatement.getSubject(), constraints);
+ continue;
+ }
+ for (final String constraint : constraints.keySet()) {
+ final FederationPolicyConstraint validator = federationPolicyConstraints.get(constraint);
+ if (validator != null) {
+ log.trace("Validating federation policy constraint {} with {}", constraint, validator);
+ if (!validator.validate(constraints.get(constraint), subordinateStatement, trustChain)) {
+ log.warn("Subordinate statement issued by {} contained constraint {} that failed",
+ subordinateStatement.getIssuer(), constraint);
+ return false;
+ }
+ } else {
+ log.debug("Ignoring non-recognized federation policy constraint {}", constraint);
+ }
}
} else {
- log.debug("Ignoring non-recognized federation policy constraint {}", constraint);
+ log.error("Unexpected trust chain contents: {} is not a subordinate statement", trustChain.get(i));
+ return false;
}
}
return true;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
index 78d57b8..424c62c 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/AbstractFederationPolicyConstraint.java
@@ -22,6 +22,7 @@ import javax.annotation.Nullable;
import org.slf4j.Logger;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
import net.shibboleth.shared.component.AbstractIdentifiableInitializableComponent;
import net.shibboleth.shared.logic.ConstraintViolationException;
@@ -40,14 +41,14 @@ public abstract class AbstractFederationPolicyConstraint<T extends Object>
/** {@inheritDoc} */
@Override
- public boolean validate(@Nullable final Object constraint,
+ public boolean validate(@Nullable final Object constraint, @Nonnull final SubordinateStatement subordinateStatement,
@Nonnull final List<EntityStatement<?>> trustChain) {
checkComponentActive();
try {
log.trace("Attempting to parse raw constraint value: {}", constraint);
final T constraintData = parseConstraint(constraint);
if (constraintData != null) {
- return doValidate(constraintData, trustChain);
+ return doValidate(constraintData, subordinateStatement, trustChain);
} else {
return true;
}
@@ -70,9 +71,11 @@ public abstract class AbstractFederationPolicyConstraint<T extends Object>
* Validate whether the given trust chain meets given federation policy constraint value,
*
* @param constraintData the non-null constraint value
+ * @param subordinateStatement subordinate statement that contains the constraint
* @param trustChain trust chain to be evaluated
* @return true if the trust chain is valid for this constraint, false otherwise.
*/
protected abstract boolean doValidate(@Nonnull final T constraintData,
+ @Nonnull final SubordinateStatement subordinateStatement,
@Nonnull final List<EntityStatement<?>> trustChain);
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
index d0a5db1..8ef37f0 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultAllowedEntityTypesConstraint.java
@@ -15,7 +15,9 @@
package net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.impl;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
@@ -25,8 +27,15 @@ import org.slf4j.Logger;
import com.fasterxml.jackson.databind.ObjectMapper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.SubordinateStatementImpl;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.Metadata;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.EntityConfigurationPayloadImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.SubordinateStatementPayloadImpl;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.component.ComponentInitializationException;
import net.shibboleth.shared.logic.Constraint;
@@ -79,6 +88,7 @@ public class DefaultAllowedEntityTypesConstraint extends AbstractFederationPolic
/** {@inheritDoc} */
@Override
protected boolean doValidate(@Nonnull final List<String> constraintData,
+ @Nonnull final SubordinateStatement subordinateStatement,
@Nonnull final List<EntityStatement<?>> trustChain) {
if (constraintData.contains("federation_entity")) {
log.warn("The value 'federation_entity' is not allowed for allowed_entity_types");
@@ -87,8 +97,12 @@ public class DefaultAllowedEntityTypesConstraint extends AbstractFederationPolic
final List<String> allowedTypes = new ArrayList<>(constraintData);
allowedTypes.add("federation_entity");
log.trace("Allowed entity types: {}", allowedTypes);
- for (final EntityStatement<?> entityStatement : trustChain) {
+ for (int i = 0; i < trustChain.size() - 1; i++) {
+ final EntityStatement<?> entityStatement = trustChain.get(i);
assert entityStatement != null;
+ if (subordinateStatement.equals(entityStatement)) {
+ break;
+ }
final Metadata metadata =
Optional.ofNullable(entityStatement.getParsedPayload().getMetadata())
.orElse(null);
@@ -97,12 +111,50 @@ public class DefaultAllowedEntityTypesConstraint extends AbstractFederationPolic
if (!allowedTypes.contains(entityType)) {
log.warn("The entity type {} is not allowed in entity statement {}", entityType,
entityStatement.getSubject());
- return false;
+ for (int j = 0; j <= i; j++) {
+ final EntityStatement<?> replacement = removeMetadata(entityType, trustChain.get(j));
+ if (replacement == null) {
+ log.error("Could not remove the entity type {} from metadata for {}", entityType,
+ entityStatement.getSubject());
+ return false;
+ }
+ trustChain.set(j, replacement);
+ }
+ } else {
+ log.trace("The entity type {} is allowed for {}", entityType, entityStatement.getSubject());
}
- log.trace("The entity type {} is allowed for {}", entityType, entityStatement.getSubject());
}
}
}
return true;
}
+
+ /**
+ * Removes the metadata of given entity type from the given entity statement.
+ *
+ * @param entityType entity type for metadata to be removed
+ * @param entityStatement entity statement holding the metadata
+ * @return updated entity statement, or null if the operation failed
+ */
+ @Nullable private EntityStatement<?> removeMetadata(final String entityType,
+ final EntityStatement<?> entityStatement) {
+ final Map<String, Map<String, Object>> metadataClaims =
+ new HashMap<>(entityStatement.getParsedPayload().getMetadata().getAllClaims());
+ metadataClaims.remove(entityType);
+ log.trace("Removed entity type {}", entityType);
+ final MetadataImpl metadata = new MetadataImpl(metadataClaims);
+ log.trace("Metadata contents {}", metadata);
+ if (entityStatement instanceof EntityConfiguration entityConfiguration) {
+ final EntityConfigurationPayloadImpl payload =
+ new EntityConfigurationPayloadImpl(entityConfiguration.getParsedPayload());
+ payload.setMetadata(metadata);
+ return new EntityConfigurationImpl(entityStatement.getJwt(), payload);
+ } else if (entityStatement instanceof SubordinateStatement subordinateStatement) {
+ final SubordinateStatementPayloadImpl payload =
+ new SubordinateStatementPayloadImpl(subordinateStatement.getParsedPayload());
+ payload.setMetadata(metadata);
+ return new SubordinateStatementImpl(entityStatement.getJwt(), payload);
+ }
+ return null;
+ }
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
index ea6874e..1dd7010 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultMaxPathLengthConstraint.java
@@ -22,6 +22,7 @@ import javax.annotation.Nullable;
import org.slf4j.Logger;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
import net.shibboleth.shared.logic.ConstraintViolationException;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -48,15 +49,16 @@ public class DefaultMaxPathLengthConstraint extends AbstractFederationPolicyCons
/** {@inheritDoc} */
@Override
protected boolean doValidate(@Nonnull final Integer constraintData,
+ @Nonnull final SubordinateStatement subordinateStatement,
@Nonnull final List<EntityStatement<?>> trustChain) {
- final List<EntityStatement<?>> intermediates = trustChain.stream()
- .filter(es -> !es.getSubject().equals(es.getIssuer()))
- .toList();
- final int length = intermediates.size();
- log.trace("Maximum path length: {}, amount of intermediates is {}", constraintData, length);
- if (constraintData < length) {
+ final int length = trustChain.indexOf(subordinateStatement);
+ if (length < 1) {
+ log.error("Unexpected contents in the trust chain: subordinate statement index is {}", length);
+ }
+ log.trace("Maximum path length: {}, amount of intermediates is {}", constraintData, length - 1);
+ if (constraintData < length - 1) {
log.warn("Maximum path length is constricted to {}, amount of intermediates is {}",
- constraintData, length);
+ constraintData, length - 1);
return false;
}
return true;
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
index 0d67ba7..9cebffb 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/constraints/impl/DefaultNamingConstraintsConstraint.java
@@ -31,6 +31,7 @@ import org.bouncycastle.asn1.x509.PKIXNameConstraintValidator;
import org.slf4j.Logger;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.SubordinateStatement;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.ConstraintViolationException;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -81,6 +82,7 @@ public class DefaultNamingConstraintsConstraint extends AbstractFederationPolicy
/** {@inheritDoc} */
@Override
protected boolean doValidate(@Nonnull final Map<String, List<String>> constraintData,
+ @Nonnull final SubordinateStatement subordinateStatement,
@Nonnull final List<EntityStatement<?>> trustChain) {
final PKIXNameConstraintValidator bcValidator = new PKIXNameConstraintValidator();
@@ -95,6 +97,9 @@ public class DefaultNamingConstraintsConstraint extends AbstractFederationPolicy
new GeneralSubtree(new GeneralName(GeneralName.dNSName, item))));
for (final EntityStatement<?> entityStatement : trustChain) {
+ if (subordinateStatement.equals(entityStatement)) {
+ break;
+ }
final String host = URI.create(entityStatement.getSubject()).getHost();
try {
bcValidator.checkExcluded(new GeneralName(GeneralName.dNSName, host));
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
index 2fa7d26..d96ac06 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/AbstractTrustChainResolutionAction.java
@@ -14,6 +14,7 @@
package net.shibboleth.idp.plugin.oidc.op.oidfed.profile.impl;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -31,13 +32,19 @@ import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
import org.slf4j.Logger;
import net.minidev.json.JSONObject;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityConfiguration;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.EntityStatement;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraintHelper;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.impl.EntityConfigurationImpl;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.claim.impl.MetadataImpl;
+import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.impl.EntityConfigurationPayloadImpl;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.policy.FederationMetadataPolicyHelper;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.RelyingPartyTrustChainContext;
import net.shibboleth.idp.plugin.oidc.op.oidfed.profile.context.VerifiedTrustChain;
import net.shibboleth.idp.profile.AbstractProfileAction;
import net.shibboleth.oidc.metadata.policy.MetadataPolicy;
+import net.shibboleth.shared.annotation.constraint.Live;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.collection.Pair;
@@ -79,6 +86,9 @@ public class AbstractTrustChainResolutionAction extends AbstractProfileAction {
/** List of claim names who are transformed from a space-separated String into a List. */
@Nonnull private List<String> arraysAsSpaceSeparatedList;
+ /** Map of supported federation policy constraints. */
+ @NonnullAfterInit private Map<String, FederationPolicyConstraint> federationPolicyConstraints;
+
/**
* Constructor.
*/
@@ -213,6 +223,27 @@ public class AbstractTrustChainResolutionAction extends AbstractProfileAction {
metadataValidationCondition = Constraint.isNotNull(condition, "MetadataValidationCondition cannot be null");
}
+ /**
+ * Set the map of supported federation policy constraints.
+ *
+ * @param constraints map of supported federation policy constraints.
+ */
+ public void setFederationPolicyConstraints(@Nonnull final Map<String, FederationPolicyConstraint> constraints) {
+ checkSetterPreconditions();
+ federationPolicyConstraints = Constraint.isNotNull(constraints, "Map of policy constraints cannot be null");
+ }
+
+ /**
+ * Get the map of supported federation policy constraints.
+ *
+ * @return map of supported federation policy constraints.
+ */
+ @Nonnull public Map<String, FederationPolicyConstraint> getFederationPolicyConstraints() {
+ checkComponentActive();
+ assert federationPolicyConstraints != null;
+ return federationPolicyConstraints;
+ }
+
/** {@inheritDoc} */
@Override
protected void doInitialize() throws ComponentInitializationException {
@@ -230,20 +261,37 @@ public class AbstractTrustChainResolutionAction extends AbstractProfileAction {
if (metadataValidationCondition == null) {
throw new ComponentInitializationException("MetadataValidationCondition cannot be null");
}
+ if (federationPolicyConstraints == null) {
+ throw new ComponentInitializationException("Map of policy constraints cannot be null");
+ }
}
/**
* Populates the given policy compliant trust chains with the given trust chain if its metadata is policy compliant.
*
- * @param chain the trust chain to be evaluated
+ * @param candidate the trust chain to be evaluated
* @param policyCompliantChains the list of policy-compliant trust chains to be populated
* @return error event ID if metadata policy merging or enforcement failed, null otherwise
*/
- @Nullable protected String populatePolicyComplaintChains(@Nonnull final List<EntityStatement<?>> chain,
- @Nonnull List<VerifiedTrustChain> policyCompliantChains) {
- final Map<String,Map<String,Object>> metadata = getMetadataLookupStrategy().apply(chain);
- log.trace("{} Metadata resolved via lookup strategy: {}", getLogPrefix(), metadata);
- if (metadata != null) {
+ @Nullable protected String populatePolicyComplaintChains(@Nonnull final List<EntityStatement<?>> candidate,
+ @Nonnull @Live List<VerifiedTrustChain> policyCompliantChains) {
+ final Map<String,Map<String,Object>> candidateMetadata = getMetadataLookupStrategy().apply(candidate);
+ log.trace("{} Metadata resolved via lookup strategy: {}", getLogPrefix(), candidateMetadata);
+ if (candidateMetadata != null) {
+ final List<EntityStatement<?>> chain = new ArrayList<>(candidate);
+ final EntityConfiguration updatedLeaf = updateEntityConfiguration(candidate.get(0), candidateMetadata);
+ if (updatedLeaf == null) {
+ log.error("Could not update the leaf entity configuration for {}", candidate.get(0).getSubject());
+ return EventIds.INVALID_MSG_CTX;
+ }
+ chain.set(0, updatedLeaf);
+ if (!FederationPolicyConstraintHelper.verifyPolicyConstraints(
+ chain, getFederationPolicyConstraints())) {
+ return OidFederationEventIds.INVALID_TRUST_CHAIN_AGAINST_CONSTRAINTS;
+ }
+ final Map<String,Map<String,Object>> metadata =
+ Optional.ofNullable(getMetadataLookupStrategy().apply(chain)).orElse(CollectionSupport.emptyMap());
+ log.trace("{} Constrained metadata resolved via lookup strategy: {}", getLogPrefix(), metadata);
final Map<String,Map<String,Object>> verifiedMetadata = new HashMap<>();
for (final String entityType : metadata.keySet()) {
final Map<String, MetadataPolicy> mergedPolicies;
@@ -313,4 +361,22 @@ public class AbstractTrustChainResolutionAction extends AbstractProfileAction {
.orElse(null);
}
+ /**
+ * Updates the given entity configuration to contain given metadata.
+ *
+ * @param entityStatement entity configuration source
+ * @param metadata metadata to be included in the updated entity configuration
+ * @return updated entity configuration or null if the source was unexpected
+ */
+ @Nullable protected EntityConfiguration updateEntityConfiguration(
+ @Nullable final EntityStatement<?> entityStatement,
+ @Nonnull final Map<String, Map<String, Object>> metadata) {
+ if (entityStatement instanceof EntityConfiguration entityConfiguration) {
+ final EntityConfigurationPayloadImpl payload =
+ new EntityConfigurationPayloadImpl(entityConfiguration.getParsedPayload());
+ payload.setMetadata(new MetadataImpl(metadata));
+ return new EntityConfigurationImpl(entityStatement.getJwt(), payload);
+ }
+ return null;
+ }
}
\ No newline at end of file
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
index ec5bbbe..d8c4c01 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/OidFederationEventIds.java
@@ -69,4 +69,10 @@ public class OidFederationEventIds {
* ID of event returned if the given metadata is invalid against policy.
*/
@Nonnull @NotEmpty public static final String INVALID_METADATA_AGAINST_POLICY = "InvalidMetadataAgainstPolicy";
+
+ /**
+ * ID of event returned if the trust chain is invalid against constraints.
+ */
+ @Nonnull @NotEmpty public static final String INVALID_TRUST_CHAIN_AGAINST_CONSTRAINTS =
+ "InvalidTrustChainAgainstConstraints";
}
diff --git a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
index 2ecef8f..7afe12b 100644
--- a/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
+++ b/idp-oidfed-op-impl/src/main/java/net/shibboleth/idp/plugin/oidc/op/oidfed/profile/impl/ValidateProvidedTrustChain.java
@@ -115,7 +115,7 @@ public class ValidateProvidedTrustChain extends AbstractTrustChainResolutionActi
@Override
protected void doExecute(@Nonnull final ProfileRequestContext profileRequestContext) {
if (!providedTrustChainValidationStrategy.test(profileRequestContext, trustChain)) {
- log.error("{} The trust chain validation failed", getLogPrefix());
+ log.warn("{} The trust chain validation failed", getLogPrefix());
ActionSupport.buildEvent(profileRequestContext, EventIds.INVALID_MSG_CTX);
return;
}
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
index 46b305c..34c4020 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net.shibboleth.idp/postconfig.xml
@@ -333,8 +333,7 @@
p:criteriaToSubjectEntityIdStrategy-ref="shibboleth.oidfed.DefaultSubjectEntityIDCriteriaToIdentifierStrategy"
p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"
p:subordinateStatementCache-ref="shibboleth.oidfed.SubordinateEntityStatementMetadataCache"
- p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache"
- p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
+ p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache">
<property name="criteriaToValidContainerLifetimeStrategy">
<bean parent="shibboleth.Functions.Constant">
<constructor-arg>
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
index 0d25b16..7d7d06a 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-beans.xml
@@ -36,7 +36,8 @@
p:metadataPolicyEnforcer-ref="#{'%{idp.oidfed.authorize.MetadataPolicyEnforcer:DefaultMetadataPolicyEnforcer}'.trim()}"
p:preSelectedTrustChainIdsLookupStrategy="#{getObject('shibboleth.oidfed.PreSelectedTrustChainIDsLookupStrategy') ?: getObject('shibboleth.oidfed.DefaultPreSelectedTrustChainIDsLookupStrategy')}"
p:arraysAsSpaceSeparatedList="%{idp.oidfed.policy.arraysAsSpaceSeparatedList:scope}"
- p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}">
+ p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}"
+ p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
<property name="metadataLookupStrategy">
<bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultCombinedMetadataFromTrustChainLookupStrategy" />
</property>
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
index 8c5cb3e..44c78c8 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidc/metadata-lookup-ext/oidfed/metadata-lookup-ext-oidfed-flow.xml
@@ -60,12 +60,14 @@
<end-state id="InvalidMetadataPolicy"/>
<end-state id="InvalidMetadataAgainstPolicy"/>
<end-state id="NoTrustChainsResolved" />
+ <end-state id="InvalidTrustChainAgainstConstraints" />
<end-state id="HandleError"/>
<global-transitions>
<transition on="InvalidMetadataPolicy" to="InvalidMetadataPolicy" />
<transition on="InvalidMetadataAgainstPolicy" to="InvalidMetadataAgainstPolicy" />
<transition on="NoTrustChainsResolved" to="NoTrustChainsResolved" />
+ <transition on="InvalidTrustChainAgainstConstraints" to="InvalidTrustChainAgainstConstraints" />
<transition on="HandleError" to="HandleError" />
</global-transitions>
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
index 758ac8f..6cce525 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/register/register-beans.xml
@@ -43,7 +43,8 @@
p:metadataPolicyEnforcer-ref="#{'%{idp.oidfed.register.MetadataPolicyEnforcer:DefaultMetadataPolicyEnforcer}'.trim()}"
p:arraysAsSpaceSeparatedList="%{idp.oidfed.policy.arraysAsSpaceSeparatedList:scope}"
p:metadataLookupStrategy-ref="DefaultCombinedMetadataFromTrustChainLookupStrategy"
- p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}">
+ p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}"
+ p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
<property name="providedTrustChainValidationStrategy">
<bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultProvidedTrustChainValidationStrategy"
p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
@@ -129,7 +130,8 @@
p:arraysAsSpaceSeparatedList="%{idp.oidfed.policy.arraysAsSpaceSeparatedList:scope}"
p:metadataLookupStrategy-ref="DefaultCombinedMetadataFromTrustChainLookupStrategy"
p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}"
- p:entityConfigurationLookupStrategy-ref="ExplicitClientRegistrationRequestEntityConfigurationLookupFunction" />
+ p:entityConfigurationLookupStrategy-ref="ExplicitClientRegistrationRequestEntityConfigurationLookupFunction"
+ p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}" />
<bean id="FetchThroughTrustChainMetadataCache" parent="shibboleth.oidc.CacheBuilder">
<constructor-arg>
@@ -148,8 +150,7 @@
p:criteriaToSubjectEntityIdStrategy-ref="shibboleth.oidfed.DefaultSubjectEntityIDCriteriaToIdentifierStrategy"
p:entityConfigurationCache-ref="shibboleth.oidfed.EntityConfigurationMetadataCache"
p:subordinateStatementCache-ref="shibboleth.oidfed.SubordinateEntityStatementMetadataCache"
- p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache"
- p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
+ p:localTrustAnchorsCache-ref="shibboleth.oidfed.LocalTrustAnchorsMetadataCache">
<property name="criteriaToValidContainerLifetimeStrategy">
<bean parent="shibboleth.Functions.Constant">
<constructor-arg>
diff --git a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
index 4fbed93..2cc79b9 100644
--- a/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
+++ b/idp-oidfed-op-impl/src/main/resources/META-INF/net/shibboleth/idp/flows/oidfed/resolve-entity/resolve-entity-beans.xml
@@ -81,7 +81,8 @@
p:metadataPolicyEnforcer-ref="#{'%{idp.oidfed.resolve-entity.MetadataPolicyEnforcer:DefaultMetadataPolicyEnforcer}'.trim()}"
p:preSelectedTrustChainIdsLookupStrategy="#{getObject('shibboleth.oidfed.PreSelectedTrustChainIDsLookupStrategy') ?: getObject('shibboleth.oidfed.DefaultPreSelectedTrustChainIDsLookupStrategy')}"
p:arraysAsSpaceSeparatedList="%{idp.oidfed.policy.arraysAsSpaceSeparatedList:scope}"
- p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}">
+ p:metadataValidationCondition-ref="#{'%{idp.oidfed.MetadataValidationCondition:DefaultMetadataValidationCondition}'.trim()}"
+ p:federationPolicyConstraints-ref="%{idp.oidfed.FederationPolicyConstraints:shibboleth.oidfed.DefaultFederationPolicyConstraints}">
<property name="metadataLookupStrategy">
<bean class="net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.DefaultCombinedMetadataFromTrustChainLookupStrategy"/>
</property>
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategyTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategyTest.java
index d4f7571..7c30d93 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategyTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/oidfed/metadata/cache/remote/trustchain/DefaultTrustChainFetchingStrategyTest.java
@@ -20,7 +20,6 @@ import static org.mockito.Mockito.when;
import java.time.Duration;
import java.time.Instant;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
@@ -37,7 +36,6 @@ import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteEnti
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteSubordinateStatementContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.RemoteTrustChainsContainer;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.cache.remote.SubordinateStatementCacheIdentifier;
-import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.constraints.FederationPolicyConstraint;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.payload.EntityConfigurationPayload;
import net.shibboleth.idp.plugin.oidc.op.oidfed.metadata.util.EntityStatementHelper;
import net.shibboleth.oidc.metadata.cache.MetadataCache;
@@ -62,7 +60,6 @@ public class DefaultTrustChainFetchingStrategyTest {
Function<CriteriaSet, Duration> criteriaToInvalidContainerLifetimeStrategy;
@SuppressWarnings("unchecked")
- @BeforeMethod
public void initMocks() {
criteriaToSubjectEntityIdStrategy = mock(Function.class);
entityConfigurationCache = mock(MetadataCache.class);
@@ -72,7 +69,9 @@ public class DefaultTrustChainFetchingStrategyTest {
criteriaToInvalidContainerLifetimeStrategy = mock(Function.class);
}
- public void setup(final Map<String, FederationPolicyConstraint> federationPolicyConstraints) {
+ @BeforeMethod
+ public void setup() {
+ initMocks();
function = new DefaultTrustChainFetchingStrategy();
function.setCriteriaToSubjectEntityIdStrategy(criteriaToSubjectEntityIdStrategy);
function.setEntityConfigurationCache(entityConfigurationCache);
@@ -80,7 +79,6 @@ public class DefaultTrustChainFetchingStrategyTest {
function.setLocalTrustAnchorsCache(localTrustAnchorsCache);
function.setCriteriaToValidContainerLifetimeStrategy(criteriaToValidContainerLifetimeStrategy);
function.setCriteriaToInvalidContainerLifetimeStrategy(criteriaToInvalidContainerLifetimeStrategy);
- function.setFederationPolicyConstraints(federationPolicyConstraints);
function.setId("mockFunction");
try {
function.initialize();
@@ -91,13 +89,11 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void nullCriteria_returnsNull() {
- setup(new HashMap<>());
Assert.assertEquals(function.apply(null), null);
}
@Test
public void noValidLifetimeCriteria_returnsNull() {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(null);
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
Assert.assertEquals(function.apply(new CriteriaSet()), null);
@@ -105,7 +101,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void noInvalidLifetimeCriteria_returnsNull() {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(null);
Assert.assertEquals(function.apply(new CriteriaSet()), null);
@@ -113,7 +108,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void noEntityConfigurationResolved_returnsNull() throws MetadataCacheException {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(entityConfigurationCache.get(any())).thenReturn(CollectionSupport.emptyList());
@@ -122,7 +116,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationException_returnsNull() throws MetadataCacheException {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(entityConfigurationCache.get(any())).thenThrow(MetadataCacheException.class);
@@ -131,7 +124,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationNoHints_returnsNull() throws MetadataCacheException {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
final RemoteEntityConfigurationContainer ecContainer =
@@ -142,7 +134,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationOneUnresolvableHint_returnsEmptyContainer() throws MetadataCacheException {
- setup(new HashMap<>());
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
when(criteriaToInvalidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
final RemoteEntityConfigurationContainer ecContainer =
@@ -154,7 +145,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@SuppressWarnings("unchecked")
@Test
public void entityConfigurationOneResolvableHint_returnsContainerWithOneChain() throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String anchor = "https://federation.local/immediate";
when(criteriaToValidContainerLifetimeStrategy.apply(any())).thenReturn(Duration.ofMinutes(5));
@@ -181,7 +171,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationOneResolvableLocalAuthorityWithBrokenHint_returnsContainerWithOneChain()
throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String immediate = "https://federation.local/immediate";
final String anchor = "https://federation.local/anchor";
@@ -211,7 +200,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationOneResolvableLocalAuthorityWithWorkingHint_returnsContainerWithTwoChains()
throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String immediate = "https://federation.local/immediate";
final String anchor = "https://federation.local/anchor";
@@ -247,7 +235,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationOneResolvableHint_matchPreSelected_returnsContainerWithOneChain()
throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String anchor = "https://federation.local/immediate";
final PreSelectedTrustChainCriterion preSelectedCriterion =
@@ -276,7 +263,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@Test
public void entityConfigurationOneResolvableHint_notMatchingPreSelected_returnsEmptyContainer()
throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String anchor = "https://federation.local/immediate";
final PreSelectedTrustChainCriterion preSelectedCriterion =
@@ -299,7 +285,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@SuppressWarnings("unchecked")
@Test
public void entityConfigurationTwoResolvableHints_returnsContainerWithTwoChains() throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String anchor1 = "https://federation.local/immediate1";
final String anchor2 = "https://federation.local/immediate2";
@@ -331,7 +316,6 @@ public class DefaultTrustChainFetchingStrategyTest {
@SuppressWarnings("unchecked")
@Test
public void entityConfigurationAuthorityLoop_returnsEmptyContantainer() throws MetadataCacheException {
- setup(new HashMap<>());
final String leaf = "https://federation.local/leaf";
final String anchor1 = "https://federation.local/immediate1";
final String anchor2 = "https://federation.local/immediate2";
diff --git a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
index a6e1551..b3e39cc 100644
--- a/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
+++ b/idp-oidfed-op-impl/src/test/java/net/shibboleth/idp/plugin/oidc/op/profile/flow/oidfed/RegistrationFlowTest.java
@@ -315,6 +315,23 @@ public class RegistrationFlowTest extends AbstractFederationFlowTest {
assertErrorCode(result, "invalid_request");
}
+ @Test
+ public void testValidTrustChain_invalidMaxLengthInIntermediate() throws Exception {
+ final String clientId = uniqueClientId();
+ final String intermediateId1 = uniqueIntermediateId();
+ final String intermediateId2 = uniqueIntermediateId();
+ final String trustChain = "[\"" + rpEntityConfiguration(clientId) + "\", \"" +
+ subordinateStatement(intermediateId1, intermediateKey, leafKey, clientId, Collections.emptyMap(),
+ Collections.emptyMap()) + "\", \"" +
+ subordinateStatement(intermediateId2, intermediateKey, intermediateKey, intermediateId1, Collections.emptyMap(),
+ Map.of("max_path_length", Integer.valueOf(0))) + "\", \"" +
+ subordinateStatement(anchorId, trustedAnchorKey, intermediateKey, intermediateId2, Collections.emptyMap(),
+ Map.of("max_path_length", Integer.valueOf(2))) + "\", \"" + trustedAnchorConfiguration() + "\"]";
+ setRequest("POST", trustChain, "application/trust-chain+json");
+ final FlowExecutionResult result = flowExecutor.launchExecution(FLOW_ID, null, externalContext);
+ assertErrorCode(result, "invalid_request");
+ }
+
@Test
public void testValidTrustChain_validNamingConstraintInAnchor() throws Exception {
final String clientId = uniqueClientId();
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list