Skip to content

Commit

Permalink
Merged in SHIBUI-456 (pull request #63)
Browse files Browse the repository at this point in the history
SHIBUI-456

* [SHIBUI-456]

    Fix tomcat configuration for `/entities` endpoint

    update documentation

* [SHIBUI-456]

    Fix tomcat configuration for `/entities` endpoint

* [SHIBUI-456]

    Copied tests from EntityControllerTests and modified to work with WebTestClient (and a live Tomcat).
  • Loading branch information
Bill Smith authored and Jonathan Johnson committed Apr 27, 2018
1 parent a9f5dcc commit 85e508b
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 16 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,17 @@ allowed with:
-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
```

In Apache HTTPD, you'll need something like:

```
<VirtualHost *:80>
AllowEncodedSlashes NoDecode
ServerName shibui.unicon.net
ProxyPass / http://localhost:8080/ nocanon
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
```

### Running as an executable

`java -jar shibui.war`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package edu.internet2.tier.shibboleth.admin.ui.configuration;

import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.stereotype.Component;

@Component
public class TomcatConfiguration implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {
@Override
public void customize(ConfigurableServletWebServerFactory factory) {
System.setProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "true");
}
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,41 @@
package edu.internet2.tier.shibboleth.admin.ui.controller

import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import net.shibboleth.ext.spring.resource.ResourceHelper
import org.joda.time.DateTime
import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver
import org.opensaml.saml.metadata.resolver.MetadataResolver
import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain
import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.Bean
import org.springframework.core.io.ClassPathResource
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.web.reactive.server.WebTestClient
import org.springframework.web.util.DefaultUriBuilderFactory
import org.xmlunit.builder.DiffBuilder
import org.xmlunit.builder.Input
import org.xmlunit.diff.DefaultNodeMatcher
import org.xmlunit.diff.ElementSelectors
import spock.lang.Specification

/**
* @author Bill Smith (wsmith@unicon.net)
*/
// TODO: implement
// @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// @ActiveProfiles("no-auth")
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles("no-auth")
class EntitiesControllerIntegrationTests extends Specification {

@Autowired
private WebTestClient webClient

def setup() {
// yeah, don't ask... this is just shenanigans
this.webClient.webClient.uriBuilderFactory.encodingMode = DefaultUriBuilderFactory.EncodingMode.NONE
}

def "GET /api/entities returns the proper json"() {
given:
def expectedBody = '''
Expand Down Expand Up @@ -55,24 +74,108 @@ class EntitiesControllerIntegrationTests extends Specification {
'''

when:
def x = 1
// TODO: implement
/*
def result = this.webClient
.get()
.uri("/api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1")
.exchange()
*/
.exchange() // someday, I'd like to know why IntelliJ "cannot resolve symbol 'exchange'"

then:
assert 1
// TODO: implement
/*
result.expectStatus().isOk()
.expectBody().consumeWith(
{ response -> new String(response.getResponseBody()) == expectedBody }
)
//.expectedBody() // some other json comparison
*/
.expectBody()
.json(expectedBody)
}

def "GET /api/entities/test is not found"() {
when:
def result = this.webClient
.get()
.uri("/api/entities/test")
.exchange()

then:
result.expectStatus().isNotFound()
}

def "GET /api/entities/test XML is not found"() {
when:
def result = this.webClient
.get()
.uri("/api/entities/test")
.header('Accept', 'application/xml')
.exchange()

then:
result.expectStatus().isNotFound()
}

def "GET /api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1 XML returns proper XML"() {
given:
def expectedBody = '''<?xml version="1.0" encoding="UTF-8"?>
<md:EntityDescriptor xmlns:md="urn:oasis:names:tc:SAML:2.0:metadata" entityID="http://test.scaldingspoon.org/test1">
<md:Extensions>
<mdattr:EntityAttributes xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute">
<saml:Attribute xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Name="http://scaldingspoon.org/realm" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
<saml:AttributeValue>internal</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute xmlns:saml="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">
<saml:AttributeValue>givenName</saml:AttributeValue>
<saml:AttributeValue>employeeNumber</saml:AttributeValue>
</saml:Attribute>
</mdattr:EntityAttributes>
</md:Extensions>
<md:SPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<md:NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</md:NameIDFormat>
<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://test.scaldingspoon.org/test1/acs" index="1"/>
</md:SPSSODescriptor>
</md:EntityDescriptor>
'''
when:
def result = this.webClient
.get()
.uri("/api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1")
.header('Accept', 'application/xml')
.exchange()

then:
def resultBody = result.expectStatus().isOk()
//.expectHeader().contentType("application/xml;charset=ISO-8859-1") // should this really be ISO-8859-1?
// expectedBody encoding is UTF-8...
.expectHeader().contentType("application/xml;charset=UTF-8")
.expectBody(String.class)
.returnResult()
def diff = DiffBuilder.compare(Input.fromString(expectedBody)).withTest(Input.fromString(resultBody.getResponseBody())).ignoreComments().checkForSimilar().ignoreWhitespace().withNodeMatcher(new DefaultNodeMatcher(ElementSelectors.byNameAndText)).build()
!diff.hasDifferences()
}

@TestConfiguration
static class Config {
@Autowired
OpenSamlObjects openSamlObjects

@Bean
MetadataResolver metadataResolver() {
def resource = ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml"))
def aggregate = new ResourceBackedMetadataResolver(resource){
@Override
DateTime getLastRefresh() {
return null
}
}

aggregate.with {
it.metadataFilter = new MetadataFilterChain()
it.id = 'testme'
it.parserPool = openSamlObjects.parserPool
it.initialize()
it
}

return new ChainingMetadataResolver().with {
it.id = 'chain'
it.resolvers = [aggregate]
it.initialize()
it
}
}
}
}

0 comments on commit 85e508b

Please sign in to comment.