[java-shib-profile] branch main updated: JSATTR-6: SAML AttributeQuery DataConnector

Brent Putman putmanb at georgetown.edu
Sat May 31 22:59:16 UTC 2025


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

putmanb pushed a commit to branch main
in repository java-shib-profile.

View the commit online:
http://git.shibboleth.net/view/?p=java-shib-profile.git;a=commit;h=21924dd76c85dc043a88c6eb679e178e44aee654

The following commit(s) were added to refs/heads/main by this push:
     new 21924dd  JSATTR-6: SAML AttributeQuery DataConnector
21924dd is described below

commit 21924dd76c85dc043a88c6eb679e178e44aee654
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Sat May 31 00:33:27 2025 -0400

    JSATTR-6: SAML AttributeQuery DataConnector
    
    Add a CriteriaSet-based resolver for DecryptionConfiguration.
    
    Refactor most of the existing CriteriaSelfEntityIDResolver into
    a base class for code reuse.
---
 ...riteriaRelyingPartyConfiigurationResolver.java} |  45 +++--
 .../CriteriaDecryptionConfigurationResolver.java   | 116 +++++++++++++
 .../impl/CriteriaSelfEntityIDResolver.java         | 189 +--------------------
 3 files changed, 145 insertions(+), 205 deletions(-)

diff --git a/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/BaseCriteriaRelyingPartyConfiigurationResolver.java
similarity index 85%
copy from shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java
copy to shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/BaseCriteriaRelyingPartyConfiigurationResolver.java
index 1a5db71..5533814 100644
--- a/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java
+++ b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/BaseCriteriaRelyingPartyConfiigurationResolver.java
@@ -32,7 +32,7 @@ import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
 import net.shibboleth.profile.relyingparty.RelyingPartyConfigurationResolver;
 import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
 import net.shibboleth.shared.annotation.constraint.NotEmpty;
-import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent;
 import net.shibboleth.shared.component.ComponentInitializationException;
 import net.shibboleth.shared.component.IdentifiableComponent;
@@ -45,19 +45,21 @@ import net.shibboleth.shared.service.ServiceException;
 import net.shibboleth.shared.service.ServiceableComponent;
 
 /**
- * Resolver which uses an instance of {@link RelyingPartyConfigurationResolver} to
- * resolve our own entityID.
+ * Abstract base resolver which uses an instance of {@link RelyingPartyConfigurationResolver} to
+ * resolve a {@link RelyingPartyConfiguration} using an input {@link CriteriaSet} only.
  * 
  * <p>
  * The required and allowed criteria are the same as the {@link RelyingPartyConfigurationResolver}
  * implementation in use.
  * </p>
+ * 
+ * @param <ReturnType>  The type of data returned by the resolver
  */
