[java-shib-attribute] branch main updated: Re-implement Subject data connector on top of new generic connector.
Scott Cantor
cantor.2 at osu.edu
Mon Jul 11 20:16:39 UTC 2022
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch main
in repository java-shib-attribute.
View the commit online:
http://git.shibboleth.net/view/?p=java-shib-attribute.git;a=commit;h=e249c48b3dc95387909b36ea9cfec0586555a5d8
The following commit(s) were added to refs/heads/main by this push:
new e249c48b3 Re-implement Subject data connector on top of new generic connector.
e249c48b3 is described below
commit e249c48b3dc95387909b36ea9cfec0586555a5d8
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Jul 11 16:16:36 2022 -0400
Re-implement Subject data connector on top of new generic connector.
---
.../dc/impl/ContextDerivedDataConnector.java | 134 +++++++++++++++++++++
.../dc/impl/ContextDerivedDataConnectorParser.java | 72 +++++++++++
.../spring/dc/impl/SubjectDataConnectorParser.java | 96 +++++++++++++++
.../impl/AttributeResolverNamespaceHandler.java | 7 +-
.../schema/shibboleth-attribute-resolver.xsd | 29 ++++-
5 files changed, 335 insertions(+), 3 deletions(-)
diff --git a/shib-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/impl/ContextDerivedDataConnector.java b/shib-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/impl/ContextDerivedDataConnector.java
new file mode 100644
index 000000000..4cd189b76
--- /dev/null
+++ b/shib-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/dc/impl/ContextDerivedDataConnector.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.dc.impl;
+
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.resolver.AbstractDataConnector;
+import net.shibboleth.idp.attribute.resolver.NoResultAnErrorResolutionException;
+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.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+import org.opensaml.profile.context.ProfileRequestContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A data connector which returns attributes whose values are derived from the
+ * {@link ProfileRequestContext} associated with the request via a plugged in {@link Function}.
+ */
+public class ContextDerivedDataConnector extends AbstractDataConnector {
+
+ /** Logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(ContextDerivedDataConnector.class);
+
+ /**
+ * Function used to generate the attributes derived from the {@link ProfileRequestContext}.
+ */
+ @NonnullAfterInit private Function<ProfileRequestContext,List<IdPAttribute>> attributesFunction;
+
+ /** Whether no record is an error. */
+ private boolean noResultIsError;
+
+ /**
+ * Gets the attribute derivation function.
+ *
+ * @return derivation function
+ */
+ @NonnullAfterInit public Function<ProfileRequestContext,List<IdPAttribute>> getAttributesFunction() {
+ return attributesFunction;
+ }
+
+ /**
+ * Sets the attribute derivation function.
+ *
+ * @param function what to set.
+ */
+ public void setAttributesFunction(@Nonnull final Function<ProfileRequestContext,List<IdPAttribute>> function) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ attributesFunction = Constraint.isNotNull(function, "Attribute Function cannot be null");
+ }
+
+ /**
+ * Gets whether the lack of returned attributes constitutes an error.
+ *
+ * @return whether the lack of returned attributes constitutes an error
+ */
+ public boolean isNoResultIsError() {
+ return noResultIsError;
+ }
+
+ /**
+ * Sets whether the lack of a returned record constitutes an error.
+ *
+ * @param flag flag to set
+ */
+ public void setNoResultIsError(final boolean flag) {
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+
+ noResultIsError = flag;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (attributesFunction == null) {
+ throw new ComponentInitializationException("Attribute lookup strategy cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Map<String,IdPAttribute> doDataConnectorResolve(
+ @Nonnull final AttributeResolutionContext resolutionContext,
+ @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException {
+
+ final List<IdPAttribute> results =
+ attributesFunction.apply(
+ resolutionContext.getProfileRequestContextLookupStrategy().apply(resolutionContext));
+
+ if (null == results || results.isEmpty()) {
+ if (noResultIsError) {
+ throw new NoResultAnErrorResolutionException(getLogPrefix() + " No attributes returned");
+ }
+ log.debug("{} Generated no attributes", getLogPrefix());
+ return null;
+ }
+
+ log.debug("{} Generated {} attributes", getLogPrefix(), results.size());
+ log.trace("{} Attributes: {}", getLogPrefix(), results);
+
+ return results.stream().collect(Collectors.toUnmodifiableMap(IdPAttribute::getId, Function.identity()));
+ }
+
+}
\ No newline at end of file
diff --git a/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ContextDerivedDataConnectorParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ContextDerivedDataConnectorParser.java
new file mode 100644
index 000000000..2655ec494
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/ContextDerivedDataConnectorParser.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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.xml.namespace.QName;
+
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.ext.spring.util.SpringSupport;
+import net.shibboleth.idp.attribute.resolver.AbstractDataConnector;
+import net.shibboleth.idp.attribute.resolver.dc.impl.ContextDerivedDataConnector;
+import net.shibboleth.idp.attribute.resolver.spring.dc.AbstractDataConnectorParser;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.xml.AttributeSupport;
+
+/** Spring Bean Definition Parser for {@link ContextDerivedDataConnector}. */
+public class ContextDerivedDataConnectorParser extends AbstractDataConnectorParser {
+
+ /** Schema type name. */
+ @Nonnull public static final QName TYPE_NAME_RESOLVER =
+ new QName(AttributeResolverNamespaceHandler.NAMESPACE, "ContextDerived");
+
+ /** {@inheritDoc} */
+ @Override
+ @Nonnull protected Class<? extends AbstractDataConnector> getNativeBeanClass() {
+ return ContextDerivedDataConnector.class;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doV2Parse(@Nonnull final Element element, @Nonnull final ParserContext parserContext,
+ @Nonnull final BeanDefinitionBuilder builder) {
+ final String functionRef = StringSupport.trimOrNull(element.getAttributeNS(null, "attributesFunctionRef"));
+
+ if (null == functionRef) {
+ throw new BeanCreationException(getLogPrefix() + "requires 'attributesFunctionRef'");
+ }
+ builder.addPropertyReference("attributesFunction", functionRef);
+
+ final String noResultIsError =
+ AttributeSupport.getAttributeValue(element, new QName("noResultIsError"));
+ if (noResultIsError != null) {
+ builder.addPropertyValue("noResultIsError", SpringSupport.getStringValueAsBoolean(noResultIsError));
+ }
+ }
+
+ /** {@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/dc/impl/SubjectDataConnectorParser.java b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/SubjectDataConnectorParser.java
new file mode 100644
index 000000000..6f69f0120
--- /dev/null
+++ b/shib-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/dc/impl/SubjectDataConnectorParser.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You 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 java.util.function.Function;
+
+import javax.annotation.Nonnull;
+import javax.xml.namespace.QName;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.w3c.dom.Element;
+
+import net.shibboleth.ext.spring.util.SpringSupport;
+import net.shibboleth.idp.attribute.resolver.dc.impl.ContextDerivedDataConnector;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.xml.AttributeSupport;
+
+/** Spring Bean Definition Parser for {@link ContextDerivedDataConnector} with a predefined mapping function. */
+public class SubjectDataConnectorParser extends ContextDerivedDataConnectorParser {
+
+ /** Schema type name. */
+ @Nonnull public static final QName TYPE_NAME_RESOLVER =
+ new QName(AttributeResolverNamespaceHandler.NAMESPACE, "Subject");
+
+ /** Class name for sourcing attributes from Subject(s). */
+ @Nonnull @NotEmpty private static final String SUBJECT_DERIVED_CLASS_NAME =
+ "net.shibboleth.idp.authn.context.impl.SubjectDerivedAttributesFunction";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(SubjectDataConnectorParser.class);
+
+ /** Class for sourcing values from Subject(s). */
+ @Nonnull private Class<? extends Function<?,?>> subjectDerivedClass;
+
+ /** Constructor. */
+ @SuppressWarnings("unchecked")
+ public SubjectDataConnectorParser() {
+ try {
+ subjectDerivedClass = (Class<? extends Function<?, ?>>) Class.forName(SUBJECT_DERIVED_CLASS_NAME);
+ } catch (final ClassNotFoundException e) {
+ log.error("Unable to load class to support instantiation of this plugin type.");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ protected void doV2Parse(@Nonnull final Element element, @Nonnull final ParserContext parserContext,
+ @Nonnull final BeanDefinitionBuilder builder) {
+
+ if (subjectDerivedClass == null) {
+ throw new BeanCreationException("Unable to load class for subject-derived attribute function.");
+ }
+
+ // Auto-inject an instance of the deferred class type as the lookup function.
+
+ final BeanDefinitionBuilder contextFunctionBuilder =
+ BeanDefinitionBuilder.genericBeanDefinition(subjectDerivedClass);
+ contextFunctionBuilder.setInitMethodName("initialize");
+ contextFunctionBuilder.setDestroyMethodName("destroy");
+ contextFunctionBuilder.addPropertyValue("id", getDefinitionId());
+
+ if (element.hasAttributeNS(null, "forCanonicalization")) {
+ contextFunctionBuilder.addPropertyValue("forCanonicalization",
+ SpringSupport.getStringValueAsBoolean(element.getAttributeNS(null, "forCanonicalization")));
+ }
+
+ builder.addPropertyValue("attributesFunction", contextFunctionBuilder.getBeanDefinition());
+
+ final String noResultIsError =
+ AttributeSupport.getAttributeValue(element, new QName("noResultIsError"));
+ if (noResultIsError != null) {
+ builder.addPropertyValue("noResultIsError", SpringSupport.getStringValueAsBoolean(noResultIsError));
+ }
+ }
+
+}
\ 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 596432c28..46352c942 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
@@ -39,10 +39,12 @@ import net.shibboleth.idp.attribute.resolver.spring.ad.mapped.impl.SourceValuePa
import net.shibboleth.idp.attribute.resolver.spring.ad.mapped.impl.ValueMapParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.http.impl.HTTPDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.ComputedIdDataConnectorParser;
+import net.shibboleth.idp.attribute.resolver.spring.dc.impl.ContextDerivedDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.PairwiseIdDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.ScriptedDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.StaticDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.impl.StoredIdDataConnectorParser;
+import net.shibboleth.idp.attribute.resolver.spring.dc.impl.SubjectDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.ldap.impl.LDAPDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.rdbms.impl.RDBMSDataConnectorParser;
import net.shibboleth.idp.attribute.resolver.spring.dc.storage.impl.StorageServiceDataConnectorParser;
@@ -118,8 +120,9 @@ public class AttributeResolverNamespaceHandler extends BaseSpringNamespaceHandle
registerBeanDefinitionParser(ScriptedDataConnectorParser.TYPE_NAME_RESOLVER, new ScriptedDataConnectorParser());
registerBeanDefinitionParser(StaticDataConnectorParser.TYPE_NAME_RESOLVER, new StaticDataConnectorParser());
registerBeanDefinitionParser(StoredIdDataConnectorParser.TYPE_NAME_RESOLVER, new StoredIdDataConnectorParser());
- // Implement in IdP layer.
- // registerBeanDefinitionParser(SubjectDataConnectorParser.TYPE_NAME_RESOLVER, new SubjectDataConnectorParser());
+ registerBeanDefinitionParser(ContextDerivedDataConnectorParser.TYPE_NAME_RESOLVER,
+ new ContextDerivedDataConnectorParser());
+ registerBeanDefinitionParser(SubjectDataConnectorParser.TYPE_NAME_RESOLVER, new SubjectDataConnectorParser());
registerBeanDefinitionParser(StorageServiceDataConnectorParser.TYPE_NAME,
new StorageServiceDataConnectorParser());
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 8126677ef..9e9ff8757 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
@@ -3,7 +3,7 @@
xmlns:resolver="urn:mace:shibboleth:2.0:resolver"
xmlns:sec="urn:mace:shibboleth:2.0:security"
targetNamespace="urn:mace:shibboleth:2.0:resolver"
- elementFormDefault="qualified" version="4.1">
+ elementFormDefault="qualified" version="5.0">
<import namespace="http://www.w3.org/XML/1998/namespace" schemaLocation="http://www.w3.org/2001/xml.xsd"/>
<import namespace="urn:mace:shibboleth:2.0:security" schemaLocation="http://shibboleth.net/schema/idp/shibboleth-security.xsd"/>
@@ -1712,6 +1712,33 @@
</complexContent>
</complexType>
+ <complexType name="ContextDerived">
+ <annotation>
+ <documentation>A data connector to pull attributes from anywhere in the PRC tree</documentation>
+ </annotation>
+ <complexContent>
+ <extension base="resolver:BaseDataConnectorType">
+ <sequence>
+ <element ref="resolver:FailoverDataConnector" minOccurs="0" maxOccurs="1"/>
+ </sequence>
+ <attribute name="noResultIsError" type="resolver:string">
+ <annotation>
+ <documentation>
+ A boolean flag indicating whether an absence of any results will cause an error. If an error
+ is raised and a failover dependency is defined for this connector the failover will be invoked.
+ Default value is false.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="attributesFunctionRef" type="resolver:string" use="required">
+ <annotation>
+ <documentation>The Function to generate the Attributes given a PRC</documentation>
+ </annotation>
+ </attribute>
+ </extension>
+ </complexContent>
+ </complexType>
+
<complexType name="Subject">
<annotation>
<documentation>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list