Skip to content

Commit

Permalink
Merged master into feature/SHIBUI-1734
Browse files Browse the repository at this point in the history
  • Loading branch information
chasegawa committed May 7, 2021
2 parents d6625a1 + 1f0606a commit 3cd2663
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package edu.internet2.tier.shibboleth.admin.ui.configuration;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.ShallowEtagHeaderFilter;

@Configuration
public class ETagsConfiguration {
@Bean
public FilterRegistrationBean<ShallowEtagHeaderFilter> shallowEtagHeaderFilter() {
FilterRegistrationBean<ShallowEtagHeaderFilter> filterRegistrationBean = new FilterRegistrationBean<>(new ShallowEtagHeaderFilter());
filterRegistrationBean.addUrlPatterns("/api/entities/*", "/entities/*");
filterRegistrationBean.setName("etagFilter");
return filterRegistrationBean;
}
}
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
package edu.internet2.tier.shibboleth.admin.ui.controller;

import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation;
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

import javax.servlet.http.HttpServletRequest;

import org.opensaml.core.criterion.EntityIdCriterion;
import org.opensaml.core.xml.io.MarshallingException;
import org.opensaml.saml.metadata.resolver.MetadataResolver;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation;
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects;
import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService;
import lombok.extern.slf4j.Slf4j;
import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
import net.shibboleth.utilities.java.support.resolver.ResolverException;

@Controller
@RequestMapping(value = "/api/entities", method = RequestMethod.GET)
@RequestMapping(value = { "/entities", // per protocol - https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol
"/api/entities" }, // existing - included to break no existing code
method = RequestMethod.GET)
@Slf4j
public class EntitiesController {
private static final Logger logger = LoggerFactory.getLogger(EntitiesController.class);

@Autowired
private MetadataResolver metadataResolver;

Expand All @@ -43,7 +46,8 @@ public ResponseEntity<?> getOne(final @PathVariable String entityId, HttpServlet
return ResponseEntity.notFound().build();
}
EntityDescriptorRepresentation entityDescriptorRepresentation = entityDescriptorService.createRepresentationFromDescriptor(entityDescriptor);
return ResponseEntity.ok(entityDescriptorRepresentation);
ResponseEntity result = ResponseEntity.ok(entityDescriptorRepresentation);
return result;
}

@RequestMapping(value = "{entityId:.*}", produces = "application/xml")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.springframework.boot.autoconfigure.domain.EntityScan
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest
import org.springframework.core.io.ClassPathResource
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import org.springframework.http.HttpHeaders
import org.springframework.http.MediaType
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.web.servlet.setup.MockMvcBuilders
Expand All @@ -23,7 +24,7 @@ import spock.lang.Subject

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*

@DataJpaTest
@ContextConfiguration(classes=[CoreShibUiConfiguration, SearchConfiguration, TestConfiguration, InternationalizationConfiguration])
Expand Down Expand Up @@ -64,6 +65,14 @@ class EntitiesControllerTests extends Specification {
result.andExpect(status().isNotFound())
}

def 'GET /entities/test'() {
when:
def result = mockMvc.perform(get("/entities/test"))

then:
result.andExpect(status().isNotFound())
}

def 'GET /api/entities/test XML'() {
when:
def result = mockMvc.perform(get("/api/entities/test").header('Accept', 'application/xml'))
Expand All @@ -72,7 +81,14 @@ class EntitiesControllerTests extends Specification {
result.andExpect(status().isNotFound())
}

//todo review
def 'GET /entities/test XML'() {
when:
def result = mockMvc.perform(get("/entities/test").header('Accept', 'application/xml'))

then:
result.andExpect(status().isNotFound())
}

def 'GET /api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'() {
given:
def expectedBody = '''
Expand Down Expand Up @@ -110,6 +126,49 @@ class EntitiesControllerTests extends Specification {
.andExpect(content().json(expectedBody, false))
}

def 'GET /entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'() {
given:
def expectedBody = '''
{
"id":null,
"serviceProviderName":null,
"entityId":"http://test.scaldingspoon.org/test1",
"organization": {},
"contacts":null,
"serviceProviderSsoDescriptor": {
"protocolSupportEnum":"SAML 2",
"nameIdFormats":["urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"]
},
"logoutEndpoints":null,
"securityInfo":null,
"assertionConsumerServices":[
{"locationUrl":"https://test.scaldingspoon.org/test1/acs","binding":"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST","makeDefault":false}
],
"serviceEnabled":false,
"createdDate":null,
"modifiedDate":null,
"attributeRelease":["givenName","employeeNumber"],
"version":-1891841119,
"createdBy":null,
"current":false
}
'''
when:
def result = mockMvc.perform(get('/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1'))

then:
// Response headers section 2.5
// from the spec https://www.ietf.org/archive/id/draft-young-md-query-14.txt
result.andExpect(status().isOk())
.andExpect(header().exists(HttpHeaders.CONTENT_TYPE)) // MUST HAVE
// .andExpect(header().exists(HttpHeaders.CONTENT_LENGTH)) // SHOULD HAVE - should end up from etag filter, so skipped for test
// .andExpect(header().exists(HttpHeaders.CACHE_CONTROL)) // SHOULD HAVE - should be included by Spring Security
// .andExpect(header().exists(HttpHeaders.LAST_MODIFIED)) // SHOULD HAVE - should end up from etag filter, so skipped for test
// .andExpect(header().exists(HttpHeaders.ETAG)) // MUST HAVE - is done by filter, so skipped for test
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(content().json(expectedBody, false))
}

def 'GET /api/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1 XML'() {
given:
def expectedBody = '''<?xml version="1.0" encoding="UTF-8"?>
Expand Down Expand Up @@ -139,4 +198,34 @@ class EntitiesControllerTests extends Specification {
.andExpect(content().contentType('application/xml;charset=ISO-8859-1'))
.andExpect(content().xml(expectedBody))
}

def 'GET /entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1 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 = mockMvc.perform(get('/entities/http%3A%2F%2Ftest.scaldingspoon.org%2Ftest1').header('Accept', 'application/xml'))

then:
result.andExpect(status().isOk())
.andExpect(content().contentType('application/xml;charset=ISO-8859-1'))
.andExpect(content().xml(expectedBody))
}
}

0 comments on commit 3cd2663

Please sign in to comment.