Skip to content

Commit

Permalink
[SHIBUI-723]
Browse files Browse the repository at this point in the history
Added support for conversion of ShibUI resolvers to OpenSaml resolvers.
Added resolver to chaining bean on post/put.
Added resolvers to chaining bean on bean creation.

Still need to handle creating OpenSaml resolvers properly (populating
all the relevant fields). Also, address new TODOs.
  • Loading branch information
Bill Smith committed Aug 8, 2018
1 parent 938f239 commit 01a5a72
Show file tree
Hide file tree
Showing 14 changed files with 512 additions and 291 deletions.
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,13 +5,16 @@
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 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 @@ -36,6 +39,7 @@
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
import java.util.List;

import static edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolverValidator.ValidationResult;

Expand All @@ -56,6 +60,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 @@ -96,7 +106,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 @@ -110,13 +120,26 @@ public ResponseEntity<?> create(@RequestBody MetadataResolver newResolver) {
MetadataResolver persistedResolver = resolverRepository.save(newResolver);
persistedResolver.updateVersion();

updateChainingMetadataResolver(persistedResolver);

persistedResolver.convertFiltersIntoTransientRepresentationIfNecessary();
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 = ((ChainingMetadataResolver) chainingMetadataResolver).getResolvers();
for (org.opensaml.saml.metadata.resolver.MetadataResolver resolver : resolverList) {
if (resolver.getId().equals(persistedResolver.getResourceId())) {
resolverList.remove(resolver);
}
}
resolverList.add(openSamlResolver);
}

@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 @@ -140,6 +163,8 @@ public ResponseEntity<?> update(@PathVariable String resourceId, @RequestBody Me
MetadataResolver persistedResolver = resolverRepository.save(updatedResolver);
persistedResolver.updateVersion();

updateChainingMetadataResolver(persistedResolver);

return ResponseEntity.ok(persistedResolver);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers;

import edu.internet2.tier.shibboleth.admin.ui.service.LuceneMetadataResolverService;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
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.DynamicMetadataResolver;
import org.opensaml.saml.metadata.resolver.impl.FunctionDrivenDynamicHTTPMetadataResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Nullable;
import javax.persistence.ElementCollection;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.OrderColumn;
import java.io.IOException;
import java.util.List;

/**
Expand All @@ -38,11 +20,6 @@
@Setter
@ToString
public class DynamicHttpMetadataResolver extends MetadataResolver {
private static final Logger logger = LoggerFactory.getLogger(DynamicHttpMetadataResolver.class);

@Autowired
LuceneMetadataResolverService luceneMetadataResolverService;

public static final String DEFAULT_TIMEOUT = "PT5S";

@Embedded
Expand All @@ -67,18 +44,4 @@ public DynamicHttpMetadataResolver() {
this.httpMetadataResolverAttributes.setSocketTimeout(DEFAULT_TIMEOUT);
this.dynamicMetadataResolverAttributes = new DynamicMetadataResolverAttributes();
}

public FunctionDrivenDynamicHTTPMetadataResolver createOpenSamlResolver(IndexWriter indexWriter) throws ResolverException {
final String resourceId = this.getResourceId();

FunctionDrivenDynamicHTTPMetadataResolver openSamlResolver = new FunctionDrivenDynamicHTTPMetadataResolver(HttpClients.createMinimal()) {
@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

luceneMetadataResolverService.addIndexedDescriptorsFromBackingStore(this.getBackingStore(), resourceId, indexWriter);
}
};
return openSamlResolver;
}
}
Original file line number Diff line number Diff line change
@@ -1,42 +1,19 @@
package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers;

import edu.internet2.tier.shibboleth.admin.ui.service.LuceneMetadataResolverService;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
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.impl.FileBackedHTTPMetadataResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.annotation.Nullable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import java.io.IOException;

@Entity
@EqualsAndHashCode(callSuper = true)
@Getter
@Setter
@ToString
public class FileBackedHttpMetadataResolver extends MetadataResolver {
private static final Logger logger = LoggerFactory.getLogger(FileBackedHttpMetadataResolver.class);

@Autowired
LuceneMetadataResolverService luceneMetadataResolverService;

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

@Embedded
private HttpMetadataResolverAttributes httpMetadataResolverAttributes;

public FileBackedHTTPMetadataResolver createOpenSamlResolver(IndexWriter indexWriter) throws ResolverException {
final String resourceId = this.getResourceId();

FileBackedHTTPMetadataResolver openSamlResolver = new FileBackedHTTPMetadataResolver(HttpClients.createMinimal(), this.metadataURL, this.backingFile) {
@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();

luceneMetadataResolverService.addIndexedDescriptorsFromBackingStore(this.getBackingStore(), resourceId, indexWriter);
}

// 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
}
};
return openSamlResolver;
}
}
Loading

0 comments on commit 01a5a72

Please sign in to comment.