Skip to content

Commit

Permalink
Merged in feature/SHIBUI-701 (pull request #232)
Browse files Browse the repository at this point in the history
SHIBUI-701 Implemented FilesystemMetadataResolver type

Approved-by: Ryan Mathis <rmathis@unicon.net>
  • Loading branch information
rmathis authored and Jonathan Johnson committed Nov 13, 2018
2 parents f4a6d3c + 8017969 commit 9b51a67
Show file tree
Hide file tree
Showing 31 changed files with 753 additions and 93 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package edu.internet2.tier.shibboleth.admin.ui.controller

import com.fasterxml.jackson.databind.ObjectMapper
import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation
import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.filesystemMetadataProviderSchema
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.localDynamicMetadataProviderSchema
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.dynamicHttpMetadataProviderSchema
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType

/**
* Controller implementing REST resource responsible for exposing structure definition for metadata resolvers user
* interface in terms of JSON schema.
*
* @author Dmitriy Kopylenko
* @author Bill Smith (wsmith@unicon.net)
*/
@RestController
@RequestMapping('/api/ui/MetadataResolver')
class MetadataResolverUiDefinitionController {

@Autowired
JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry

JsonSchemaResourceLocation jsonSchemaLocation

@Autowired
ObjectMapper jacksonObjectMapper

@GetMapping(value = "/{resolverType}")
ResponseEntity<?> getUiDefinitionJsonSchema(@PathVariable String resolverType) {
switch (SchemaType.getSchemaType(resolverType)) {
case SchemaType.FILESYSTEM_METADATA_RESOLVER:
jsonSchemaLocation = filesystemMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break
/* case SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER:
jsonSchemaLocation = localDynamicMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break*/
/* case SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER:
jsonSchemaLocation = dynamicHttpMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry)
break*/
default:
throw new UnsupportedOperationException("Json schema for an unsupported metadata resolver (" + resolverType + ") was requested")
}
try {
def parsedJson = jacksonObjectMapper.readValue(this.jsonSchemaLocation.url, Map)
return ResponseEntity.ok(parsedJson)
}
catch (Exception e) {
e.printStackTrace()
return ResponseEntity.status(INTERNAL_SERVER_ERROR)
.body([jsonParseError : e.getMessage(),
sourceUiSchemaDefinitionFile: this.jsonSchemaLocation.url])
}
}

@GetMapping(value = "/types")
ResponseEntity<?> getResolverTypes() {
return ResponseEntity.ok(SchemaType.getResolverTypes())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.*;
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS;
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES;
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER;
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER;
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER;

/**
* @author Dmitriy Kopylenko
Expand All @@ -30,6 +33,21 @@ public class JsonSchemaComponentsConfiguration {
@Setter
private String entityAttributesFiltersUiSchemaLocation = "classpath:entity-attributes-filters-ui-schema.json";

//Configured via @ConfigurationProperties (using setter method) with 'shibui.filesystem-metadata-provider-ui-schema-location' property and
// default value set here if that property is not explicitly set in application.properties
@Setter
private String filesystemMetadataResolverUiSchemaLocation = "classpath:file-system-metadata-provider.schema.json";

/* TODO: Will be added as part of SHIBUI-703
@Setter
private String localDynamicMetadataResolverUiSchemaLocation = "classpath:local-dynamic-metadata-provider.schema.json";
*/

/* TODO: Will be added as part of SHIBUI-704
@Setter
private String dynamicHttpMetadataResolverUiSchemaLocation = "classpath:dynamic-http-metadata-provider.schema.json";
*/

@Bean
public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) {
return JsonSchemaResourceLocationRegistry.inMemory()
Expand All @@ -44,7 +62,25 @@ public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(Res
.resourceLoader(resourceLoader)
.jacksonMapper(jacksonMapper)
.detectMalformedJson(true)
.build())
.register(FILESYSTEM_METADATA_RESOLVER, JsonSchemaLocationBuilder.with()
.jsonSchemaLocation(filesystemMetadataResolverUiSchemaLocation)
.resourceLoader(resourceLoader)
.jacksonMapper(jacksonMapper)
.detectMalformedJson(true)
.build());
/*.register(DYNAMIC_HTTP_METADATA_RESOLVER, JsonSchemaLocationBuilder.with()
.jsonSchemaLocation(dynamicHttpMetadataResolverUiSchemaLocation)
.resourceLoader(resourceLoader)
.jacksonMapper(jacksonMapper)
.detectMalformedJson(true)
.build())
.register(LOCAL_DYNAMIC_METADATA_RESOLVER, JsonSchemaLocationBuilder.with()
.jsonSchemaLocation(localDynamicMetadataResolverUiSchemaLocation)
.resourceLoader(resourceLoader)
.jacksonMapper(jacksonMapper)
.detectMalformedJson(true)
.build());*/

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URI;
Expand Down Expand Up @@ -120,8 +121,10 @@ public ResponseEntity<?> create(@RequestBody MetadataResolver newResolver) throw

//TODO: currently, the update call might explode, but the save works.. in which case, the UI never gets
// n valid response. This operation is not atomic. Should we return an error here?
org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver);
OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation);
if (persistedResolver.getDoInitialization()) {
org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver);
OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation);
}

