[java-shib-attribute] branch main updated: IDP-2152 - DataConnector for metadata tags

Scott Cantor cantor.2 at osu.edu
Tue Aug 8 15:00:06 UTC 2023


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=77332971d644dce6c05b03b75e2ae8a6b610691d

The following commit(s) were added to refs/heads/main by this push:
     new 77332971d IDP-2152 - DataConnector for metadata tags
77332971d is described below

commit 77332971d644dce6c05b03b75e2ae8a6b610691d
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Aug 8 11:00:03 2023 -0400

    IDP-2152 - DataConnector for metadata tags
    
    https://shibboleth.atlassian.net/browse/IDP-2152
    
    Initial implementation pending testing.
---
 .../impl/EntityAttributesDataConnectorParser.java  |  59 ++++++++++
 .../impl/AttributeResolverNamespaceHandler.java    |   4 +-
 .../schema/shibboleth-attribute-resolver.xsd       |  23 +++-
 .../impl/EntityAttributesDataConnector.java        | 131 +++++++++++++++++++++
 4 files changed, 213 insertions(+), 4 deletions(-)

diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/EntityAttributesDataConnectorParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/EntityAttributesDataConnectorParser.java
new file mode 100644
index 000000000..55de010c2
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/EntityAttributesDataConnectorParser.java
@@ -0,0 +1,59 @@
+/*
+ * 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.idp.attribute.resolver.spring.dc.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.xml.namespace.QName;
+
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.idp.attribute.resolver.spring.dc.AbstractDataConnectorParser;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.idp.saml.attribute.resolver.impl.EntityAttributesDataConnector;
+import net.shibboleth.shared.xml.AttributeSupport;
+
+/** Bean definition Parser for a {@link EntityAttributesDataConnector}. */
+public class EntityAttributesDataConnectorParser extends AbstractDataConnectorParser {
+
+    /** Schema type - resolver. */
+    @Nonnull public static final QName TYPE_NAME =
+            new QName(AttributeResolverNamespaceHandler.NAMESPACE, "EntityAttributes");
+
+    /** {@inheritDoc} */
+    @Override
+    @Nullable protected final Class<EntityAttributesDataConnector> getBeanClass(@Nonnull final Element element) {
+        return EntityAttributesDataConnector.class;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+            @Nonnull final BeanDefinitionBuilder builder) {
+        super.doParse(config, parserContext, builder);
+        
+        if (config.hasAttributeNS(null,  "metadataContextStrategyRef")) {
+            builder.addPropertyReference("metadataContextLookupStrategy",
+                    AttributeSupport.ensureAttributeValue(config, null, "metadataContextStrategyRef"));
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override protected boolean failOnDependencies() {
+        return true;
+    }
+
+}
\ No newline at end of file
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
index f235fdf07..623bd7133 100644
--- a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
@@ -120,8 +120,8 @@ public class AttributeResolverNamespaceHandler extends BaseSpringNamespaceHandle
         registerBeanDefinitionParser(SubjectDataConnectorParser.TYPE_NAME, new SubjectDataConnectorParser());
         registerBeanDefinitionParser(StorageServiceDataConnectorParser.TYPE_NAME,
                 new StorageServiceDataConnectorParser());
-        //registerBeanDefinitionParser(EntityAttributesDataConnectorParser.TYPE_NAME,
-                //new EntityAttributesDataConnectorParser());
+        registerBeanDefinitionParser(EntityAttributesDataConnectorParser.TYPE_NAME,
+                new EntityAttributesDataConnectorParser());
 
 
         // Encoders
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 d03c8f5d4..4a61215a2 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
@@ -445,7 +445,7 @@
 
     <complexType name="SAML1NameIdentifier">
         <annotation>
-            <documentation>An attribute definition that creates attributes whose values are SAML 1 NameIdentifiers.</documentation>
+            <documentation>DEPRECATED: An attribute definition that creates attributes whose values are SAML 1 NameIdentifiers.</documentation>
         </annotation>
         <complexContent>
             <extension base="resolver:BaseAttributeDefinitionType">
@@ -472,7 +472,7 @@
 
     <complexType name="SAML2NameID">
         <annotation>
-            <documentation>An attribute definition that creates attributes whose values are SAML 2 NameIDs.</documentation>
+            <documentation>DEPRECATED: An attribute definition that creates attributes whose values are SAML 2 NameIDs.</documentation>
         </annotation>
         <complexContent>
             <extension base="resolver:BaseAttributeDefinitionType">
@@ -1753,6 +1753,25 @@
         </complexContent>
     </complexType>
     
+    <complexType name="EntityAttributes">
+        <annotation>
+            <documentation>
+                A connector for extracting mapped/decoded metadata tags from a peer's metadata. 
+            </documentation>
+        </annotation>
+        <complexContent>
+            <extension base="resolver:BaseDataConnectorType">
+                <attribute name="metadataContextStrategyRef" type="resolver:string">
+                    <annotation>
+                        <documentation>
+                            Bean ID of a Function to locate the SAMLMetadataContext to operate on.
+                            Default is to locate it under the inbound message context via SAMLPeerEntityContext.
+                        </documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
 
     <!--  Support types for DataConnectors  -->
 
diff --git a/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/EntityAttributesDataConnector.java b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/EntityAttributesDataConnector.java
new file mode 100644
index 000000000..3e3ee3294
--- /dev/null
+++ b/shib-saml-attribute-impl/src/main/java/net/shibboleth/idp/saml/attribute/resolver/impl/EntityAttributesDataConnector.java
@@ -0,0 +1,131 @@
+/*
+ * 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.idp.saml.attribute.resolver.impl;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+
+import org.opensaml.messaging.context.navigate.ChildContextLookup;
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.opensaml.profile.context.navigate.InboundMessageContextLookup;
+import org.opensaml.saml.common.messaging.context.SAMLMetadataContext;
+import org.opensaml.saml.common.messaging.context.SAMLPeerEntityContext;
+import org.opensaml.saml.ext.saml2mdattr.EntityAttributes;
+import org.opensaml.saml.saml2.metadata.EntityDescriptor;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Multimap;
+
+import net.shibboleth.idp.attribute.AttributesMapContainer;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AbstractDataConnector;
+import net.shibboleth.idp.attribute.resolver.DataConnector;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.logic.Constraint;
+import net.shibboleth.shared.primitive.LoggerFactory;
+
+/**
+ * A {@link DataConnector} that returns the decoded {@link EntityAttributes}
+ * from a peer's metadata.
+ * 
+ * @since 5.0.0
+ */
+ at ThreadSafe
+public class EntityAttributesDataConnector extends AbstractDataConnector {
+
+    /** Class logger. */
+    @Nonnull private final Logger log = LoggerFactory.getLogger(EntityAttributesDataConnector.class);
+
+    /** Metadata context lookup strategy. */
+    @Nonnull private Function<ProfileRequestContext,SAMLMetadataContext> metadataContextLookupStrategy;
+
+    /** Constructor. */
+    public EntityAttributesDataConnector() {
+        // Default is inbound -> SAMLPeerEntityContext -> SAMLMetadataContext.
+        metadataContextLookupStrategy = new ChildContextLookup<>(SAMLMetadataContext.class).compose(
+                new ChildContextLookup<>(SAMLPeerEntityContext.class).compose(
+                        new InboundMessageContextLookup()));
+    }
+    
+    /**
+     * Set the lookup strategy for the {@link SAMLMetadataContext} to pull tags from.
+     * 
+     * @param strategy lookup strategy
+     */
+    public void setMetadataContextLookupStrategy(
+            @Nonnull final Function<ProfileRequestContext,SAMLMetadataContext> strategy) {
+        metadataContextLookupStrategy = Constraint.isNotNull(strategy, "SAMLMetadataContext strategy cannot be null");
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    @Nonnull @Unmodifiable @NotLive protected Map<String, IdPAttribute> doDataConnectorResolve(
+            @Nonnull final AttributeResolutionContext resolutionContext,
+            @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException {
+        
+        final SAMLMetadataContext metadataContext = metadataContextLookupStrategy.apply(
+                resolutionContext.getProfileRequestContextLookupStrategy().apply(resolutionContext));
+        final EntityDescriptor entity = metadataContext != null ? metadataContext.getEntityDescriptor() : null;
+        if (entity == null) {
+            log.debug("Specified metadata source was absent.");
+            return CollectionSupport.emptyMap();
+        }
+        
+        final List<AttributesMapContainer> containerList = entity.getObjectMetadata().get(AttributesMapContainer.class);
+        if (containerList != null && !containerList.isEmpty()) {
+            final AttributesMapContainer container = containerList.get(0);
+            final Multimap<String,IdPAttribute> tags = container.get();
+            if (!tags.isEmpty()) {
+                final Map<String,IdPAttribute> results = new HashMap<>();
+
+                for (final IdPAttribute attribute : tags.values()) {
+                    try {
+                        if (results.containsKey(attribute.getId())) {
+                            final IdPAttribute existing = results.get(attribute.getId());
+                            final List<IdPAttributeValue> union = new ArrayList<>(existing.getValues());
+                            union.addAll(attribute.getValues());
+                            existing.setValues(union);
+                        } else {
+                            // We have to clone because of the other branch of this conditional,
+                            // we might need to mutate the values by combining them with a leter set.
+                            results.put(attribute.getId(), attribute.clone());
+                        }
+                    } catch(final CloneNotSupportedException e) {
+                        throw new ResolutionException(e);
+                    }
+                }
+                
+                log.trace("{} Resolved attributes: {}", getLogPrefix(), results);
+                return results;
+            }
+        }
+        
+        log.trace("{} No entity attributes resolved", getLogPrefix());
+        return CollectionSupport.emptyMap();
+    }
+    
+}
\ No newline at end of file

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


More information about the commits mailing list