[java-identity-provider] branch master updated: IDP-1522 - Support for encrypted attributes in the resolver
Scott Cantor
cantor.2 at osu.edu
Tue Jun 30 17:29:26 UTC 2020
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=9c8e6d6bc1ad682abed92c95960a734399d92e08
The following commit(s) were added to refs/heads/master by this push:
new 9c8e6d6bc IDP-1522 - Support for encrypted attributes in the resolver
9c8e6d6bc is described below
commit 9c8e6d6bc1ad682abed92c95960a734399d92e08
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Jun 30 13:29:18 2020 -0400
IDP-1522 - Support for encrypted attributes in the resolver
https://issues.shibboleth.net/jira/browse/IDP-1522
---
.../ad/impl/DecryptedAttributeDefinition.java | 124 ++++++++++
.../resolver/ad/impl/DecryptedAttributeTest.java | 249 +++++++++++++++++++++
.../attribute/resolver/impl/ad/SealerKeyStore.jks | Bin 0 -> 984 bytes
.../attribute/resolver/impl/ad/SealerKeyStore.kver | 1 +
.../impl/DecryptedAttributeDefinitionParser.java | 54 +++++
.../impl/AttributeResolverNamespaceHandler.java | 5 +-
.../resolver/spring/AttributeResolverTest.java | 42 +++-
.../resolver/spring/attribute-resolver.xml | 21 +-
.../attribute/resolver/spring/externalBeans.xml | 21 +-
.../idp/attribute/resolver/spring/sealer.xml | 18 --
.../idp/attribute/resolver/spring/service.xml | 12 +-
.../attribute/resolver/spring/storageService.xml | 11 +-
.../net/shibboleth/idp/saml/impl/TestSources.java | 69 ++++--
.../schema/shibboleth-attribute-resolver.xsd | 22 ++
14 files changed, 587 insertions(+), 62 deletions(-)
diff --git a/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeDefinition.java b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeDefinition.java
new file mode 100644
index 000000000..ff8023940
--- /dev/null
+++ b/idp-attribute-resolver-impl/src/main/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeDefinition.java
@@ -0,0 +1,124 @@
+/*
+ * 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.ad.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.concurrent.ThreadSafe;
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+import net.shibboleth.idp.attribute.EmptyAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AbstractAttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.PluginDependencySupport;
+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.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.security.DataSealer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * An {@link AttributeDefinition} that creates an attribute whose values are the
+ * values of all its dependencies.
+ */
+ at ThreadSafe
+public class DecryptedAttributeDefinition extends AbstractAttributeDefinition {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(DecryptedAttributeDefinition.class);
+
+ /** The DataSealer that we'll use to decrypt the attribute. */
+ @NonnullAfterInit private DataSealer sealer;
+
+ /**
+ * Set the DataSealer (sealer) for this Definition.
+ *
+ * @param newSealer what to set
+ */
+ public void setDataSealer(@Nonnull final DataSealer newSealer) {
+ ComponentSupport.ifDestroyedThrowDestroyedComponentException(this);
+ ComponentSupport.ifInitializedThrowUnmodifiabledComponentException(this);
+
+ sealer = Constraint.isNotNull(newSealer, "DataSealer cannot be null");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void doInitialize() throws ComponentInitializationException {
+ super.doInitialize();
+
+ if (getDataConnectorDependencies().isEmpty() && getAttributeDependencies().isEmpty()) {
+ throw new ComponentInitializationException(getLogPrefix() + " no dependencies were configured");
+ } else if (sealer == null) {
+ throw new ComponentInitializationException("DataSealer cannot be null");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override @Nonnull protected IdPAttribute doAttributeDefinitionResolve(
+ @Nonnull final AttributeResolutionContext resolutionContext,
+ @Nonnull final AttributeResolverWorkContext workContext) throws ResolutionException {
+ Constraint.isNotNull(workContext, "AttributeResolverWorkContext cannot be null");
+
+ final List<IdPAttributeValue> results =
+ PluginDependencySupport.getMergedAttributeValues(workContext, getAttributeDependencies(),
+ getDataConnectorDependencies(), getId());
+
+ final Collection<IdPAttributeValue> decryptedValues = new ArrayList<>(results.size());
+
+ for (final IdPAttributeValue value : results) {
+
+ if (value instanceof EmptyAttributeValue) {
+ log.trace("{} Passing through EmptyAttributeValue", getLogPrefix());
+ decryptedValues.add(value);
+ continue;
+ } else if (!(value instanceof StringAttributeValue)) {
+ log.warn("{} Ignoring non-string-valued IdPAttributeValue type {}", getLogPrefix(),
+ value.getClass().getSimpleName());
+ continue;
+ }
+
+ log.trace("{} Encrypted attribute value: {}", getLogPrefix(), ((StringAttributeValue) value).getValue());
+
+ try{
+ final String decrypted = sealer.unwrap(((StringAttributeValue) value).getValue());
+ log.trace("{}: Decrypted attribute value: {}", getLogPrefix(), decrypted);
+ decryptedValues.add(new StringAttributeValue(decrypted));
+
+ } catch(final Exception e){
+ log.warn("{}: Error decrypting attribute: {}", getLogPrefix(), e);
+ }
+ }
+
+ final IdPAttribute decryptedAttribute = new IdPAttribute(getId());
+ decryptedAttribute.setValues(decryptedValues);
+
+ return decryptedAttribute;
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-impl/src/test/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeTest.java b/idp-attribute-resolver-impl/src/test/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeTest.java
new file mode 100644
index 000000000..0bdb05419
--- /dev/null
+++ b/idp-attribute-resolver-impl/src/test/java/net/shibboleth/idp/attribute/resolver/ad/impl/DecryptedAttributeTest.java
@@ -0,0 +1,249 @@
+/*
+ * 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.ad.impl;
+
+import static org.testng.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.core.io.ClassPathResource;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import net.shibboleth.idp.attribute.EmptyAttributeValue;
+import net.shibboleth.idp.attribute.EmptyAttributeValue.EmptyType;
+import net.shibboleth.idp.attribute.IdPAttribute;
+import net.shibboleth.idp.attribute.IdPAttributeValue;
+import net.shibboleth.idp.attribute.StringAttributeValue;
+import net.shibboleth.idp.attribute.resolver.AttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.DataConnector;
+import net.shibboleth.idp.attribute.resolver.ResolutionException;
+import net.shibboleth.idp.attribute.resolver.ResolverAttributeDefinitionDependency;
+import net.shibboleth.idp.attribute.resolver.ResolverDataConnectorDependency;
+import net.shibboleth.idp.attribute.resolver.ResolverTestSupport;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolutionContext;
+import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContext;
+import net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImpl;
+import net.shibboleth.idp.attribute.resolver.impl.AttributeResolverImplTest;
+import net.shibboleth.idp.saml.impl.TestSources;
+import net.shibboleth.utilities.java.support.collection.LazySet;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.resource.Resource;
+import net.shibboleth.utilities.java.support.resource.TestResourceConverter;
+import net.shibboleth.utilities.java.support.security.DataSealer;
+import net.shibboleth.utilities.java.support.security.DataSealerException;
+import net.shibboleth.utilities.java.support.security.impl.BasicKeystoreKeyStrategy;
+
+/** Test for {@link DecryptedAttributeDefinition}. */
+public class DecryptedAttributeTest {
+
+ private static final String TEST_ATTRIBUTE_NAME = "decrypted";
+
+ private DataSealer dataSealer;
+
+ @BeforeClass public void setUp() throws ComponentInitializationException {
+ ClassPathResource resource =
+ new ClassPathResource("net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.jks");
+ final Resource keystoreResource = TestResourceConverter.of(resource);
+
+ resource = new ClassPathResource("net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.kver");
+ final Resource versionResource = TestResourceConverter.of(resource);
+
+ final BasicKeystoreKeyStrategy strategy = new BasicKeystoreKeyStrategy();
+
+ strategy.setKeyAlias("secret");
+ strategy.setKeyPassword("kpassword");
+
+ strategy.setKeystorePassword("password");
+ strategy.setKeystoreResource(keystoreResource);
+
+ strategy.setKeyVersionResource(versionResource);
+
+ strategy.initialize();
+
+ dataSealer = new DataSealer();
+ dataSealer.setKeyStrategy(strategy);
+ dataSealer.initialize();
+ }
+
+ /**
+ * Test resolution of an empty definition to nothing.
+ *
+ * @throws ResolutionException if resolution failed.
+ * @throws ComponentInitializationException if initialization fails (which it shouldn't).
+ */
+ @Test public void empty() throws ResolutionException, ComponentInitializationException {
+ final DecryptedAttributeDefinition decrypted = new DecryptedAttributeDefinition();
+ decrypted.setId(TEST_ATTRIBUTE_NAME);
+ try {
+ decrypted.initialize();
+ fail("no dependencies");
+ } catch (final ComponentInitializationException e) {
+
+ }
+ decrypted.setDataConnectorDependencies(Collections.singleton(TestSources.makeDataConnectorDependency("foo", "bar")));
+
+ try {
+ decrypted.initialize();
+ fail("no DataSealer");
+ } catch (final ComponentInitializationException e) {
+
+ }
+
+ decrypted.setDataSealer(dataSealer);
+ decrypted.initialize();
+
+ final AttributeResolutionContext context = new AttributeResolutionContext();
+ context.getSubcontext(AttributeResolverWorkContext.class, true);
+ final IdPAttribute result = decrypted.resolve(context);
+
+ assertTrue(result.getValues().isEmpty());
+ }
+
+ /**
+ * Test when dependent on a data connector.
+ *
+ * @throws ComponentInitializationException if initialization fails (which it shouldn't).
+ * @throws DataSealerException
+ */
+ @Test public void dataConnector() throws ComponentInitializationException, DataSealerException {
+
+ // Set the dependency on the data connector
+ final DecryptedAttributeDefinition decrypted = new DecryptedAttributeDefinition();
+ decrypted.setId(TEST_ATTRIBUTE_NAME);
+
+ final Set<ResolverDataConnectorDependency> dependencySet = new LazySet<>();
+ dependencySet.add(TestSources.makeDataConnectorDependency(TestSources.STATIC_CONNECTOR_NAME,
+ TestSources.DEPENDS_ON_ATTRIBUTE_NAME_CONNECTOR));
+ decrypted.setDataConnectorDependencies(dependencySet);
+ decrypted.setDataSealer(dataSealer);
+ decrypted.initialize();
+
+ // Generate encrypted data.
+ final IdPAttribute attr1 = new IdPAttribute(TestSources.DEPENDS_ON_ATTRIBUTE_NAME_CONNECTOR);
+ attr1.setValues(List.of(new StringAttributeValue(dataSealer.wrap(TestSources.COMMON_ATTRIBUTE_VALUE_STRING)),
+ new StringAttributeValue(dataSealer.wrap(TestSources.CONNECTOR_ATTRIBUTE_VALUE_STRING))));
+
+ final IdPAttribute attr2 = new IdPAttribute(TestSources.DEPENDS_ON_SECOND_ATTRIBUTE_NAME);
+ attr2.setValues(List.of(new StringAttributeValue(dataSealer.wrap(TestSources.SECOND_ATTRIBUTE_VALUE_STRINGS[0])),
+ new StringAttributeValue(dataSealer.wrap(TestSources.SECOND_ATTRIBUTE_VALUE_STRINGS[1]))));
+
+ // And resolve
+ final Set<DataConnector> connectorSet = new LazySet<>();
+ connectorSet.add(TestSources.populatedStaticConnector(List.of(attr1,attr2)));
+
+ final Set<AttributeDefinition> attributeSet = new LazySet<>();
+ attributeSet.add(decrypted);
+
+ final AttributeResolverImpl resolver = AttributeResolverImplTest.newAttributeResolverImpl("foo", attributeSet, connectorSet);
+ resolver.initialize();
+
+ final AttributeResolutionContext context = new AttributeResolutionContext();
+ try {
+ resolver.resolveAttributes(context);
+ } catch (final ResolutionException e) {
+ fail("resolution failed", e);
+ }
+
+ final Collection<?> values = context.getResolvedIdPAttributes().get(TEST_ATTRIBUTE_NAME).getValues();
+ assertEquals(values.size(), 2);
+ assertTrue(values.contains(TestSources.COMMON_ATTRIBUTE_VALUE_RESULT), "looking for " + TestSources.COMMON_ATTRIBUTE_VALUE_STRING);
+ assertTrue(values.contains(TestSources.CONNECTOR_ATTRIBUTE_VALUE_RESULT),
+ "looking for " + TestSources.CONNECTOR_ATTRIBUTE_VALUE_STRING);
+ }
+
+ /**
+ * Test when dependent on another attribute.
+ *
+ * @throws ComponentInitializationException if initialization fails (which it shouldn't).
+ * @throws DataSealerException
+ */
+ @Test public void attribute() throws ComponentInitializationException, DataSealerException {
+
+ final DecryptedAttributeDefinition decrypted = new DecryptedAttributeDefinition();
+ decrypted.setId(TEST_ATTRIBUTE_NAME);
+
+ final Set<ResolverAttributeDefinitionDependency> dependencySet = new LazySet<>();
+ dependencySet.add(TestSources.makeAttributeDefinitionDependency(TestSources.DEPENDS_ON_ATTRIBUTE_NAME_ATTR));
+ decrypted.setAttributeDependencies(dependencySet);
+ decrypted.setDataSealer(dataSealer);
+ decrypted.initialize();
+
+ final Set<AttributeDefinition> am = new LazySet<>();
+ am.add(decrypted);
+
+ final IdPAttribute dependency = new IdPAttribute(TestSources.DEPENDS_ON_ATTRIBUTE_NAME_ATTR);
+ dependency.setValues(List.of(new StringAttributeValue(dataSealer.wrap(TestSources.COMMON_ATTRIBUTE_VALUE_STRING)),
+ new StringAttributeValue(dataSealer.wrap(TestSources.ATTRIBUTE_ATTRIBUTE_VALUE_STRING))));
+ am.add(TestSources.populatedStaticAttribute(dependency));
+
+ final AttributeResolverImpl resolver = AttributeResolverImplTest.newAttributeResolverImpl("foo", am, null);
+ resolver.initialize();
+
+ final AttributeResolutionContext context = new AttributeResolutionContext();
+ try {
+ resolver.resolveAttributes(context);
+ } catch (final ResolutionException e) {
+ fail("resolution failed", e);
+ }
+ final Collection<IdPAttributeValue> values = context.getResolvedIdPAttributes().get(TEST_ATTRIBUTE_NAME).getValues();
+
+ assertEquals(values.size(), 2);
+ assertTrue(values.contains(TestSources.COMMON_ATTRIBUTE_VALUE_RESULT),
+ "looking for value " + TestSources.COMMON_ATTRIBUTE_VALUE_STRING);
+ assertTrue(values.contains(TestSources.ATTRIBUTE_ATTRIBUTE_VALUE_RESULT),
+ "looking for value " + TestSources.ATTRIBUTE_ATTRIBUTE_VALUE_STRING);
+ }
+
+ /**
+ * Test resolution of an empty definition to nothing.
+ *
+ * @throws ResolutionException if resolution failed.
+ * @throws ComponentInitializationException if initialization fails (which it shouldn't).
+ */
+ @Test public void nullValue() throws ResolutionException, ComponentInitializationException {
+ final List<IdPAttributeValue> values = new ArrayList<>(3);
+ values.add(TestSources.COMMON_ATTRIBUTE_VALUE_RESULT);
+ values.add(new EmptyAttributeValue(EmptyType.NULL_VALUE));
+ final IdPAttribute attr = new IdPAttribute(TestSources.DEPENDS_ON_ATTRIBUTE_NAME_ATTR);
+
+ attr.setValues(values);
+
+ final AttributeResolutionContext resolutionContext =
+ ResolverTestSupport.buildResolutionContext(ResolverTestSupport.buildDataConnector("connector1", attr));
+ final ResolverDataConnectorDependency depend = TestSources.makeDataConnectorDependency("connector1", TestSources.DEPENDS_ON_ATTRIBUTE_NAME_ATTR);
+
+ final DecryptedAttributeDefinition decrypted = new DecryptedAttributeDefinition();
+ decrypted.setId(TEST_ATTRIBUTE_NAME);
+ decrypted.setDataConnectorDependencies(Collections.singleton(depend));
+ decrypted.setDataSealer(dataSealer);
+ decrypted.initialize();
+
+ final IdPAttribute result = decrypted.resolve(resolutionContext);
+
+ final List<IdPAttributeValue> outValues = result.getValues();
+ assertEquals(outValues.size(), 1);
+ assertFalse(outValues.contains(TestSources.COMMON_ATTRIBUTE_VALUE_RESULT));
+ assertTrue(outValues.contains(new EmptyAttributeValue(EmptyType.NULL_VALUE)));
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.jks b/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.jks
new file mode 100644
index 000000000..147d92bb0
Binary files /dev/null and b/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.jks differ
diff --git a/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.kver b/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.kver
new file mode 100644
index 000000000..2cd48df38
--- /dev/null
+++ b/idp-attribute-resolver-impl/src/test/resources/net/shibboleth/idp/attribute/resolver/impl/ad/SealerKeyStore.kver
@@ -0,0 +1 @@
+CurrentVersion = 1
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/DecryptedAttributeDefinitionParser.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/DecryptedAttributeDefinitionParser.java
new file mode 100644
index 000000000..cbdec83ac
--- /dev/null
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/ad/impl/DecryptedAttributeDefinitionParser.java
@@ -0,0 +1,54 @@
+/*
+ * 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.ad.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.ad.impl.DecryptedAttributeDefinition;
+import net.shibboleth.idp.attribute.resolver.spring.ad.BaseAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.impl.AttributeResolverNamespaceHandler;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/** Bean definition parser for a {@link DecryptedAttributeDefinition}. */
+public class DecryptedAttributeDefinitionParser extends BaseAttributeDefinitionParser {
+
+ /** Schema type name. */
+ @Nonnull public static final QName TYPE_NAME_RESOLVER =
+ new QName(AttributeResolverNamespaceHandler.NAMESPACE, "Decrypted");
+
+ /** {@inheritDoc} */
+ @Override protected Class<DecryptedAttributeDefinition> getBeanClass(@Nullable final Element element) {
+ return DecryptedAttributeDefinition.class;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void doParse(@Nonnull final Element config, @Nonnull final ParserContext parserContext,
+ @Nonnull final BeanDefinitionBuilder builder) {
+ super.doParse(config, parserContext, builder);
+
+ builder.addPropertyReference("dataSealer",
+ StringSupport.trimOrNull(config.getAttributeNS(null, "dataSealerRef")));
+ }
+
+}
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
index a5eeeb7d4..4991dbc1e 100644
--- a/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
+++ b/idp-attribute-resolver-spring/src/main/java/net/shibboleth/idp/attribute/resolver/spring/impl/AttributeResolverNamespaceHandler.java
@@ -31,6 +31,7 @@ import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SAML2NameIDAttribute
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.ScopedAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.ScriptedAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SimpleAttributeDefinitionParser;
+import net.shibboleth.idp.attribute.resolver.spring.ad.impl.DecryptedAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.SubjectDerivedAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.ad.impl.TemplateAttributeDefinitionParser;
import net.shibboleth.idp.attribute.resolver.spring.ad.mapped.impl.MappedAttributeDefinitionParser;
@@ -93,6 +94,8 @@ public class AttributeResolverNamespaceHandler extends BaseSpringNamespaceHandle
new ScriptedAttributeDefinitionParser());
registerBeanDefinitionParser(SimpleAttributeDefinitionParser.TYPE_NAME_RESOLVER,
new SimpleAttributeDefinitionParser());
+ registerBeanDefinitionParser(DecryptedAttributeDefinitionParser.TYPE_NAME_RESOLVER,
+ new DecryptedAttributeDefinitionParser());
registerBeanDefinitionParser(TemplateAttributeDefinitionParser.TYPE_NAME_RESOLVER,
new TemplateAttributeDefinitionParser());
registerBeanDefinitionParser(SourceValueParser.TYPE_NAME_RESOLVER, new SourceValueParser());
@@ -140,4 +143,4 @@ public class AttributeResolverNamespaceHandler extends BaseSpringNamespaceHandle
}
// Checkstyle: MethodLength ON
-}
\ No newline at end of file
+}
diff --git a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
index 60a22e47e..87243f406 100644
--- a/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
+++ b/idp-attribute-resolver-spring/src/test/java/net/shibboleth/idp/attribute/resolver/spring/AttributeResolverTest.java
@@ -25,6 +25,7 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -53,6 +54,7 @@ import com.unboundid.ldap.sdk.LDAPException;
import net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor;
import net.shibboleth.ext.spring.config.StringToDurationConverter;
+import net.shibboleth.ext.spring.config.StringToResourceConverter;
import net.shibboleth.ext.spring.util.SchemaTypeAwareXMLBeanDefinitionReader;
import net.shibboleth.idp.attribute.IdPAttribute;
import net.shibboleth.idp.attribute.IdPAttributeValue;
@@ -66,6 +68,8 @@ import net.shibboleth.idp.saml.impl.TestSources;
import net.shibboleth.idp.testing.DatabaseTestingSupport;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.security.DataSealer;
+import net.shibboleth.utilities.java.support.security.DataSealerException;
import net.shibboleth.utilities.java.support.service.ReloadableService;
import net.shibboleth.utilities.java.support.service.ServiceException;
import net.shibboleth.utilities.java.support.service.ServiceableComponent;
@@ -160,6 +164,37 @@ public class AttributeResolverTest extends OpenSAMLInitBaseTestCase {
helper(false);
}
+ /**
+ * Not actually a test, just a convenience method for encrypting a value to put into the test data.
+ * @throws DataSealerException
+ * @throws ComponentInitializationException
+ */
+ @Test(enabled=false)
+ private void dumpEncryptedString() throws DataSealerException {
+ final String inputFile ="net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml";
+
+ final GenericApplicationContext context = new GenericApplicationContext();
+ context.getBeanFactory().addBeanPostProcessor(new IdentifiableBeanPostProcessor());
+ setTestContext(context);
+ context.setDisplayName("ApplicationContext: " + AttributeResolverTest.class);
+
+ final ConversionServiceFactoryBean service = new ConversionServiceFactoryBean();
+ context.setDisplayName("ApplicationContext: ");
+ service.setConverters(Set.of(new StringToDurationConverter(), new StringToResourceConverter()));
+ service.afterPropertiesSet();
+
+ context.getBeanFactory().setConversionService(service.getObject());
+
+ final SchemaTypeAwareXMLBeanDefinitionReader beanDefinitionReader =
+ new SchemaTypeAwareXMLBeanDefinitionReader(context);
+
+ beanDefinitionReader.loadBeanDefinitions(inputFile);
+ context.refresh();
+
+ final DataSealer sealer = context.getBean("encryptedAttribute.DataSealer", DataSealer.class);
+ log.info("Encrypted string is {}", sealer.wrap("Hello World"));
+ }
+
private void helper(final boolean stripNulls) throws ComponentInitializationException, ServiceException, ResolutionException {
final String inputFile;
@@ -195,7 +230,7 @@ public class AttributeResolverTest extends OpenSAMLInitBaseTestCase {
final Map<String, IdPAttribute> resolvedAttributes = resolutionContext.getResolvedIdPAttributes();
log.debug("resolved attributes '{}'", resolvedAttributes);
- assertEquals(resolvedAttributes.size(), 14);
+ assertEquals(resolvedAttributes.size(), 15);
// Static
IdPAttribute attribute = resolvedAttributes.get("eduPersonAffiliation");
@@ -204,6 +239,11 @@ public class AttributeResolverTest extends OpenSAMLInitBaseTestCase {
assertEquals(values.size(), expectedEPAValues);
assertTrue(values.contains(new StringAttributeValue("member")));
+
+ attribute = resolvedAttributes.get("decryptedOne");
+ assertNotNull(attribute);
+ values = attribute.getValues();
+ assertTrue(values.contains(new StringAttributeValue("Hello World")));
// Broken (case 665)
attribute = resolvedAttributes.get("broken");
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
index d4d774fdd..fba76d169 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<AttributeResolver xmlns="urn:mace:shibboleth:2.0:resolver" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">
@@ -29,6 +30,11 @@
<InputAttributeDefinition ref="eduPersonAffiliation" />
</AttributeDefinition>
+ <AttributeDefinition xsi:type="Decrypted" id="decryptedOne" dataSealerRef="encryptedAttribute.DataSealer">
+ <InputDataConnector ref="staticEncrypted" attributeNames="encryptedOne"/>
+ </AttributeDefinition>
+
+
<!-- Schema: Core schema attributes-->
<AttributeDefinition xsi:type="Simple" id="uid">
@@ -202,14 +208,21 @@
<!-- Data Connectors -->
<!-- ========================================== -->
+ <DataConnector id="staticEncrypted" xsi:type="Static">
+ <Attribute id="encryptedOne">
+ <!-- plaintext: Hello World -->
+ <Value>AAdzZWNyZXQxfrZRV23BOWmQMLc4mNEbYRxwgcY+z2Y8gm+0duysPsTsMJwa66gqhwM18uFw/PsGtcBYClwLmfs8fLIFP0lNAG7jpQ==</Value>
+ </Attribute>
+ </DataConnector>
+
<!-- Example Relational Database Connector -->
<DataConnector id="myDB" xsi:type="RelationalDatabase">
<SimpleManagedConnection
- jdbcDriver="org.hsqldb.jdbc.JDBCDriver"
- jdbcURL="jdbc:hsqldb:mem:myTestDB"
- jdbcUserName="SA"
- jdbcPassword="" />
+ jdbcDriver="org.hsqldb.jdbc.JDBCDriver"
+ jdbcURL="jdbc:hsqldb:mem:myTestDB"
+ jdbcUserName="SA"
+ jdbcPassword="" />
<QueryTemplate>
<![CDATA[
SELECT * FROM student WHERE userid = '$resolutionContext.principal'
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml
index 3c9ddfe18..90240899d 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml
@@ -6,7 +6,10 @@
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
+
+ default-init-method="initialize"
+ default-destroy-method="destroy">
<bean id="shibboleth.VelocityEngine" class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
@@ -21,7 +24,19 @@
</props>
</property>
</bean>
-
+
+ <bean id="encryptedAttribute.DataSealer" class="net.shibboleth.utilities.java.support.security.DataSealer">
+ <property name="keyStrategy">
+ <bean class="net.shibboleth.utilities.java.support.security.impl.BasicKeystoreKeyStrategy"
+ p:keyAlias="secret"
+ p:keystoreResource="classpath:/net/shibboleth/idp/attribute/resolver/spring/ad/SealerKeyStore.jks"
+ p:keyVersionResource="classpath:/net/shibboleth/idp/attribute/resolver/spring/ad/SealerKeyStore.kver"
+ p:keystorePassword="password"
+ p:keyPassword="kpassword"
+ p:updateInterval="PT0S" />
+ </property>
+ </bean>
+
<bean id="shibboleth.PropertySourcesPlaceholderConfigurer"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"
p:placeholderPrefix="%{" p:placeholderSuffix="}" />
@@ -37,4 +52,4 @@
c:path="net/shibboleth/idp/attribute/resolver/spring/dc/rdbms/rdbms-attribute-resolver-spring-props-context.xml"/>
</util:list>
-</beans>
\ No newline at end of file
+</beans>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/sealer.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/sealer.xml
deleted file mode 100644
index 893f1a7d0..000000000
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/sealer.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:util="http://www.springframework.org/schema/util"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
-
- <bean id="shibboleth.TransientIDDataSealer" class="net.shibboleth.utilities.java.support.security.DataSealer">
- <property name="keyStrategy">
- <bean class="net.shibboleth.utilities.java.support.security.impl.BasicKeystoreKeyStrategy"
- p:keystoreResource="/net/shibboleth/idp/attribute/resolver/spring/ad/SealerKeyStore.jks"
- p:keyVersionResource="/net/shibboleth/idp/attribute/resolver/spring/ad/SealerKeyStore.kver"
- p:keystorePassword="kpassword"
- p:keyPassword="password"
- p:updateInterval="PT0S" />
- </property>
- </bean>
-</beans>
\ No newline at end of file
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/service.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/service.xml
index 0a5ed25d4..2c594187b 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/service.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/service.xml
@@ -6,13 +6,13 @@
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize"
- default-destroy-method="destroy"
- >
+ default-destroy-method="destroy">
<!-- This BeanPostProcessor auto-sets identifiable beans with the bean name (if not already set). -->
<bean id="shibboleth.IdentifiableBeanPostProcessor"
class="net.shibboleth.ext.spring.config.IdentifiableBeanPostProcessor" />
-
+
+
<bean id="shibboleth.VelocityEngine" class="net.shibboleth.ext.spring.velocity.VelocityEngineFactoryBean">
<property name="velocityProperties">
<props>
@@ -26,7 +26,7 @@
</props>
</property>
</bean>
- <bean id="shibboleth.AttributeResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
+ <bean id="shibboleth.AttributeResolverService" class="net.shibboleth.ext.spring.service.ReloadableSpringService"
depends-on="shibboleth.VelocityEngine"
p:beanPostProcessors-ref="shibboleth.IdentifiableBeanPostProcessor"
p:failFast="false" p:reloadCheckDelay="0">
@@ -40,11 +40,11 @@
</constructor-arg>
<property name="serviceConfigurations">
<util:list>
- <value>net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml</value>
+ <value>net/shibboleth/idp/attribute/resolver/spring/externalBeans.xml</value>
<value>net/shibboleth/idp/attribute/resolver/spring/storageService.xml</value>
<value>net/shibboleth/idp/attribute/resolver/spring/attribute-resolver.xml</value>
<value>net/shibboleth/idp/attribute/resolver/spring/dc/staticAttributesNative.xml</value>
</util:list>
</property>
</bean>
-</beans>
\ No newline at end of file
+</beans>
diff --git a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/storageService.xml b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/storageService.xml
index eec8099dc..e2fd196f5 100644
--- a/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/storageService.xml
+++ b/idp-attribute-resolver-spring/src/test/resources/net/shibboleth/idp/attribute/resolver/spring/storageService.xml
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-init-method="initialize"
@@ -14,9 +14,10 @@
<list>
<bean class="net.shibboleth.ext.spring.config.StringToIPRangeConverter"/>
<bean class="net.shibboleth.ext.spring.config.StringToDurationConverter"/>
+ <bean class="net.shibboleth.ext.spring.config.StringToResourceConverter" />
</list>
</property>
</bean>
- <bean id="shibboleth.StorageService" p:id="test" class="org.opensaml.storage.impl.MemoryStorageService"
- p:cleanupInterval="PT10M" />
-</beans>
\ No newline at end of file
+ <bean id="shibboleth.StorageService" p:id="test" class="org.opensaml.storage.impl.MemoryStorageService"
+ p:cleanupInterval="PT10M" />
+</beans>
diff --git a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/impl/TestSources.java b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/impl/TestSources.java
index 56785e4e7..21dd91881 100644
--- a/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/impl/TestSources.java
+++ b/idp-saml-impl/src/test/java/net/shibboleth/idp/saml/impl/TestSources.java
@@ -18,13 +18,11 @@
package net.shibboleth.idp.saml.impl;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.regex.Pattern;
import javax.annotation.Nonnull;
@@ -47,8 +45,8 @@ import net.shibboleth.idp.attribute.resolver.context.AttributeResolverWorkContex
import net.shibboleth.idp.saml.attribute.resolver.impl.SAML2NameIDAttributeDefinition;
import net.shibboleth.idp.testing.DatabaseTestingSupport;
import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
import net.shibboleth.utilities.java.support.annotation.constraint.NullableElements;
-import net.shibboleth.utilities.java.support.collection.LazySet;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.component.ComponentSupport;
@@ -120,6 +118,24 @@ public final class TestSources {
private TestSources() {
}
+ /**
+ * Create a static connector with provided attributes and values.
+ *
+ * @param attributes the objects to populate it with
+ * @return The connector
+ * @throws ComponentInitializationException if we cannot initialized (unlikely)
+ */
+ public static DataConnector populatedStaticConnector(@Nonnull @NonnullElements final List<IdPAttribute> attributes)
+ throws ComponentInitializationException {
+
+ final StaticDataConnector connector = new StaticDataConnector();
+ connector.setId(STATIC_CONNECTOR_NAME);
+ connector.setValues(attributes);
+ connector.initialize();
+
+ return connector;
+ }
+
/**
* Create a static connector with known attributes and values.
*
@@ -127,27 +143,19 @@ public final class TestSources {
* @throws ComponentInitializationException if we cannot initialized (unlikely)
*/
public static DataConnector populatedStaticConnector() throws ComponentInitializationException {
- IdPAttribute attr;
- Set<IdPAttribute> attributeSet;
-
- attributeSet = new LazySet<>();
+ List<IdPAttribute> attributeSet = new ArrayList<>(2);
- attr = new IdPAttribute(DEPENDS_ON_ATTRIBUTE_NAME_CONNECTOR);
- attr.setValues(Arrays.asList(new StringAttributeValue(COMMON_ATTRIBUTE_VALUE_STRING),
+ IdPAttribute attr = new IdPAttribute(DEPENDS_ON_ATTRIBUTE_NAME_CONNECTOR);
+ attr.setValues(List.of(new StringAttributeValue(COMMON_ATTRIBUTE_VALUE_STRING),
new StringAttributeValue(CONNECTOR_ATTRIBUTE_VALUE_STRING)));
attributeSet.add(attr);
attr = new IdPAttribute(DEPENDS_ON_SECOND_ATTRIBUTE_NAME);
- attr.setValues(Arrays.asList(new StringAttributeValue(SECOND_ATTRIBUTE_VALUE_STRINGS[0]),
+ attr.setValues(List.of(new StringAttributeValue(SECOND_ATTRIBUTE_VALUE_STRINGS[0]),
new StringAttributeValue(SECOND_ATTRIBUTE_VALUE_STRINGS[1])));
attributeSet.add(attr);
-
- StaticDataConnector connector = new StaticDataConnector();
- connector.setId(STATIC_CONNECTOR_NAME);
- connector.setValues(attributeSet);
- connector.initialize();
-
- return connector;
+
+ return populatedStaticConnector(attributeSet);
}
/**
@@ -159,11 +167,11 @@ public final class TestSources {
public static AttributeDefinition populatedStaticAttribute() throws ComponentInitializationException {
return populatedStaticAttribute(DEPENDS_ON_ATTRIBUTE_NAME_ATTR, 2);
}
-
+
public static AttributeDefinition populatedStaticAttribute(String attributeName,
int attributeValuesCount) throws ComponentInitializationException {
- IdPAttribute attr;
- List<IdPAttributeValue> valuesList = new ArrayList<>();
+
+ final List<IdPAttributeValue> valuesList = new ArrayList<>();
if (attributeValuesCount > 0) {
valuesList.add(new StringAttributeValue(COMMON_ATTRIBUTE_VALUE_STRING));
@@ -174,12 +182,25 @@ public final class TestSources {
for (int i = 2; i < attributeValuesCount; i++) {
valuesList.add(new StringAttributeValue(ATTRIBUTE_ATTRIBUTE_VALUE_STRING + i));
}
- attr = new IdPAttribute(attributeName);
+ final IdPAttribute attr = new IdPAttribute(attributeName);
attr.setValues(valuesList);
- StaticAttributeDefinition definition = new StaticAttributeDefinition();
- definition.setId(attributeName);
- definition.setValue(attr);
+ return populatedStaticAttribute(attr);
+ }
+
+ /**
+ * Create a static attribute with known attribute.
+ *
+ * @param attribute the input attribute
+ * @return the attribute definition
+ * @throws ComponentInitializationException if we cannot initialized (unlikely)
+ */
+ public static AttributeDefinition populatedStaticAttribute(@Nonnull final IdPAttribute attribute)
+ throws ComponentInitializationException {
+
+ final StaticAttributeDefinition definition = new StaticAttributeDefinition();
+ definition.setId(attribute.getId());
+ definition.setValue(attribute);
definition.initialize();
return definition;
}
diff --git a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
index 1bec5e739..769ac5df4 100644
--- a/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
+++ b/idp-schema/src/main/resources/schema/shibboleth-attribute-resolver.xsd
@@ -638,6 +638,28 @@
</extension>
</complexContent>
</complexType>
+
+ <complexType name="Decrypted">
+ <annotation>
+ <documentation>An attribute definition involving an encrypted (DataSealed) attribute</documentation>
+ </annotation>
+ <complexContent>
+ <extension base="resolver:BaseAttributeDefinitionType">
+ <choice maxOccurs="unbounded" minOccurs="0">
+ <element ref="resolver:InputAttributeDefinition"/>
+ <element ref="resolver:InputDataConnector"/>
+ <element name="DisplayName" type="resolver:LocalizedStringType"/>
+ <element name="DisplayDescription" type="resolver:LocalizedStringType"/>
+ <element ref="resolver:AttributeEncoder"/>
+ </choice>
+ <attribute name="dataSealerRef" type="resolver:string">
+ <annotation>
+ <documentation>Value to use for the decryption key</documentation>
+ </annotation>
+ </attribute>
+ </extension>
+ </complexContent>
+ </complexType>
<complexType name="SubjectDerivedAttribute">
<annotation>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list