return ResponseEntity.created(getResourceUriFor(persistedResolver)).body(persistedResolver);
}
Expand All @@ -148,8 +151,16 @@ public ResponseEntity<?> update(@PathVariable String resourceId, @RequestBody Me

MetadataResolver persistedResolver = resolverRepository.save(updatedResolver);

org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver);
OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation);
if (persistedResolver.getDoInitialization()) {
org.opensaml.saml.metadata.resolver.MetadataResolver openSamlRepresentation = null;
try {
openSamlRepresentation = metadataResolverConverterService.convertToOpenSamlRepresentation(persistedResolver);
} catch (FileNotFoundException e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ErrorResponse(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "label.file-doesnt-exist"));
}
OpenSamlChainingMetadataResolverUtil.updateChainingMetadataResolver((OpenSamlChainingMetadataResolver) chainingMetadataResolver, openSamlRepresentation);
}

return ResponseEntity.ok(persistedResolver);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
public class FilesystemMetadataResolver extends MetadataResolver {
public FilesystemMetadataResolver() {
type = "FilesystemMetadataResolver";
this.setDoInitialization(false);
}

private String metadataFile;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ public class MetadataResolver extends AbstractAuditable {

private Boolean satisfyAnyPredicates = false;

private Boolean doInitialization = true;

@OneToMany(cascade = CascadeType.ALL)
@OrderColumn
private List<MetadataFilter> metadataFilters = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ public DateTime getLastRefresh() {

@Override
protected void initMetadataResolver() throws ComponentInitializationException {
super.initMetadataResolver();
if (this.sourceResolver.getDoInitialization()) {
super.initMetadataResolver();

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

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS;
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES;
import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER;
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER;
//import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER;

/**
* Utility methods for common JSON schema types lookups.
Expand All @@ -27,12 +30,37 @@ public static JsonSchemaResourceLocation metadataSourcesSchema(JsonSchemaResourc
* Searches entity attributes filters JSON schema resource location object in the given location registry.
*
* @param resourceLocationRegistry
* @returnentity attributes filters JSON schema resource location object
* @return entity attributes filters JSON schema resource location object
* @throws IllegalStateException if schema is not found in the given registry
*/
public static JsonSchemaResourceLocation entityAttributesFiltersSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) {
return resourceLocationRegistry
.lookup(ENTITY_ATTRIBUTES_FILTERS)
.orElseThrow(() -> new IllegalStateException("JSON schema resource location for entity attributes filters is not registered."));
}

/**
* Searches filesystem metadata resolver JSON schema resource location object in the given location registry.
*
* @param resourceLocationRegistry
* @return filesystem metadata resolver JSON schema resource location object
* @throws IllegalStateException if schema is not found in the given registry
*/
public static JsonSchemaResourceLocation filesystemMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) {
return resourceLocationRegistry
.lookup(FILESYSTEM_METADATA_RESOLVER)
.orElseThrow(() -> new IllegalStateException("JSON schema resource location for filesystem metadata resolver is not registered."));
}

/* public static JsonSchemaResourceLocation localDynamicMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) {
return resourceLocationRegistry
.lookup(LOCAL_DYNAMIC_METADATA_RESOLVER)
.orElseThrow(() -> new IllegalStateException("JSON schema resource location for local dynamic metadata resolver is not registered."));
}*/

/* public static JsonSchemaResourceLocation dynamicHttpMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) {
return resourceLocationRegistry
.lookup(DYNAMIC_HTTP_METADATA_RESOLVER)
.orElseThrow(() -> new IllegalStateException("JSON schema resource location for dynamic http metadata resolver is not registered."));
}*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* Encapsulates arbitrary JSON schema location.
Expand Down Expand Up @@ -91,6 +94,41 @@ public static JsonSchemaResourceLocation newSchemaLocation(String jsonSchemaLoca
}

public enum SchemaType {
METADATA_SOURCES, ENTITY_ATTRIBUTES_FILTERS
// common types
METADATA_SOURCES("MetadataSources"),

// filter types
ENTITY_ATTRIBUTES_FILTERS("EntityAttributesFilters"),

// resolver types
FILE_BACKED_HTTP_METADATA_RESOLVER("FileBackedHttpMetadataResolver"),
FILESYSTEM_METADATA_RESOLVER("FilesystemMetadataResolver");
// LOCAL_DYNAMIC_METADATA_RESOLVER,
// DYNAMIC_HTTP_METADATA_RESOLVER;

String jsonType;

SchemaType(String jsonType) {
this.jsonType = jsonType;
}

String getJsonType() {
return jsonType;
}

public static List<String> getResolverTypes() {
return Stream.of(SchemaType.values()).map(SchemaType::getJsonType).filter(it -> it.endsWith("Resolver")).collect(Collectors.toList());
}

public static SchemaType getSchemaType(String jsonType) {
List<SchemaType> schemaTypes = Stream.of(SchemaType.values()).filter(it -> it.getJsonType().equals(jsonType)).collect(Collectors.toList());
if (schemaTypes.size() > 1) {
throw new RuntimeException("Found multiple schema types for jsonType (" + jsonType + ")!");
} else if (schemaTypes.size() == 0) {
throw new RuntimeException("Found no schema types for jsonType (" + jsonType + ")! Verify that the code supports all schema types.");
} else {
return schemaTypes.get(0);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import javax.validation.ConstraintViolationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;

Expand Down Expand Up @@ -61,9 +62,10 @@ private OpenSamlFileBackedHTTPMetadataResolver convertToOpenSamlRepresentation(F

private OpenSamlFilesystemMetadataResolver convertToOpenSamlRepresentation(FilesystemMetadataResolver resolver) throws IOException, ResolverException, ComponentInitializationException {
IndexWriter indexWriter = indexWriterService.getIndexWriter(resolver.getResourceId());
URL url = Thread.currentThread().getContextClassLoader().getResource(placeholderResolverService()
.resolveValueFromPossibleTokenPlaceholder(resolver.getMetadataFile()));
File metadataFile = new File(url.getPath());
File metadataFile = new File(resolver.getMetadataFile());
if (resolver.getDoInitialization() && !metadataFile.exists()) {
throw new FileNotFoundException("No file was found on the fileysystem for provided filename: " + resolver.getMetadataFile());
}

OpenSamlFilesystemMetadataResolver openSamlResolver = new OpenSamlFilesystemMetadataResolver(openSamlObjects.getParserPool(),
indexWriter,
Expand Down
Loading

0 comments on commit 9b51a67

Please sign in to comment.