Skip to content

Commit

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

Approved-by: Shibui Jenkins <shibui.jenkins@gmail.com>
  • Loading branch information
Bill Smith authored and Jonathan Johnson committed Aug 23, 2018
2 parents 7885efc + a9d46cd commit 1d685ab
Show file tree
Hide file tree
Showing 23 changed files with 639 additions and 98 deletions.
2 changes: 1 addition & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ dependencies {
testCompile "org.xmlunit:xmlunit-core:2.5.1"
testRuntime 'cglib:cglib-nodep:3.2.5'

testCompile "net.shibboleth.ext:spring-extensions:5.4.0-SNAPSHOT"
compile "net.shibboleth.ext:spring-extensions:5.4.0-SNAPSHOT"

//JSON schema generator
testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.29'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,17 @@
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.service.IndexWriterService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.HttpClients;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
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.FileBackedHTTPMetadataResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -44,70 +34,24 @@ public class MetadataResolverConfiguration {
@Autowired
MetadataResolverRepository metadataResolverRepository;

@Autowired
MetadataResolverConverterService metadataResolverConverterService;

@Bean
public MetadataResolver metadataResolver() throws ResolverException, ComponentInitializationException {
ChainingMetadataResolver metadataResolver = new ChainingMetadataResolver();
metadataResolver.setId("chain");

List<MetadataResolver> resolvers = new ArrayList<>();

String incommonMRId = "incommonmd";
// TODO: remove this later when we allow for creation of arbitrary metadata resolvers
FileBackedHTTPMetadataResolver incommonMR = new FileBackedHTTPMetadataResolver(HttpClients.createMinimal(), "http://md.incommon.org/InCommon/InCommon-metadata.xml", "/tmp/incommonmd.xml"){
@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

IndexWriter indexWriter;
try {
indexWriter = indexWriterService.getIndexWriter(incommonMRId);
} catch (IOException e) {
throw new ComponentInitializationException(e);
}

for (String entityId: this.getBackingStore().getIndexedDescriptors().keySet()) {

Document document = new Document();
document.add(new StringField("id", entityId, Field.Store.YES));
document.add(new TextField("content", entityId, Field.Store.YES)); // TODO: change entityId to be content of entity descriptor block
try {
indexWriter.addDocument(document);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
try {
indexWriter.commit();
} catch (IOException e) {
throw new ComponentInitializationException(e);
}
}

// TODO: this is probably not the best way to do this
@Nullable
@Override
public DateTime getLastRefresh() {
return null;
}

// TODO: this is probably not the best way to do this
@Override
protected void processConditionalRetrievalHeaders(HttpResponse response) {
// let's do nothing 'cause we want to allow a refresh
Iterable<edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver> persistedResolvers = metadataResolverRepository.findAll();
for (edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver resolver : persistedResolvers) {
try {
MetadataResolver openSamlResolver = metadataResolverConverterService.convertToOpenSamlRepresentation(resolver);
resolvers.add(openSamlResolver);
} catch (IOException e) {
//TODO: do something interesting here?
}
};
incommonMR.setId(incommonMRId);
incommonMR.setParserPool(openSamlObjects.getParserPool());
incommonMR.setMetadataFilter(new MetadataFilterChain());
incommonMR.initialize();


resolvers.add(incommonMR);

if (!metadataResolverRepository.findAll().iterator().hasNext()) {
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);
}

metadataResolver.setResolvers(resolvers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@
import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidationService;
import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository;
import edu.internet2.tier.shibboleth.admin.ui.service.IndexWriterService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService;
import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService;
import lombok.extern.slf4j.Slf4j;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.IndexWriter;
import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
Expand All @@ -37,6 +40,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidator.ValidationResult;
Expand All @@ -61,6 +65,12 @@ public class MetadataResolversController {
@Autowired
IndexWriterService indexWriterService;

@Autowired
org.opensaml.saml.metadata.resolver.MetadataResolver chainingMetadataResolver;

@Autowired
MetadataResolverConverterService metadataResolverConverterService;

@ExceptionHandler({InvalidTypeIdException.class, IOException.class, HttpMessageNotReadableException.class})
public ResponseEntity<?> unableToParseJson(Exception ex) {
return ResponseEntity.badRequest().body(new ErrorResponse(HttpStatus.BAD_REQUEST.toString(), ex.getMessage()));
Expand Down Expand Up @@ -99,7 +109,7 @@ public ResponseEntity<?> getOne(@PathVariable String resourceId) {

@PostMapping("/MetadataResolvers")
@Transactional
public ResponseEntity<?> create(@RequestBody MetadataResolver newResolver) {
public ResponseEntity<?> create(@RequestBody MetadataResolver newResolver) throws IOException, ResolverException {
if (resolverRepository.findByName(newResolver.getName()) != null) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
Expand All @@ -112,12 +122,26 @@ public ResponseEntity<?> create(@RequestBody MetadataResolver newResolver) {
MetadataResolver persistedResolver = resolverRepository.save(newResolver);
positionOrderContainerService.appendPositionOrderForNew(persistedResolver);

updateChainingMetadataResolver(persistedResolver);

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

private void updateChainingMetadataResolver(MetadataResolver persistedResolver) throws IOException, ResolverException {
org.opensaml.saml.metadata.resolver.MetadataResolver openSamlResolver = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver);
List<org.opensaml.saml.metadata.resolver.MetadataResolver> resolverList = new ArrayList<>(((ChainingMetadataResolver) chainingMetadataResolver).getResolvers());
for (org.opensaml.saml.metadata.resolver.MetadataResolver resolver : resolverList) {
if (resolver.getId().equals(persistedResolver.getResourceId())) {
resolverList.remove(resolver);
}
}
resolverList.add(openSamlResolver);
((ChainingMetadataResolver) chainingMetadataResolver).setResolvers(resolverList);
}

@PutMapping("/MetadataResolvers/{resourceId}")
@Transactional
public ResponseEntity<?> update(@PathVariable String resourceId, @RequestBody MetadataResolver updatedResolver) {
public ResponseEntity<?> update(@PathVariable String resourceId, @RequestBody MetadataResolver updatedResolver) throws IOException, ResolverException {
MetadataResolver existingResolver = resolverRepository.findByResourceId(resourceId);
if (existingResolver == null) {
return ResponseEntity.notFound().build();
Expand All @@ -137,6 +161,8 @@ public ResponseEntity<?> update(@PathVariable String resourceId, @RequestBody Me

MetadataResolver persistedResolver = resolverRepository.save(updatedResolver);

updateChainingMetadataResolver(persistedResolver);

return ResponseEntity.ok(persistedResolver);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
@Setter
@ToString
public class DynamicHttpMetadataResolver extends MetadataResolver {



public static final String DEFAULT_TIMEOUT = "PT5S";

@Embedded
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

Expand All @@ -15,7 +14,6 @@
@Setter
@ToString
public class FileBackedHttpMetadataResolver extends MetadataResolver {

public FileBackedHttpMetadataResolver() {
type = "FileBackedHttpMetadataResolver";
}
Expand All @@ -34,5 +32,4 @@ public FileBackedHttpMetadataResolver() {

@Embedded
private HttpMetadataResolverAttributes httpMetadataResolverAttributes;

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@Setter
@ToString
public class FilesystemMetadataResolver extends MetadataResolver {

public FilesystemMetadataResolver() {
type = "FilesystemMetadataResolver";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
@Setter
@ToString
public class LocalDynamicMetadataResolver extends MetadataResolver {

public LocalDynamicMetadataResolver() {
type = "LocalDynamicMetadataResolver";
}
Expand All @@ -27,5 +26,4 @@ public LocalDynamicMetadataResolver() {

@Embedded
private DynamicMetadataResolverAttributes dynamicMetadataResolverAttributes;

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
@Setter
@ToString
public class ResourceBackedMetadataResolver extends MetadataResolver {

public ResourceBackedMetadataResolver() {
type = "ResourceBackedMetadataResolver";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml;

import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver;
import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.apache.http.HttpResponse;
import org.apache.http.impl.client.HttpClients;
import org.apache.lucene.index.IndexWriter;
import org.joda.time.DateTime;
import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver;

import javax.annotation.Nullable;

import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis;

/**
* @author Bill Smith (wsmith@unicon.net)
*/
public class OpenSamlFileBackedHTTPMetadataResolver extends FileBackedHTTPMetadataResolver {
private IndexWriter indexWriter;
private FileBackedHttpMetadataResolver sourceResolver;

private OpenSamlMetadataResolverDelegate delegate;

public OpenSamlFileBackedHTTPMetadataResolver(IndexWriter indexWriter,
FileBackedHttpMetadataResolver sourceResolver) throws ResolverException {
super(HttpClients.createMinimal(), sourceResolver.getMetadataURL(), sourceResolver.getBackingFile());
this.indexWriter = indexWriter;
this.sourceResolver = sourceResolver;
this.delegate = new OpenSamlMetadataResolverDelegate();

this.setId(sourceResolver.getResourceId());

OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromHttpMetadataResolverAttributes(
this, sourceResolver.getHttpMetadataResolverAttributes());
OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes(
this, sourceResolver.getReloadableMetadataResolverAttributes());

this.setBackupFile(sourceResolver.getBackingFile());
this.setBackupFileInitNextRefreshDelay(toMillis(sourceResolver.getBackupFileInitNextRefreshDelay()));
this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile());

//TODO: Where does this get set in OpenSAML land?
// sourceResolver.getMetadataURL();
}

// TODO: this is still probably not the best way to do this?
@Nullable
@Override
public DateTime getLastRefresh() {
return null;
}

// TODO: this is still probably not the best way to do this?
@Override
protected void processConditionalRetrievalHeaders(HttpResponse response) {
// let's do nothing 'cause we want to allow a refresh
}

@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

delegate.addIndexedDescriptorsFromBackingStore(this.getBackingStore(),
this.sourceResolver.getResourceId(),
indexWriter);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml;

import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.resolver.ResolverException;
import org.apache.lucene.index.IndexWriter;
import org.joda.time.DateTime;
import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver;

import javax.annotation.Nullable;
import java.io.File;

/**
* @author Bill Smith (wsmith@unicon.net)
*/
public class OpenSamlFilesystemMetadataResolver extends FilesystemMetadataResolver {
private IndexWriter indexWriter;
private edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver sourceResolver;
private OpenSamlMetadataResolverDelegate delegate;

public OpenSamlFilesystemMetadataResolver(File metadataFile,
IndexWriter indexWriter,
edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver sourceResolver) throws ResolverException {
super(metadataFile);
this.indexWriter = indexWriter;
this.sourceResolver = sourceResolver;
this.delegate = new OpenSamlMetadataResolverDelegate();

this.setId(sourceResolver.getResourceId());

OpenSamlMetadataResolverConstructorHelper.updateOpenSamlMetadataResolverFromReloadableMetadataResolverAttributes(
this, sourceResolver.getReloadableMetadataResolverAttributes());
}

// TODO: this is still probably not the best way to do this?
@Nullable
@Override
public DateTime getLastRefresh() {
return null;
}

@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

delegate.addIndexedDescriptorsFromBackingStore(this.getBackingStore(),
this.sourceResolver.getResourceId(),
indexWriter);
}
}
Loading

0 comments on commit 1d685ab

Please sign in to comment.