Skip to content

Commit

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

Approved-by: Shibui Jenkins <shibui.jenkins@gmail.com>
  • Loading branch information
dima767 authored and Jonathan Johnson committed Jun 11, 2018
2 parents c620f5e + c5a588a commit dbe6d58
Show file tree
Hide file tree
Showing 20 changed files with 964 additions and 116 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,29 @@
package edu.internet2.tier.shibboleth.admin.ui.service;

import com.google.common.base.Predicate;
import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter;
import com.google.common.base.Predicate
import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter
import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilterTarget
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects;
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver
import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository
import groovy.util.logging.Slf4j
import groovy.xml.DOMBuilder
import groovy.xml.MarkupBuilder;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.opensaml.saml.common.profile.logic.EntityIdPredicate;
import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver;
import org.opensaml.saml.metadata.resolver.MetadataResolver;
import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver;
import org.opensaml.saml.metadata.resolver.filter.MetadataFilter;
import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.metadata.EntityDescriptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;

public class JPAMetadataResolverServiceImpl implements MetadataResolverService {
private static final Logger logger = LoggerFactory.getLogger(JPAMetadataResolverServiceImpl.class);
import groovy.xml.MarkupBuilder
import net.shibboleth.utilities.java.support.resolver.ResolverException
import org.opensaml.saml.common.profile.logic.EntityIdPredicate
import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver
import org.opensaml.saml.metadata.resolver.MetadataResolver
import org.opensaml.saml.metadata.resolver.RefreshableMetadataResolver
import org.opensaml.saml.metadata.resolver.filter.MetadataFilter
import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain
import org.opensaml.saml.saml2.core.Attribute
import org.opensaml.saml.saml2.metadata.EntityDescriptor

import org.springframework.beans.factory.annotation.Autowired
import org.w3c.dom.Document

@Slf4j
class JPAMetadataResolverServiceImpl implements MetadataResolverService {

@Autowired
private MetadataResolver metadataResolver
Expand All @@ -35,68 +36,61 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService {

// TODO: enhance
@Override
public void reloadFilters(String metadataResolverName) {
ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver)metadataResolver;

// MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().stream().filter(r -> r.getId().equals(metadataResolverName)).findFirst().get();
void reloadFilters(String metadataResolverName) {
ChainingMetadataResolver chainingMetadataResolver = (ChainingMetadataResolver)metadataResolver
MetadataResolver targetMetadataResolver = chainingMetadataResolver.getResolvers().find { it.id == metadataResolverName }
edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName);
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver jpaMetadataResolver = metadataResolverRepository.findByName(metadataResolverName)

if (targetMetadataResolver && targetMetadataResolver.getMetadataFilter() instanceof MetadataFilterChain) {
MetadataFilterChain metadataFilterChain = (MetadataFilterChain)targetMetadataResolver.getMetadataFilter();
MetadataFilterChain metadataFilterChain = (MetadataFilterChain)targetMetadataResolver.getMetadataFilter()

List<MetadataFilter> metadataFilters = new ArrayList<>();
List<MetadataFilter> metadataFilters = new ArrayList<>()

for (edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter metadataFilter : jpaMetadataResolver.getMetadataFilters()) {
if (metadataFilter instanceof EntityAttributesFilter) {
EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) metadataFilter;
EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) metadataFilter

org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter target = new org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter();
Map<Predicate<EntityDescriptor>, Collection<Attribute>> rules = new HashMap<>();
org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter target = new org.opensaml.saml.metadata.resolver.filter.impl.EntityAttributesFilter()
Map<Predicate<EntityDescriptor>, Collection<Attribute>> rules = new HashMap<>()
if (entityAttributesFilter.getEntityAttributesFilterTarget().getEntityAttributesFilterTargetType() == EntityAttributesFilterTarget.EntityAttributesFilterTargetType.ENTITY) {
rules.put(
new EntityIdPredicate(entityAttributesFilter.getEntityAttributesFilterTarget().getValue()),
(List<Attribute>)(List<? extends Attribute>)entityAttributesFilter.getAttributes()
);
)
}
target.setRules(rules);
metadataFilters.add(target);
target.setRules(rules)
metadataFilters.add(target)
}
}
metadataFilterChain.setFilters(metadataFilters);
metadataFilterChain.setFilters(metadataFilters)
}