-public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializableComponent
-    implements Resolver<String, CriteriaSet>, IdentifiableComponent {
+public abstract class BaseCriteriaRelyingPartyConfiigurationResolver<ReturnType> extends AbstractIdentifiedInitializableComponent
+    implements Resolver<ReturnType, CriteriaSet>, IdentifiableComponent {
     
     /** Logger. */
-    @Nonnull private Logger log = LoggerFactory.getLogger(CriteriaSelfEntityIDResolver.class);
+    @Nonnull private Logger log = LoggerFactory.getLogger(BaseCriteriaRelyingPartyConfiigurationResolver.class);
     
     /** The RelyingPartyConfigurationResolver to which to delegate. */
     @NonnullAfterInit private ReloadableService<RelyingPartyConfigurationResolver> rpcResolver;
@@ -94,18 +96,18 @@ public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializabl
         super.doDestroy();
     }
 
-    /** {@inheritDoc} */
-    @Nonnull public Iterable<String> resolve(@Nullable final CriteriaSet criteria) throws ResolverException {
-        checkComponentActive();
-        final String entityID = resolveSingle(criteria);
-        if (entityID != null) {
-            return CollectionSupport.singletonList(entityID);
-        }
-        return CollectionSupport.emptyList();
-    }
-
-    /** {@inheritDoc} */
-    @Nullable public String resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+    /**
+     * Resolve the {@link RelyingPartyConfiguration} based on the input {@link CriteriaSet}.
+     * 
+     * @param criteria the criteria for resolution
+     * 
+     * @return the relying party configuration along with the internal synthetic profile request context
+     * (often necessary for further data fetching from the configuration), or null if resolution fails
+     * 
+     * @throws ResolverException if there is a fatal error resolving the configuration
+     */
+    @Nullable protected Pair<RelyingPartyConfiguration, ProfileRequestContext> resolveRelyingPartyConfiguration(
+            @Nullable final CriteriaSet criteria) throws ResolverException {
         checkComponentActive();
         
         final ProfileRequestContext prc = buildContext(criteria);
@@ -118,12 +120,7 @@ public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializabl
         
         try (final ServiceableComponent<RelyingPartyConfigurationResolver> resolver =
                 rpcResolver.getServiceableComponent()) {
-            final RelyingPartyConfiguration rpc = resolver.getComponent().resolveSingle(prcSet);
-            if (rpc != null) {
-                return rpc.getIssuer(prc);
-            } else {
-                log.error("RelyingPartyConfigurationResolver returned null configuration");
-            }
+            return new Pair<>(resolver.getComponent().resolveSingle(prcSet), prc);
         } catch (final ResolverException e) {
             log.error("RelyingPartyConfigurationResolver did not resolve a RelyingPartyConfiguration: {}", e.getMessage());
         } catch (final ServiceException e) {
diff --git a/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaDecryptionConfigurationResolver.java b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaDecryptionConfigurationResolver.java
new file mode 100644
index 0000000..a63a57f
--- /dev/null
+++ b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaDecryptionConfigurationResolver.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.profile.relyingparty.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.criterion.ProfileIDCriterion;
+import org.opensaml.security.config.SecurityConfiguration;
+import org.opensaml.xmlsec.DecryptionConfiguration;
+import org.opensaml.xmlsec.SecurityConfigurationSupport;
+import org.opensaml.xmlsec.config.XMLSecurityConfiguration;
+
+import net.shibboleth.profile.config.ProfileConfiguration;
+import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
+import net.shibboleth.profile.relyingparty.RelyingPartyConfigurationResolver;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.collection.Pair;
+import net.shibboleth.shared.resolver.CriteriaSet;
+import net.shibboleth.shared.resolver.ResolverException;
+
+/**
+ * Resolver which uses an instance of {@link RelyingPartyConfigurationResolver} to
+ * resolve a list of {@link DecryptionConfiguration} applicable for a peer entity.
+ * 
+ * <p>
+ * The required and allowed criteria are the same as the {@link RelyingPartyConfigurationResolver}
+ * implementation in use. Also supports an optional {@link ProfileIDCriterion}, which if supplied is used
+ * to resolve the profile-specific configuration.
+ * </p>
+ */
+public class CriteriaDecryptionConfigurationResolver
+    extends BaseCriteriaRelyingPartyConfiigurationResolver<List<DecryptionConfiguration>> {
+    
+    /** {@inheritDoc} */
+    @Nonnull public Iterable<List<DecryptionConfiguration>> resolve(@Nullable final CriteriaSet criteria) throws ResolverException {
+        checkComponentActive();
+        final List<DecryptionConfiguration> config = resolveSingle(criteria);
+        if (config != null) {
+            return CollectionSupport.singletonList(config);
+        }
+        return CollectionSupport.emptyList();
+    }
+
+    /** {@inheritDoc} */
+    @Nullable public List<DecryptionConfiguration> resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
+        checkComponentActive();
+
+        final Pair<RelyingPartyConfiguration, ProfileRequestContext> rpcData = resolveRelyingPartyConfiguration(criteria);
+        if (rpcData != null) {
+            final RelyingPartyConfiguration rpc = rpcData.getFirst();
+            final ProfileRequestContext prc = rpcData.getSecond();
+            assert rpc != null && prc != null;
+            
+            return buildConfigList(rpc, prc, criteria);
+        }
+        return null;
+    }
+
+    /**
+     * Build the list of configurations.
+     * 
+     * @param rpc the relying party configuration 
+     * @param prc the synthetic profile request context
+     * @param criteria  the input criteria
+     * 
+     * @return the list of configurations
+     */
+    @Nonnull private List<DecryptionConfiguration> buildConfigList(@Nonnull final RelyingPartyConfiguration rpc,
+            @Nonnull final ProfileRequestContext prc, CriteriaSet criteria) {
+        
+        final List<DecryptionConfiguration> configs = new ArrayList<>();
+        
+        String profileID = null;
+        final ProfileIDCriterion profileIDCriterion = criteria.get(ProfileIDCriterion.class);
+        if (profileIDCriterion != null) {
+            profileID  = profileIDCriterion.getProfileId();
+        }
+
+        if (profileID != null) {
+            final ProfileConfiguration pc = rpc.getProfileConfiguration(prc, profileID);
+            if (pc != null) {
+                final SecurityConfiguration sc = pc.getSecurityConfiguration(prc);
+                if (sc instanceof XMLSecurityConfiguration xsc && xsc.getDecryptionConfiguration() != null) {
+                    configs.add(xsc.getDecryptionConfiguration());
+                }
+            }
+        }
+
+        final SecurityConfiguration defaultConfig = rpc.getSecurityConfiguration(prc);
+        if (defaultConfig instanceof XMLSecurityConfiguration xsc && xsc.getDecryptionConfiguration() != null) {
+            configs.add(xsc.getDecryptionConfiguration());
+        }
+
+        configs.add(SecurityConfigurationSupport.getGlobalDecryptionConfiguration());
+        
+        return configs;
+    }
+    
+}
\ No newline at end of file
diff --git a/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java
index 1a5db71..1ac4716 100644
--- a/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java
+++ b/shib-profile-impl/src/main/java/net/shibboleth/profile/relyingparty/impl/CriteriaSelfEntityIDResolver.java
@@ -17,32 +17,14 @@ package net.shibboleth.profile.relyingparty.impl;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
-import org.opensaml.core.criterion.EntityIdCriterion;
 import org.opensaml.profile.context.ProfileRequestContext;
-import org.opensaml.profile.criterion.ProfileRequestContextCriterion;
-import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
-import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
-import org.opensaml.saml.criterion.RoleDescriptorCriterion;
-import org.opensaml.saml.saml2.metadata.EntityDescriptor;
-import org.opensaml.saml.saml2.metadata.RoleDescriptor;
-import org.slf4j.Logger;
 
-import net.shibboleth.profile.context.RelyingPartyContext;
 import net.shibboleth.profile.relyingparty.RelyingPartyConfiguration;
 import net.shibboleth.profile.relyingparty.RelyingPartyConfigurationResolver;
-import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
-import net.shibboleth.shared.annotation.constraint.NotEmpty;
 import net.shibboleth.shared.collection.CollectionSupport;
-import net.shibboleth.shared.component.AbstractIdentifiedInitializableComponent;
-import net.shibboleth.shared.component.ComponentInitializationException;
-import net.shibboleth.shared.component.IdentifiableComponent;
-import net.shibboleth.shared.primitive.LoggerFactory;
+import net.shibboleth.shared.collection.Pair;
 import net.shibboleth.shared.resolver.CriteriaSet;
-import net.shibboleth.shared.resolver.Resolver;
 import net.shibboleth.shared.resolver.ResolverException;
-import net.shibboleth.shared.service.ReloadableService;
-import net.shibboleth.shared.service.ServiceException;
-import net.shibboleth.shared.service.ServiceableComponent;
 
 /**
  * Resolver which uses an instance of {@link RelyingPartyConfigurationResolver} to
@@ -53,47 +35,8 @@ import net.shibboleth.shared.service.ServiceableComponent;
  * implementation in use.
  * </p>
  */
-public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializableComponent
-    implements Resolver<String, CriteriaSet>, IdentifiableComponent {
+public class CriteriaSelfEntityIDResolver extends BaseCriteriaRelyingPartyConfiigurationResolver<String> {
     
-    /** Logger. */
-    @Nonnull private Logger log = LoggerFactory.getLogger(CriteriaSelfEntityIDResolver.class);
-    
-    /** The RelyingPartyConfigurationResolver to which to delegate. */
-    @NonnullAfterInit private ReloadableService<RelyingPartyConfigurationResolver> rpcResolver;
-    
-    /**
-     * Set the {@link RelyingPartyConfigurationResolver} instance to which to delegate.
-     * 
-     * @param resolver the relying party resolver 
-     */
-    public void setRelyingPartyConfigurationResolver(
-            @Nullable final ReloadableService<RelyingPartyConfigurationResolver> resolver) {
-        checkSetterPreconditions();
-        
-        rpcResolver = resolver;
-    }
-
-    /** {@inheritDoc} */
-    @Override public void setId(@Nonnull @NotEmpty final String componentId) {
-        super.setId(componentId);
-    }
-
-    /** {@inheritDoc} */
-    protected void doInitialize() throws ComponentInitializationException {
-        super.doInitialize();
-        
-        if (rpcResolver == null) {
-            throw new ComponentInitializationException("RelyingPartyConfigurationResolver cannot be null");
-        }
-    }
-
-    /** {@inheritDoc} */
-    protected void doDestroy() {
-        rpcResolver = null;
-        super.doDestroy();
-    }
-
     /** {@inheritDoc} */
     @Nonnull public Iterable<String> resolve(@Nullable final CriteriaSet criteria) throws ResolverException {
         checkComponentActive();
@@ -107,131 +50,15 @@ public class CriteriaSelfEntityIDResolver extends AbstractIdentifiedInitializabl
     /** {@inheritDoc} */
     @Nullable public String resolveSingle(@Nullable final CriteriaSet criteria) throws ResolverException {
         checkComponentActive();
-        
-        final ProfileRequestContext prc = buildContext(criteria);
-        if (prc == null) {
-            log.error("Unable to extract or build ProfileRequestContext for resolution");
-            return null;
-        }
-        
-        final CriteriaSet prcSet = new CriteriaSet(new ProfileRequestContextCriterion(prc));
-        
-        try (final ServiceableComponent<RelyingPartyConfigurationResolver> resolver =
-                rpcResolver.getServiceableComponent()) {
-            final RelyingPartyConfiguration rpc = resolver.getComponent().resolveSingle(prcSet);
-            if (rpc != null) {
-                return rpc.getIssuer(prc);
-            } else {
-                log.error("RelyingPartyConfigurationResolver returned null configuration");
-            }
-        } catch (final ResolverException e) {
-            log.error("RelyingPartyConfigurationResolver did not resolve a RelyingPartyConfiguration: {}", e.getMessage());
-        } catch (final ServiceException e) {
-            log.error("RelyingPartyConfiguration resolver unvailable: {}", e.getMessage());
-        }
-        return null;
-    }
-
-    /**
-     * Build and populate the synthetic instance of {@link ProfileRequestContext} which will be used
-     * in the resolution call to the delegate as well as to resolve the entityID setting.
-     * 
-     * @param criteria the input criteria
-     * @return the synthetic context instance, or null if required data is not supplied
-     */
-    @Nullable private ProfileRequestContext buildContext(@Nullable final CriteriaSet criteria) {
-        if (criteria == null) {
-            return null;
-        }
-        
-        final ProfileRequestContextCriterion prcCriterion = criteria.get(ProfileRequestContextCriterion.class);
-        if (prcCriterion != null) {
-            return prcCriterion.getProfileRequestContext();
-        }
-
-        final String entityID = resolveEntityID(criteria);
-        log.debug("Resolved effective entityID from criteria: {}", entityID);
-
-        final EntityDescriptor entityDescriptor = resolveEntityDescriptor(criteria);
-        log.debug("Resolved effective entity descriptor from criteria: {}", entityDescriptor);
 
-        final RoleDescriptor roleDescriptor = resolveRoleDescriptor(criteria);
-        log.debug("Resolved effective role descriptor from criteria: {}", roleDescriptor);
+        final Pair<RelyingPartyConfiguration, ProfileRequestContext> rpcData = resolveRelyingPartyConfiguration(criteria);
+        if (rpcData != null) {
+            final RelyingPartyConfiguration rpc = rpcData.getFirst();
+            final ProfileRequestContext prc = rpcData.getSecond();
+            assert rpc != null && prc != null;
 
-        if (entityID != null || entityDescriptor != null || roleDescriptor != null) {
-            final ProfileRequestContext prc = new ProfileRequestContext();
-            final RelyingPartyContext rpc = prc.ensureSubcontext(RelyingPartyContext.class);
-            rpc.setVerified(true);
-
-            rpc.setRelyingPartyId(entityID);
-
-            if (entityDescriptor != null || roleDescriptor != null) {
-                final SAMLPeerEntityContext peerContext = prc.ensureSubcontext(SAMLPeerEntityContext.class);
-                rpc.setRelyingPartyIdContextTree(peerContext);
-
-                peerContext.setEntityId(entityID);
-
-                if (roleDescriptor != null) {
-                    peerContext.setRole(roleDescriptor.getSchemaType() != null
-                            ? roleDescriptor.getSchemaType() : roleDescriptor.getElementQName());
-                }
-
-                final SAMLMetadataContext metadataContext = peerContext.ensureSubcontext(SAMLMetadataContext.class);
-                metadataContext.setEntityDescriptor(entityDescriptor);
-                metadataContext.setRoleDescriptor(roleDescriptor);
-            }
-            return prc;
-        }
-        return null;
-    }
-
-    /**
-     * Resolve the entityID from the criteria.
-     * 
-     * @param criteria the input criteria
-     * @return the input entityID criterion or null if could not be resolved
-     */
-    @Nullable private String resolveEntityID(@Nonnull final CriteriaSet criteria) {
-        final EntityIdCriterion eic = criteria.get(EntityIdCriterion.class);
-        if (eic != null) {
-            return eic.getEntityId();
-        }
-
-        final EntityDescriptor ed = resolveEntityDescriptor(criteria);
-        if (ed != null) {
-            return ed.getEntityID();
+            return rpc.getIssuer(prc);
         }
-
-        return null;
-    }
-
-    /**
-     * Resolve the EntityDescriptor from the criteria.
-     *
-     * @param criteria the input criteria
-     * @return the input entity descriptor criterion, or null if could not be resolved
-     */
-    @Nullable private EntityDescriptor resolveEntityDescriptor(@Nonnull final CriteriaSet criteria) {
-        final RoleDescriptor rd = resolveRoleDescriptor(criteria);
-        if (rd != null && rd.getParent() != null && rd.getParent() instanceof EntityDescriptor) {
-            return (EntityDescriptor)rd.getParent();
-        }
-
-        return null;
-    }
-
-    /**
-     * Resolve the RoleDescriptor from the criteria.
-     *
-     * @param criteria the input criteria
-     * @return the input role descriptor criterion or null if could not be resolved
-     */
-    @Nullable private RoleDescriptor resolveRoleDescriptor(@Nonnull final CriteriaSet criteria) {
-        final RoleDescriptorCriterion rdc = criteria.get(RoleDescriptorCriterion.class);
-        if (rdc != null) {
-            return rdc.getRole();
-        }
-
         return null;
     }
     

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


More information about the commits mailing list