Skip to content

Commit

Permalink
SHIBUI-2269
Browse files Browse the repository at this point in the history
Unit test to check that the service builds the proper XML for the "external provider"
  • Loading branch information
chasegawa committed Jun 28, 2022
1 parent b7e9253 commit a9e09db
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilF
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.SignatureValidationFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.opensaml.OpenSamlNameIdFormatFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver
Expand Down Expand Up @@ -286,6 +287,12 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
}
}

void constructXmlNodeForResolver(ExternalMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) {
markupBuilderDelegate.MetadataFilters(providerRef: 'InCommonMD') {
childNodes()
}
}

void constructXmlNodeForResolver(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) {
markupBuilderDelegate.MetadataProvider(id: resolver.xmlId,
'xsi:type': 'FileBackedHTTPMetadataProvider',
Expand Down Expand Up @@ -486,28 +493,26 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService {
xml.omitEmptyAttributes = true
xml.omitNullAttributes = true

// CHARLESTODO - determine wrapping type here - possible: https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter
xml.MetadataProvider(id: 'ShibbolethIdPUIGeneratedMetadata',
xmlns: 'urn:mace:shibboleth:2.0:metadata',
// https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter
xml.MetadataFilter(
'xsi:type': 'ByReference',
'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance',
'xsi:type': 'ChainingMetadataProvider',
'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd'
'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd',
'xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata',
'xmlns': 'urn:mace:shibboleth:2.0:metadata',
'xmlns:security': 'urn:mace:shibboleth:2.0:security',
'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion'
) {

resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each {
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr ->
// Only include the custom type: ExternalMetadataResolver
if ((mr.type != 'ExternalMetadataResolver') && (mr.enabled)) {
if ((mr.type == 'ExternalMetadataResolver') && (mr.enabled)) {
constructXmlNodeForResolver(mr, delegate) {
//TODO: enhance
def didNamespaceProtectionFilter = !(shibUIConfiguration.protectedAttributeNamespaces && shibUIConfiguration.protectedAttributeNamespaces.size() > 0)
mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter ->
if (filter.isFilterEnabled()) {
doNamespaceProtectionFilter()
constructXmlNodeForFilter(filter, delegate)
}
}
doNamespaceProtectionFilter()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,28 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.envers.Audited;

import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
@EqualsAndHashCode(callSuper = true)
@Getter
@Setter
@ToString
@Audited
public class ExternalMetadataResolver extends MetadataResolver {
}
@Column
private String description;

@Column(unique = true)
private String externalResolverId;

public ExternalMetadataResolver() {
type = "ExternalMetadataResolver";
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package edu.internet2.tier.shibboleth.admin.ui.service

import com.google.common.collect.Lists
import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest
import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration
import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration
import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute
import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeValue
import edu.internet2.tier.shibboleth.admin.ui.domain.XSString
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ClasspathMetadataResource
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.RegexScheme
Expand All @@ -18,6 +23,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSaml
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository
import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator
import edu.internet2.tier.shibboleth.admin.util.AttributeUtility
import groovy.xml.DOMBuilder
import groovy.xml.MarkupBuilder
import net.shibboleth.ext.spring.resource.ResourceHelper
Expand All @@ -31,6 +37,8 @@ import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.core.io.ClassPathResource
import org.springframework.test.context.ContextConfiguration
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.xmlunit.builder.DiffBuilder
import org.xmlunit.builder.Input
import spock.lang.Ignore
Expand Down Expand Up @@ -67,6 +75,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest {
@Autowired
TestObjectGenerator testObjectGenerator

AttributeUtility attributeUtility
DOMBuilder domBuilder = DOMBuilder.newInstance()
StringWriter writer = new StringWriter()
MarkupBuilder markupBuilder
Expand All @@ -75,13 +84,51 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest {
markupBuilder = new MarkupBuilder(writer)
markupBuilder.omitNullAttributes = true
markupBuilder.omitEmptyAttributes = true
attributeUtility = new AttributeUtility(openSamlObjects)
}

def cleanup() {
metadataResolverRepository.deleteAll()
writer.close()
}

def 'test generating ExternalMetadataResolver XML'() {
given:
def resolver = new ExternalMetadataResolver().with {
it.setEnabled(true)
it.setName("testme")
it.setExternalResolverId("InCommonMD")
it.setDescription("some description that won't appear in the xml")
it.addFilter(new EntityAttributesFilter().with {
it.name = 'EntityAttributes'
EntityAttributesFilterTarget filterTarget = testObjectGenerator.buildEntityAttributesFilterTarget()
filterTarget.setSingleValue("https://sp.example.org/shibboleth")
it.setEntityAttributesFilterTarget(filterTarget)
def attribute = attributeUtility.createAttributeWithStringValues('http://shibboleth.net/ns/attributes/releaseAllValues', null, 'eduPersonPrincipalName')
attribute.nameFormat = 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri'
attribute.namespacePrefix = 'saml2'
attribute.attributeValues.each { val ->
((XSString)val).namespacePrefix = 'saml2' +
''
}
it.attributes = [attribute]
it.intoTransientRepresentation()
it.enabled = true;
it
})
it
}
metadataResolverRepository.save(resolver)
metadataResolverService.reloadFilters("testme")

when:
Document doc = JPAMetadataResolverServiceImpl.cast(metadataResolverService).generateExternalMetadataFilterConfiguration()
Node node = doc.getFirstChild()

then:
generatedXmlIsTheSameAsExpectedXml('/conf/2269.xml', node)
}

def 'test adding a filter'() {
given:
def expectedXML = '''<?xml version="1.0" encoding="UTF-8"?>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ package edu.internet2.tier.shibboleth.admin.ui.util
import edu.internet2.tier.shibboleth.admin.ui.security.model.User
import groovy.xml.XmlUtil
import junit.framework.Assert
import javax.xml.transform.Source;
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult

import org.apache.commons.lang.StringUtils
import org.springframework.security.core.context.SecurityContextHolder
import org.w3c.dom.Document
import org.w3c.dom.Node
import org.xmlunit.builder.DiffBuilder
import org.xmlunit.builder.Input
import org.xmlunit.builder.Input.Builder

import javax.xml.transform.Source
import javax.xml.transform.Transformer
import javax.xml.transform.TransformerException
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult

/**
* @author Bill Smith (wsmith@unicon.net)
*/
Expand Down Expand Up @@ -50,6 +50,19 @@ class TestHelpers {
Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences());
}

static void generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Node generatedXml) {
def Builder builder = Input.fromNode(generatedXml)
def Source source = builder.build()
def myDiff = DiffBuilder.compare(Input.fromStream(TestHelpers.getResourceAsStream(expectedXmlResource)))
.withTest(builder)
.withAttributeFilter({attribute -> !attribute.name.equals("sourceDirectory")})
.ignoreComments()
.ignoreWhitespace()
.build()
System.out.println("@@@ \n" + getString(source) + "\n")
Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences());
}

public static String getString(DOMSource domSource) throws TransformerException {
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
Expand All @@ -67,4 +80,4 @@ class TestHelpers {
def user = new User(username: username, role: rolename)
Optional.of(user)
}
}
}
21 changes: 21 additions & 0 deletions backend/src/test/resources/conf/2269.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<MetadataFilter xsi:type="ByReference"
xmlns="urn:mace:shibboleth:2.0:metadata"
xmlns:security="urn:mace:shibboleth:2.0:security"
xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd">

<MetadataFilters providerRef="InCommonMD">
<MetadataFilter xsi:type="EntityAttributes">
<saml2:Attribute xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion"
Name="http://shibboleth.net/ns/attributes/releaseAllValues"
NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml2:AttributeValue xmlns:xsd="http://www.w3.org/2001/XMLSchema" xsi:type="xsd:string">eduPersonPrincipalName</saml2:AttributeValue>
</saml2:Attribute>
<Entity>https://sp.example.org/shibboleth</Entity>
</MetadataFilter>
</MetadataFilters>

</MetadataFilter>

0 comments on commit a9e09db

Please sign in to comment.