if (metadataResolver instanceof RefreshableMetadataResolver) {
try {
((RefreshableMetadataResolver)metadataResolver).refresh();
((RefreshableMetadataResolver)metadataResolver).refresh()
} catch (ResolverException e) {
logger.warn("error refreshing metadataResolver " + metadataResolverName, e);
log.warn("error refreshing metadataResolver " + metadataResolverName, e)
}
}
}

// TODO: enhance
@Override
public Document generateConfiguration() {
Document generateConfiguration() {
// TODO: this can probably be a better writer
new StringWriter().withCloseable { writer ->
def xml = new MarkupBuilder(writer)
xml.omitEmptyAttributes = true
xml.omitNullAttributes = true

xml.MetadataProvider(id: 'ShibbolethMetadata',
xmlns: 'urn:mace:shibboleth:2.0:metadata',
'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'
) {
metadataResolverRepository.findAll().each { edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver mr ->
MetadataProvider(id: 'HTTPMetadata',
'xsi:type': 'FileBackedHTTPMetadataProvider',
backingFile: '%{idp.home}/metadata/incommonmd.xml',
metadataURL: 'http://md.incommon.org/InCommon/InCommon-metadata.xml',
minRefreshDelay: 'PT5M',
maxRefreshDelay: 'PT1H',
refreshDelayFactor: '0.75'
) {
metadataResolverRepository.findAll().each { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr ->
constructXmlNodeForResolver(mr, delegate) {
MetadataFilter(
'xsi:type': 'SignatureValidation',
'requireSignedRoot': 'true',
Expand All @@ -114,7 +108,7 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService {
//TODO: enhance
mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter filter ->
if (filter instanceof EntityAttributesFilter) {
EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter)filter
EntityAttributesFilter entityAttributesFilter = (EntityAttributesFilter) filter
MetadataFilter('xsi:type': 'EntityAttributes') {
// TODO: enhance. currently this does weird things with namespaces
entityAttributesFilter.attributes.each { attribute ->
Expand All @@ -131,8 +125,49 @@ public class JPAMetadataResolverServiceImpl implements MetadataResolverService {
}
}
}

return DOMBuilder.newInstance().parseText(writer.toString())
}
}

void constructXmlNodeForResolver(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) {
markupBuilderDelegate.MetadataProvider(id: resolver.name,
'xsi:type': 'FileBackedHTTPMetadataProvider',
backingFile: resolver.backingFile,
metadataURL: resolver.metadataURL,
initializeFromBackupFile: !resolver.initializeFromBackupFile ?: null,
backupFileInitNextRefreshDelay: resolver.backupFileInitNextRefreshDelay,
requireValidMetadata: !resolver.requireValidMetadata ?: null,
failFastInitialization: !resolver.failFastInitialization ?: null,
sortKey: resolver.sortKey,
criterionPredicateRegistryRef: resolver.criterionPredicateRegistryRef,
useDefaultPredicateRegistry: !resolver.useDefaultPredicateRegistry ?: null,
satisfyAnyPredicates: resolver.satisfyAnyPredicates ?: null,

parserPoolRef: resolver.reloadableMetadataResolverAttributes?.parserPoolRef,
minRefreshDelay: resolver.reloadableMetadataResolverAttributes?.minRefreshDelay,
maxRefreshDelay: resolver.reloadableMetadataResolverAttributes?.maxRefreshDelay,
refreshDelayFactor: resolver.reloadableMetadataResolverAttributes?.refreshDelayFactor,
indexesRef: resolver.reloadableMetadataResolverAttributes?.indexesRef,
resolveViaPredicatesOnly: resolver.reloadableMetadataResolverAttributes?.resolveViaPredicatesOnly ?: null,
expirationWarningThreshold: resolver.reloadableMetadataResolverAttributes?.expirationWarningThreshold,

httpClientRef: resolver.httpMetadataResolverAttributes?.httpClientRef,
connectionRequestTimeout: resolver.httpMetadataResolverAttributes?.connectionRequestTimeout,
connectionTimeout: resolver.httpMetadataResolverAttributes?.connectionTimeout,
socketTimeout: resolver.httpMetadataResolverAttributes?.socketTimeout,
disregardTLSCertificate: resolver.httpMetadataResolverAttributes?.disregardTLSCertificate ?: null,
httpClientSecurityParametersRef: resolver.httpMetadataResolverAttributes?.httpClientSecurityParametersRef,
proxyHost: resolver.httpMetadataResolverAttributes?.proxyHost,
proxyPort: resolver.httpMetadataResolverAttributes?.proxyHost,
proxyUser: resolver.httpMetadataResolverAttributes?.proxyUser,
proxyPassword: resolver.httpMetadataResolverAttributes?.proxyPassword,
httpCaching: resolver.httpMetadataResolverAttributes?.httpCaching,
httpCacheDirectory: resolver.httpMetadataResolverAttributes?.httpCacheDirectory,
httpMaxCacheEntries: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntries,
httpMaxCacheEntrySize: resolver.httpMetadataResolverAttributes?.httpMaxCacheEntrySize) {

childNodes()
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ protected void processConditionalRetrievalHeaders(HttpResponse response) {
resolvers.add(incommonMR);

if (!metadataResolverRepository.findAll().iterator().hasNext()) {
edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver();
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver();
mr.setName("incommonmd");
metadataResolverRepository.save(mr);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package edu.internet2.tier.shibboleth.admin.ui.controller;

import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver;
import edu.internet2.tier.shibboleth.admin.ui.repository.FileBackedHttpMetadataResolverRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

import java.net.URI;

/**
* @author Bill Smith (wsmith@unicon.net)
*/
@RestController
@RequestMapping("/api/MetadataProvider/FileBackedHttp")
public class FileBackedHttpMetadataProviderController {
private static final Logger logger = LoggerFactory.getLogger(FileBackedHttpMetadataProviderController.class);

@Autowired
FileBackedHttpMetadataResolverRepository repository;

@DeleteMapping("/{resourceId}")
public ResponseEntity<?> deleteByResourceId(@PathVariable String resourceId) {
if (repository.deleteByResourceId(resourceId)) {
return ResponseEntity.accepted().build();
} else {
return ResponseEntity.notFound().build();
}
}

@GetMapping("/name/{metadataProviderName}")
@Transactional(readOnly = true)
public ResponseEntity<?> getOneByName(@PathVariable String metadataProviderName) {
FileBackedHttpMetadataResolver resolver = repository.findByName(metadataProviderName);
if (resolver == null) {
return ResponseEntity.notFound().build();
} else {
resolver.setVersion(resolver.hashCode());
return ResponseEntity.ok(resolver);
}
}

@GetMapping("/{resourceId}")
@Transactional(readOnly = true)
public ResponseEntity<?> getOneByResourceId(@PathVariable String resourceId) {
FileBackedHttpMetadataResolver resolver = repository.findByResourceId(resourceId);
if (resolver == null) {
return ResponseEntity.notFound().build();
} else {
resolver.setVersion(resolver.hashCode());
return ResponseEntity.ok(resolver);
}
}

@PostMapping
public ResponseEntity<?> create(@RequestBody FileBackedHttpMetadataResolver resolver) {
if (repository.findByName(resolver.getName()) != null) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}

FileBackedHttpMetadataResolver persistedResolver = repository.save(resolver);
persistedResolver.setVersion(persistedResolver.hashCode());

return ResponseEntity
.created(getResourceUriFor(persistedResolver))
.body(persistedResolver);
}

@PutMapping
public ResponseEntity<?> update(@RequestBody FileBackedHttpMetadataResolver resolver) {
FileBackedHttpMetadataResolver existingResolver = repository.findByResourceId(resolver.getResourceId());

if (existingResolver == null) {
return ResponseEntity.notFound().build();
}

if (existingResolver.hashCode() != resolver.getVersion()) {
logger.info("Comparing: " + existingResolver.hashCode() + " with " + resolver.getVersion());
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}

resolver.setAudId(existingResolver.getAudId());
//TODO: Do we need to set anything else? dates?

FileBackedHttpMetadataResolver updatedResolver = repository.save(resolver);
updatedResolver.setVersion(updatedResolver.hashCode());

return ResponseEntity.ok(updatedResolver);
}

private static URI getResourceUriFor(FileBackedHttpMetadataResolver resolver) {
return ServletUriComponentsBuilder
.fromCurrentServletMapping().path("/api/MetadataProvider/FileBackedHttp/")
.pathSegment(resolver.getResourceId())
.build()
.toUri();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import edu.internet2.tier.shibboleth.admin.ui.domain.EntityAttributesFilter;
import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataFilter;
import edu.internet2.tier.shibboleth.admin.ui.domain.MetadataResolver;
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver;
import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation;
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository;
import edu.internet2.tier.shibboleth.admin.ui.service.FilterService;
Expand Down

This file was deleted.

Loading

0 comments on commit dbe6d58

Please sign in to comment.