diff --git a/backend/build.gradle b/backend/build.gradle index f41778d28..554674bbb 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -1,11 +1,11 @@ plugins { - id 'groovy' - id 'war' - id 'org.springframework.boot' version '2.4.2' - id 'com.gorylenko.gradle-git-properties' version '1.4.21' - id 'io.freefair.lombok' version '5.3.0' - id 'com.palantir.docker' version '0.28.0' - id 'com.palantir.docker-run' version '0.28.0' + id "groovy" + id "war" + id "org.springframework.boot" + id "io.freefair.lombok" + id "com.gorylenko.gradle-git-properties" version "1.4.21" + id "com.palantir.docker" version "0.28.0" + id "com.palantir.docker-run" version "0.28.0" } apply plugin: 'io.spring.dependency-management' @@ -14,18 +14,26 @@ apply plugin: 'jacoco' sourceCompatibility = 11 targetCompatibility = 11 +test { + useJUnitPlatform() // Needed by spock to find specification tests +} + repositories { jcenter() maven { url 'https://build.shibboleth.net/nexus/content/groups/public' artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] } + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } mavenLocal() + mavenCentral() } configurations.all { resolutionStrategy { - force 'org.cryptacular:cryptacular:1.1.3' + force "org.cryptacular:cryptacular:${project.'cryptacularVersion'}" eachDependency { details -> if (details.requested.group == 'org.seleniumhq.selenium' && details.requested.name != 'htmlunit-driver') { @@ -105,7 +113,7 @@ bootWar { } springBoot { - mainClassName = 'edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication' + mainClass = 'edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication' buildInfo() } @@ -114,24 +122,22 @@ generateLombokConfig.enabled = false dependencies { // opensaml deps ['opensaml-saml-api', 'opensaml-saml-impl', 'opensaml-xmlsec-api', 'opensaml-xmlsec-impl'].each { - compile "org.opensaml:${it}:${project.'opensaml.version'}" + compile "org.opensaml:${it}:${project.'opensamlVersion'}" } -// Left here to save time later - when pac4j is/was updated, I needed all of these to get the runtime right with the SAML2 client -// runtimeOnly "org.bouncycastle:bcprov-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcprov-ext-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcutil-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcpkix-jdk15on:1.69" - + runtimeOnly "org.bouncycastle:bcprov-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcprov-ext-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcutil-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcpkix-jdk15on:1.70" // shibboleth idp deps ['idp-profile-spring', 'idp-profile-api'].each { - compile "net.shibboleth.idp:${it}:${project.'shibboleth.version'}" + compile "net.shibboleth.idp:${it}:${project.'shibbolethVersion'}" } // hibernate deps ['hibernate-core'].each { - compile "org.hibernate:${it}:${project.'hibernate.version'}" + compile "org.hibernate:${it}:${project.'hibernateVersion'}" } // spring boot auto-config starters @@ -139,18 +145,18 @@ dependencies { compile "org.springframework.boot:spring-boot-${it}" } // To override older version with security issue - https://www.lunasec.io/docs/blog/log4j-zero-day/ - implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.15.0' - implementation 'org.apache.logging.log4j:log4j-api:2.15.0' + implementation "org.apache.logging.log4j:log4j-to-slf4j:${project.'log4JVersion'}" + implementation "org.apache.logging.log4j:log4j-api:${project.'log4JVersion'}" // TODO: figure out what this should really be - runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' + runtimeOnly "org.springframework.boot:spring-boot-starter-tomcat:${project.'springbootVersion'}" //Spring Configuration Annotation Processor - makes IntelliJ happy about @ConfigurationProperties - compileOnly "org.springframework.boot:spring-boot-configuration-processor" + compileOnly "org.springframework.boot:spring-boot-configuration-processor:${project.'springbootVersion'}" // lucene deps ['core', 'analyzers-common', 'queryparser'].each { - compile "org.apache.lucene:lucene-${it}:${project.'lucene.version'}" + compile "org.apache.lucene:lucene-${it}:${project.'luceneVersion'}" } compile "org.liquibase:liquibase-core" @@ -159,30 +165,32 @@ dependencies { //For easy data mocking capabilities compile 'net.andreinc.mockneat:mockneat:0.1.4' - compile 'org.codehaus.groovy:groovy-all:3.0.7' - //So it works on Java 9 without explicitly requiring to load that module (needed by Hibernate) runtimeOnly 'javax.xml.bind:jaxb-api:2.3.0' // runtime libraries for later java versions runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:2.3.0' compile "com.h2database:h2" - runtimeOnly "org.postgresql:postgresql:42.2.20" - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.2.0' - runtimeOnly 'mysql:mysql-connector-java:5.1.48' + runtimeOnly 'org.postgresql:postgresql:42.3.4' + runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:3.0.4' + runtimeOnly 'mysql:mysql-connector-java:8.0.29' //Swagger compile 'io.springfox:springfox-swagger2:2.9.2' compile 'io.springfox:springfox-swagger-ui:2.9.2' - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.springframework.security:spring-security-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" + + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + testCompile "org.springframework.security:spring-security-test:${project.'springSecurityVersion'}" + testCompile 'org.skyscreamer:jsonassert:1.5.0' testCompile "org.xmlunit:xmlunit-core:2.5.1" testRuntime 'cglib:cglib-nodep:3.2.5' - compile "net.shibboleth.ext:spring-extensions:5.4.0" + compile "net.shibboleth.ext:spring-extensions:6.2.0" //JSON schema generator testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.29' @@ -196,18 +204,18 @@ dependencies { integrationTestCompile configurations.compile integrationTestCompile 'com.saucelabs:sebuilder-interpreter:1.0.6' integrationTestCompile 'jp.vmi:selenese-runner-java:3.20.0' - integrationTestCompile "org.springframework.boot:spring-boot-starter-test" - integrationTestCompile "org.springframework.security:spring-security-test" - integrationTestCompile "org.spockframework:spock-core:1.3-groovy-2.5" - integrationTestCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + integrationTestCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + integrationTestCompile "org.springframework.security:spring-security-test:${project.'springSecurityVersion'}" // CSV file support - compile 'com.opencsv:opencsv:4.4' + compile 'com.opencsv:opencsv:4.4', { + exclude group: 'commons-collections' + } - testCompile 'org.skyscreamer:jsonassert:1.5.0' + compile "org.apache.commons:commons-collections4:${project.'commonsCollections4Version'}" // Envers for persistent entities versioning - compile 'org.hibernate:hibernate-envers' + compile "org.hibernate:hibernate-envers:${project.'hibernateVersion'}" //Pacj4 sub-project runtimeOnly project(':pac4j-module') @@ -219,7 +227,9 @@ dependencies { enversTestCompile sourceSets.test.output enversTestCompile configurations.compile enversTestCompile configurations.testCompile + enversTestCompile configurations.testImplementation + enversTestRuntime configurations.testImplementation enversTestRuntime configurations.runtime enversTestRuntime configurations.testRuntime } @@ -247,6 +257,7 @@ task enversTest(type: Test) { classpath = sourceSets.enversTest.runtimeClasspath systemProperties = System.properties systemProperties['user.dir'] = workingDir + useJUnitPlatform() } check { diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index 79420f6d0..ed3f794c0 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -32,7 +32,7 @@ import groovy.util.logging.Slf4j import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.utilities.java.support.scripting.EvaluableScript -import org.apache.commons.collections.CollectionUtils +import org.apache.commons.collections4.CollectionUtils import org.opensaml.saml.common.profile.logic.EntityIdPredicate import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilter diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java index 1c8a86907..43539d77d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.web.ResourceProperties; +import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; @@ -17,7 +17,7 @@ */ @Configuration -@EnableConfigurationProperties({ResourceProperties.class}) +@EnableConfigurationProperties({WebProperties.class}) public class StaticResourcesConfiguration implements WebMvcConfigurer { static final String[] STATIC_RESOURCES = new String[]{ "/**/*.css", @@ -36,16 +36,17 @@ public class StaticResourcesConfiguration implements WebMvcConfigurer { }; @Autowired - private ResourceProperties resourceProperties = new ResourceProperties(); + private WebProperties resourceProperties = new WebProperties(); @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler(STATIC_RESOURCES) - .addResourceLocations(resourceProperties.getStaticLocations()) + .addResourceLocations(resourceProperties.getResources().getStaticLocations()) .setCachePeriod(10); registry.addResourceHandler("/**") .addResourceLocations( - Arrays.stream(resourceProperties.getStaticLocations()) + Arrays.stream(resourceProperties.getResources().getStaticLocations()) .map(l -> l + "index.html") .toArray(String[]::new) ) @@ -59,4 +60,4 @@ protected Resource getResource(String resourcePath, Resource location) throws IO } ); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java index 6600307af..0b77412d5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java @@ -1,20 +1,8 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; - -import javax.persistence.Column; -import javax.persistence.EntityListeners; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; -import javax.validation.constraints.NotNull; - +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.EqualsAndHashCode; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.envers.Audited; @@ -24,11 +12,19 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; - -import lombok.EqualsAndHashCode; - +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; @MappedSuperclass @EntityListeners(AuditingEntityListener.class) @@ -42,13 +38,13 @@ public abstract class AbstractAuditable implements Auditable { @CreationTimestamp @CreatedDate - @Column(nullable = false, updatable = false, columnDefinition = "DATETIME(6)") + @Column(nullable = false, updatable = false) @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") private LocalDateTime createdDate; @UpdateTimestamp @LastModifiedDate - @Column(nullable = false, columnDefinition = "DATETIME(6)") + @Column(nullable = false) @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") private LocalDateTime modifiedDate; @@ -81,7 +77,7 @@ public LocalDateTime getCreatedDate() { @Override public void setCreatedDate(LocalDateTime createdDate) { - this.createdDate = createdDate; + this.createdDate = createdDate == null ? null : createdDate.truncatedTo(ChronoUnit.NANOS); } @Override @@ -91,7 +87,7 @@ public LocalDateTime getModifiedDate() { @Override public void setModifiedDate(LocalDateTime modifiedDate) { - this.modifiedDate = modifiedDate; + this.modifiedDate = modifiedDate == null ? null : modifiedDate.truncatedTo(ChronoUnit.NANOS); } public String getCreatedBy() { @@ -134,4 +130,4 @@ private static ZonedDateTime toZonedDateTime(LocalDateTime localDateTime) { .toZonedDateTime() .truncatedTo(ChronoUnit.MILLIS); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java index 449cda701..ee9747bd9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java @@ -7,16 +7,17 @@ import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.common.CacheableSAMLObject; import org.opensaml.saml.saml2.common.TimeBoundSAMLObject; -import org.opensaml.xmlsec.signature.Signature; import org.opensaml.xmlsec.signature.SignableXMLObject; +import org.opensaml.xmlsec.signature.Signature; import javax.annotation.Nullable; import javax.persistence.CascadeType; import javax.persistence.MappedSuperclass; import javax.persistence.OneToOne; +import java.time.Duration; +import java.time.Instant; import java.util.List; - @MappedSuperclass @EqualsAndHashCode(callSuper = true) @Audited @@ -42,23 +43,27 @@ public boolean isValid() { } @Override - public Long getCacheDuration() { - return cacheDuration; + public Duration getCacheDuration() { + return null == cacheDuration ? null : Duration.ofMillis(cacheDuration); } @Override - public void setCacheDuration(Long cacheDuration) { - this.cacheDuration = cacheDuration; + public void setCacheDuration(@Nullable final Duration duration) { + if (duration == null) { + cacheDuration = null; + } else { + cacheDuration = duration.toMillis(); + } } @Override - public DateTime getValidUntil() { - return validUntil; + public Instant getValidUntil() { + return null == validUntil ? null : Instant.ofEpochMilli(validUntil.getMillis()); } @Override - public void setValidUntil(DateTime validUntil) { - this.validUntil = validUntil; + public void setValidUntil(Instant validUntilInstant) { + this.validUntil = new DateTime(validUntilInstant.toEpochMilli()); } @Override @@ -102,4 +107,4 @@ public List getOrderedChildren() { return null; //TODO ? } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java index c5f33b7b1..396278587 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java @@ -2,24 +2,24 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) -public class AdditionalMetadataLocation extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AdditionalMetadataLocation { - - private String locationURI; +public class AdditionalMetadataLocation extends AbstractXMLObject + implements org.opensaml.saml.saml2.metadata.AdditionalMetadataLocation { + @Column(name = "locationuri", nullable = true) private String locationURI; private String namespaceURI; @Override - public String getLocationURI() { + public String getURI() { return locationURI; } @Override - public void setLocationURI(String locationURI) { + public void setURI(String locationURI) { this.locationURI = locationURI; } @@ -32,4 +32,4 @@ public String getNamespaceURI() { public void setNamespaceURI(String namespaceURI) { this.namespaceURI = namespaceURI; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java index e5dba9a06..7370003d8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java @@ -2,22 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class AffiliateMember extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AffiliateMember { - - private String localId; + @Column(name = "local_id") + private String uri; @Override - public String getID() { - return this.localId; + public String getURI() { + return this.uri; } @Override - public void setID(String id) { - this.localId = id; + public void setURI(String uri) { + this.uri = uri; } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java index a1dba47fa..632bcb888 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java @@ -86,11 +86,11 @@ public void setServiceDescriptions(List serviceDescriptions) } @Override - public List getRequestAttributes() { + public List getRequestedAttributes() { return (List) (List) this.requestedAttributes; } public void setRequestedAttributes(List requestedAttributes) { this.requestedAttributes = requestedAttributes; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java index 21aea9486..51b753c1d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java @@ -2,22 +2,21 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class AttributeProfile extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AttributeProfile { - - private String profileURI; + @Column(name = "profileuri") private String uri; @Override - public String getProfileURI() { - return profileURI; + public String getURI() { + return uri; } @Override - public void setProfileURI(String profileURI) { - this.profileURI = profileURI; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java index 11296d558..d4aa76b91 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java @@ -1,10 +1,54 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.opensaml.core.xml.util.AttributeMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.PostLoad; +import javax.persistence.PrePersist; +import javax.persistence.Transient; +import javax.xml.namespace.QName; +import java.util.HashMap; +import java.util.Map; +/** + * Since Java doesn't support multiple inheritance, this is based on a copy of previously written code - AbstractAttributeExtensibleXMLObject + */ @Entity @EqualsAndHashCode(callSuper = true) -public class AttributeValue extends AbstractXMLObject implements org.opensaml.saml.saml2.core.AttributeValue { -} +public class AttributeValue extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.saml2.core.AttributeValue { + private transient final AttributeMap unknownAttributes = new AttributeMap(this); + private String textContent; + @ElementCollection private Map storageAttributeMap = new HashMap<>(); + + @Nullable + @Override + public String getTextContent() { + return null; + } + + @Override + public void setTextContent(@Nullable String newContent) { + this.textContent = newContent; + } + + @Nonnull + @Override + @Transient + public AttributeMap getUnknownAttributes() { + return this.unknownAttributes; + } + + @PrePersist + void prePersist() { + this.storageAttributeMap = this.unknownAttributes; + } + + @PostLoad + void postLoad() { + this.unknownAttributes.putAll(this.storageAttributeMap); + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java index 54748b91c..1e9d564bb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java @@ -2,22 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class Company extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.Company { - - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java index 2cf346579..53f24b720 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java @@ -1,25 +1,25 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; -import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) @Audited public class EmailAddress extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.EmailAddress { - - private String address; + @Column(name = "address") + private String uri; @Override - public String getAddress() { - return address; + public String getURI() { + return uri; } @Override - public void setAddress(String address) { - this.address = address; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java index d48a3ea6f..effdd6be7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java @@ -3,6 +3,8 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.ext.saml2mdattr.impl.EntityAttributesImpl; import org.opensaml.saml.saml2.core.Assertion; import javax.annotation.Nullable; @@ -55,4 +57,17 @@ public List getOrderedChildren() { return Collections.unmodifiableList(children); } -} + + @Override + public List getEntityAttributesChildren() { + ArrayList children = new ArrayList<>(); + + if (this.getAssertions().size() == 0 && this.getAttributes().size() == 0) { + return null; + } + + children.addAll(this.getAttributes()); + children.addAll(this.getAssertions()); + return children; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java index 612733fc4..e450ae623 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java @@ -1,9 +1,9 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; -import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -11,15 +11,16 @@ @Audited public class GivenName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.GivenName { - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java index 13453438a..ba93d33be 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java @@ -12,7 +12,7 @@ @Audited public class Logo extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.Logo { @Column(name = "logUrl") - private String url; + private String uri; @Column(name = "logoHieght") private int height; @@ -24,13 +24,13 @@ public class Logo extends AbstractXMLObject implements org.opensaml.saml.ext.sam private String xmlLang; @Override - public String getURL() { - return this.url; + public String getURI() { + return this.uri; } @Override - public void setURL(String url) { - this.url = url; + public void setURI(String uri) { + this.uri = uri; } @Override @@ -63,4 +63,4 @@ public String getXMLLang() { public void setXMLLang(@Nullable String xmlLang) { this.xmlLang = xmlLang; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java index 148ec91e7..8c6a9ed27 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -10,16 +11,16 @@ @Audited public class NameIDFormat extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.NameIDFormat { - private String format; - + @Column(name = "format") + private String uri; @Override - public String getFormat() { - return format; + public String getURI() { + return uri; } @Override - public void setFormat(String format) { - this.format = format; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java index 1cf739ece..c8e556695 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java @@ -4,6 +4,7 @@ import org.hibernate.envers.Audited; import javax.annotation.Nullable; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -13,7 +14,8 @@ public class OrganizationURL extends AbstractXMLObject implements org.opensaml.s private String xMLLang; - private String value; + @Column(name="value") + private String uri; @Nullable @Override @@ -28,12 +30,12 @@ public void setXMLLang(@Nullable String xmlLang) { @Nullable @Override - public String getValue() { - return value; + public String getURI() { + return uri; } @Override - public void setValue(@Nullable String value) { - this.value = value; + public void setURI(@Nullable String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java index a62cdeaa6..b6be50f64 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java @@ -2,21 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) public class SurName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.SurName { - - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String name) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java index 729d5d40f..7aa111b07 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java @@ -2,21 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) public class TelephoneNumber extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.TelephoneNumber { - - private String number; + @Column(name = "number") + private String value; @Override - public String getNumber() { - return number; + public String getValue() { + return value; } @Override - public void setNumber(String number) { - this.number = number; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java index 1b13a3cd4..e1a7646ac 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java @@ -11,6 +11,7 @@ import javax.annotation.Nullable; import javax.persistence.Entity; import javax.persistence.Transient; +import java.time.Instant; @Entity @EqualsAndHashCode(callSuper = true) @@ -29,23 +30,21 @@ protected XSDateTime() { @Nullable @Override //TODO: find good way to persist - public DateTime getValue() { - return this.dateTime; + public Instant getValue() { + return Instant.ofEpochMilli(this.dateTime.getMillis()); } @Override - public void setValue(@Nullable DateTime newValue) { - this.dateTime = newValue; + public void setValue(@Nullable Instant newValue) { + this.dateTime = new DateTime(newValue.toEpochMilli()); } @Nonnull - @Override public DateTimeFormatter getDateTimeFormatter() { return this.dateTimeFormatter; } - @Override public void setDateTimeFormatter(@Nonnull DateTimeFormatter newFormatter) { this.dateTimeFormatter = newFormatter; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java index 8663bf818..336bb8cd7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java @@ -12,16 +12,16 @@ @Audited public class XSURI extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSURI { @Column(name = "xsuriValue") - private String value; + private String uri; @Nullable @Override - public String getValue() { - return this.value; + public String getURI() { + return this.uri; } @Override - public void setValue(@Nullable String value) { - this.value = value; + public void setURI(@Nullable String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java index 90a5f6c18..d9c1fc636 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java @@ -6,6 +6,7 @@ import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.common.SAMLObjectBuilder; import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterContext; import org.opensaml.saml.metadata.resolver.filter.impl.NameIDFormatFilter; import org.opensaml.saml.saml2.metadata.AttributeAuthorityDescriptor; import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; @@ -45,7 +46,7 @@ public void setRemoveExistingFormats(final boolean flag) { @Nullable @Override - public XMLObject filter(@Nullable XMLObject metadata) throws FilterException { + public XMLObject filter(@Nullable XMLObject metadata, @Nonnull final MetadataFilterContext context) throws FilterException { if (metadata == null) { return null; } @@ -84,8 +85,8 @@ protected void filterRoleDescriptor(@Nonnull final RoleDescriptor role, for (final String format : formats) { final NameIDFormat nif = formatBuilder.buildObject(); - nif.setFormat(format); + nif.setURI(format); roleFormats.add(nif); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 6a54c409b..c5d64dc5b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -7,8 +7,6 @@ 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.joda.time.chrono.ISOChronology; import org.opensaml.saml.metadata.resolver.filter.FilterException; import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; @@ -17,8 +15,11 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.time.Duration; +import java.time.Instant; -import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toPositiveNonZeroDuration; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toTimeDuration; import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** @@ -49,8 +50,9 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); this.setBackupFile(placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackingFile())); - this.setBackupFileInitNextRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()))); + this.setBackupFileInitNextRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()), + Duration.ofSeconds(5))); if (sourceResolver.getInitializeFromBackupFile() != null) { this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile()); } @@ -64,7 +66,7 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -115,14 +117,14 @@ public synchronized void refresh() throws ResolverException { try { - DateTime now = new DateTime(ISOChronology.getInstanceUTC()); + Instant nowInstant = Instant.ofEpochMilli(System.currentTimeMillis()); String mdId = getMetadataIdentifier(); final byte[] mdBytes = fetchMetadata(); if (mdBytes == null) { - processCachedMetadata(mdId, now); + processCachedMetadata(mdId, nowInstant); } else { - processNewMetadata(mdId, now, mdBytes); + processNewMetadata(mdId, nowInstant, mdBytes); } } catch (final Throwable t) { if (t instanceof Exception) { @@ -133,4 +135,4 @@ public synchronized void refresh() throws ResolverException { } } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java index cfd3bdf2c..c247e7b53 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java @@ -14,6 +14,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; +import java.time.Instant; /** * @author Bill Smith (wsmith@unicon.net) @@ -46,7 +47,7 @@ public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -87,4 +88,4 @@ public void refilter() { logger.error("An error occurred while attempting to filter metadata!", e); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java index cd7c564c7..548c14eb6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java @@ -8,7 +8,10 @@ import org.opensaml.saml.metadata.resolver.impl.AbstractDynamicMetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver; -import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import java.time.Duration; + +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toPositiveNonZeroDuration; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toTimeDuration; import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** @@ -24,12 +27,12 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr if (attributes != null) { if (attributes.getBackgroundInitializationFromCacheDelay() != null) { dynamicMetadataResolver - .setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + .setBackgroundInitializationFromCacheDelay(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } if (attributes.getCleanupTaskInterval() != null) { - dynamicMetadataResolver.setCleanupTaskInterval(toMillis(placeholderResolverService() + dynamicMetadataResolver.setCleanupTaskInterval(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getCleanupTaskInterval()))); } @@ -38,22 +41,22 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr } if (attributes.getMaxCacheDuration() != null) { - dynamicMetadataResolver.setMaxCacheDuration(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMaxCacheDuration(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxCacheDuration()))); } if (attributes.getMaxIdleEntityData() != null) { - dynamicMetadataResolver.setMaxIdleEntityData(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMaxIdleEntityData(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxIdleEntityData()))); } if (attributes.getMinCacheDuration() != null) { - dynamicMetadataResolver.setMinCacheDuration(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMinCacheDuration(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMinCacheDuration()))); } if (attributes.getBackgroundInitializationFromCacheDelay() != null) { - dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } @@ -98,17 +101,17 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA if (attributes != null) { if (attributes.getExpirationWarningThreshold() != null) { reloadingMetadataResolver - .setExpirationWarningThreshold(toMillis(placeholderResolverService() + .setExpirationWarningThreshold(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getExpirationWarningThreshold()))); } - if (attributes.getMaxRefreshDelay() != null) { - reloadingMetadataResolver.setMaxRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxRefreshDelay()))); - } - if (attributes.getMinRefreshDelay() != null) { - reloadingMetadataResolver.setMinRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(attributes.getMinRefreshDelay()))); - } + + // Open SAML 4.x libarry requires values non-null, greater than zero for min and max refresh rates + reloadingMetadataResolver.setMaxRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(attributes.getMaxRefreshDelay()), + Duration.ofHours(4))); + reloadingMetadataResolver.setMinRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(attributes.getMinRefreshDelay()), + Duration.ofMinutes(5))); if (attributes.getResolveViaPredicatesOnly() != null) { reloadingMetadataResolver.setResolveViaPredicatesOnly(attributes.getResolveViaPredicatesOnly()); @@ -125,4 +128,4 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA // attributes.getTaskTimerRef(); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java index 62bdb37d8..1c02099f6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java @@ -14,6 +14,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; +import java.time.Instant; /** * @author Bill Smith (wsmith@unicon.net) @@ -47,7 +48,7 @@ public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -79,4 +80,4 @@ public void refilter() { logger.error("An error occurred while attempting to filter metadata!", e); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java index 93fec88aa..a39ccdd1a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Optional; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -28,8 +29,6 @@ import edu.internet2.tier.shibboleth.admin.ui.security.model.User; import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; -import groovy.util.logging.Slf4j; -import jline.internal.Log; /** * Implementation of the REST resource endpoints exposing system users. @@ -76,7 +75,7 @@ public List getAll() { return results; } catch (Exception e) { - Log.error("Unable to fetch users because: {}", e.getMessage()); + log.error("Unable to fetch users because: {}", e.getMessage()); throw e; } } @@ -149,4 +148,4 @@ ResponseEntity updateOne(@PathVariable(value = "username") String username, @ User savedUser = userService.save(persistedUser); return ResponseEntity.ok(savedUser); } - } + } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java index d1f1f0ccc..f6c419b31 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java @@ -156,7 +156,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope if (ed.getSPSSODescriptor("") != null && ed.getSPSSODescriptor("").getNameIDFormats().size() > 0) { ServiceProviderSsoDescriptorRepresentation serviceProviderSsoDescriptorRepresentation = representation.getServiceProviderSsoDescriptor(true); serviceProviderSsoDescriptorRepresentation.setNameIdFormats( - ed.getSPSSODescriptor("").getNameIDFormats().stream().map(p -> p.getFormat()).collect(Collectors.toList()) + ed.getSPSSODescriptor("").getNameIDFormats().stream().map(p -> p.getURI()).collect(Collectors.toList()) ); } @@ -165,7 +165,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope OrganizationRepresentation organizationRepresentation = new OrganizationRepresentation(); organizationRepresentation.setName(ed.getOrganization().getOrganizationNames().get(0).getValue()); organizationRepresentation.setDisplayName(ed.getOrganization().getDisplayNames().get(0).getValue()); - organizationRepresentation.setUrl(ed.getOrganization().getURLs().get(0).getValue()); + organizationRepresentation.setUrl(ed.getOrganization().getURLs().get(0).getURI()); representation.setOrganization(organizationRepresentation); } @@ -179,10 +179,10 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope contactRepresentation.setType(contactPerson.getType().toString()); } if (contactPerson.getGivenName() != null) { - contactRepresentation.setName(contactPerson.getGivenName().getName()); + contactRepresentation.setName(contactPerson.getGivenName().getValue()); } if (contactPerson.getEmailAddresses() != null && contactPerson.getEmailAddresses().size() > 0) { - contactRepresentation.setEmailAddress(contactPerson.getEmailAddresses().get(0).getAddress()); + contactRepresentation.setEmailAddress(contactPerson.getEmailAddresses().get(0).getURI()); } contactRepresentations.add(contactRepresentation); @@ -200,17 +200,17 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope mduiRepresentation.setDisplayName(uiInfo.getDisplayNames().get(0).getValue()); } if (uiInfo.getInformationURLs().size() > 0) { - mduiRepresentation.setInformationUrl(uiInfo.getInformationURLs().get(0).getValue()); + mduiRepresentation.setInformationUrl(uiInfo.getInformationURLs().get(0).getURI()); } if (uiInfo.getPrivacyStatementURLs().size() > 0) { - mduiRepresentation.setPrivacyStatementUrl(uiInfo.getPrivacyStatementURLs().get(0).getValue()); + mduiRepresentation.setPrivacyStatementUrl(uiInfo.getPrivacyStatementURLs().get(0).getURI()); } if (uiInfo.getDescriptions().size() > 0) { mduiRepresentation.setDescription(uiInfo.getDescriptions().get(0).getValue()); } if (uiInfo.getLogos().size() > 0) { org.opensaml.saml.ext.saml2mdui.Logo logo = uiInfo.getLogos().get(0); - mduiRepresentation.setLogoUrl(logo.getURL()); + mduiRepresentation.setLogoUrl(logo.getURI()); mduiRepresentation.setLogoHeight(logo.getHeight()); mduiRepresentation.setLogoWidth(logo.getWidth()); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java index b19328e27..0d531321a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java @@ -36,4 +36,14 @@ public static Long toMillis(String xmlDuration) { duration.addTo(zero); // potentially can return undesired results for large xmlDurations return zero.getTime(); } -} + + public static java.time.Duration toTimeDuration(String xmlDuration) { + long value = toMillis(xmlDuration); + return java.time.Duration.ofMillis(value); + } + + public static java.time.Duration toPositiveNonZeroDuration (String xmlDuration, java.time.Duration defaultDuration) { + long value = toMillis(xmlDuration); + return value > 0 ? java.time.Duration.ofMillis(value) : defaultDuration; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java index 8b4e7a71a..5fd444344 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java @@ -185,11 +185,11 @@ public static void setupContacts(EntityDescriptor ed, EntityDescriptorRepresenta contactPerson.setType(contactRepresentation.getType()); GivenName givenName = openSamlObjects.buildDefaultInstanceOfType(GivenName.class); - givenName.setName(contactRepresentation.getName()); + givenName.setValue(contactRepresentation.getName()); contactPerson.setGivenName(givenName); EmailAddress emailAddress = openSamlObjects.buildDefaultInstanceOfType(EmailAddress.class); - emailAddress.setAddress(contactRepresentation.getEmailAddress()); + emailAddress.setURI(contactRepresentation.getEmailAddress()); contactPerson.addEmailAddress(emailAddress); ed.addContactPerson(contactPerson); @@ -233,7 +233,7 @@ public static void setupOrganization(EntityDescriptor ed, EntityDescriptorRepres OrganizationURL organizationURL = openSamlObjects.buildDefaultInstanceOfType(OrganizationURL.class); organizationURL.setXMLLang("en"); - organizationURL.setValue(organizationRepresentation.getUrl()); + organizationURL.setURI(organizationRepresentation.getUrl()); organization.getURLs().add(organizationURL); ed.setOrganization(organization); @@ -296,7 +296,7 @@ public static void setupSPSSODescriptor(EntityDescriptor ed, EntityDescriptorRep for (String nameidFormat : representation.getServiceProviderSsoDescriptor().getNameIdFormats()) { NameIDFormat nameIDFormat = openSamlObjects.buildDefaultInstanceOfType(NameIDFormat.class); - nameIDFormat.setFormat(nameidFormat); + nameIDFormat.setURI(nameidFormat); spssoDescriptor.getNameIDFormats().add(nameIDFormat); } @@ -327,7 +327,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getInformationUrl())) { InformationURL informationURL = openSamlObjects.buildDefaultInstanceOfType(InformationURL.class); getUIInfo(ed).addInformationURL(informationURL); - informationURL.setValue(mduiRepresentation.getInformationUrl()); + informationURL.setURI(mduiRepresentation.getInformationUrl()); informationURL.setXMLLang("en"); } else { ed.getOptionalSPSSODescriptor() @@ -339,7 +339,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getPrivacyStatementUrl())) { PrivacyStatementURL privacyStatementURL = openSamlObjects.buildDefaultInstanceOfType(PrivacyStatementURL.class); getUIInfo(ed).addPrivacyStatementURL(privacyStatementURL); - privacyStatementURL.setValue(mduiRepresentation.getPrivacyStatementUrl()); + privacyStatementURL.setURI(mduiRepresentation.getPrivacyStatementUrl()); privacyStatementURL.setXMLLang("en"); } else { ed.getOptionalSPSSODescriptor() @@ -363,7 +363,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getLogoUrl())) { Logo logo = openSamlObjects.buildDefaultInstanceOfType(Logo.class); getUIInfo(ed).addLogo(logo); - logo.setURL(mduiRepresentation.getLogoUrl()); + logo.setURI(mduiRepresentation.getLogoUrl()); logo.setHeight(mduiRepresentation.getLogoHeight()); logo.setWidth(mduiRepresentation.getLogoWidth()); logo.setXMLLang("en"); diff --git a/backend/src/main/resources/jpa-saml2-metadata-config.xml b/backend/src/main/resources/jpa-saml2-metadata-config.xml index 91a2de51a..b008809ce 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-config.xml @@ -21,10 +21,10 @@ - - + + - + @@ -41,15 +41,15 @@ - - + + - + - - + + @@ -81,24 +81,24 @@ - - + + - - + + - - + + - + @@ -115,24 +115,24 @@ - - + + - - + + - - + + - + @@ -149,15 +149,15 @@ - - + + - - + + @@ -202,8 +202,8 @@ - - + + @@ -235,22 +235,22 @@ - - + + - - + + - - + + @@ -269,22 +269,22 @@ - - + + - - + + - - + + @@ -316,29 +316,29 @@ - - + + - - + + - - + + - - + + @@ -357,16 +357,16 @@ - - + + - - + + - + \ No newline at end of file diff --git a/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml b/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml index 868961e13..f2dd17dfe 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml @@ -7,8 +7,8 @@ - - + + diff --git a/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml b/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml index 1ab941897..b9aa1bb66 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml @@ -9,8 +9,8 @@ - - + + @@ -44,8 +44,8 @@ - - + + @@ -69,8 +69,8 @@ - - + + @@ -98,8 +98,8 @@ - - + + @@ -116,4 +116,4 @@ - + \ No newline at end of file diff --git a/backend/src/main/resources/modified-saml2-assertion-config.xml b/backend/src/main/resources/modified-saml2-assertion-config.xml index 1f9d649a0..2f09fa77b 100644 --- a/backend/src/main/resources/modified-saml2-assertion-config.xml +++ b/backend/src/main/resources/modified-saml2-assertion-config.xml @@ -46,15 +46,15 @@ - - + + - - + + @@ -73,8 +73,8 @@ - - + + @@ -93,8 +93,8 @@ - - + + @@ -113,22 +113,22 @@ - - + + - - + + - - + + @@ -207,8 +207,8 @@ - - + + @@ -221,14 +221,14 @@ - - + + - - + + @@ -310,4 +310,4 @@ - + \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy index bda1b4dfa..d64fa8861 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy @@ -2,17 +2,12 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService -import groovy.json.JsonOutput import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet - -import org.joda.time.DateTime import org.opensaml.core.criterion.EntityIdCriterion 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.FilesystemMetadataResolver import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired @@ -22,15 +17,14 @@ import org.springframework.context.annotation.Bean import org.springframework.core.io.ClassPathResource import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.reactive.server.WebTestClient -import org.springframework.test.web.servlet.result.MockMvcResultHandlers -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.util.DefaultUriBuilderFactory import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.diff.DefaultNodeMatcher import org.xmlunit.diff.ElementSelectors import spock.lang.Specification +import java.time.Instant + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -165,7 +159,7 @@ class EntitiesControllerIntegrationTests extends Specification { def resource = ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml")) def aggregate = new ResourceBackedMetadataResolver(resource){ @Override - DateTime getLastRefresh() { + Instant getLastRefresh() { return null } } @@ -186,4 +180,4 @@ class EntitiesControllerIntegrationTests extends Specification { } } } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index 703e44f7a..594ee6750 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -22,7 +22,6 @@ import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet -import org.joda.time.DateTime import org.opensaml.core.criterion.EntityIdCriterion import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain @@ -37,6 +36,8 @@ import org.xmlunit.builder.Input import spock.lang.Ignore import spock.lang.Unroll +import java.time.Instant + import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml @ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration ]) @@ -93,10 +94,8 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { givenName employeeNumber + testme - - testme - @@ -131,7 +130,9 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { assert metadataResolverRepository.findAll().size() > 0 def ed = metadataResolver.resolveSingle(new CriteriaSet(new EntityIdCriterion('http://test.scaldingspoon.org/test1'))) def resultString = openSamlObjects.marshalToXmlString(ed) + println("RESULTSTRING:") println(resultString) + // line 99 above being added to release all values, not its own thing def diff = DiffBuilder.compare(Input.fromString(expectedXML)).withTest(Input.fromString(resultString)).ignoreComments().ignoreWhitespace().build() !diff.hasDifferences() } @@ -475,7 +476,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { MetadataResolver metadataResolver(OpenSamlObjects openSamlObjects) { def aggregate = new ResourceBackedMetadataResolver(ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml"))){ @Override - DateTime getLastRefresh() { + Instant getLastRefresh() { return null } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy index 321ef2b38..d25e9813c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy @@ -1005,7 +1005,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' @@ -1034,7 +1034,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' @@ -1070,7 +1070,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' diff --git a/beacon/core/build.gradle b/beacon/core/build.gradle index c80df0931..b4ddfd4ca 100644 --- a/beacon/core/build.gradle +++ b/beacon/core/build.gradle @@ -1,16 +1,21 @@ import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { - id 'org.springframework.boot' version '2.4.2' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.6.RELEASE' + id 'groovy' } -apply plugin: 'groovy' sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } } dependencyManagement { @@ -20,14 +25,13 @@ dependencyManagement { } dependencies { - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" - - testCompile 'org.junit.jupiter:junit-jupiter-api:5.5.2' - testCompile 'org.junit.jupiter:junit-jupiter-engine:5.5.2' + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" } jar { archiveName = "beacon-core-${version}.jar" -} +} \ No newline at end of file diff --git a/beacon/spring/build.gradle b/beacon/spring/build.gradle index 61ab07be5..eb6d1e991 100644 --- a/beacon/spring/build.gradle +++ b/beacon/spring/build.gradle @@ -1,7 +1,7 @@ import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { - id 'org.springframework.boot' version '2.0.0.RELEASE' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.6.RELEASE' } @@ -9,8 +9,13 @@ apply plugin: 'java' sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } } jar { diff --git a/gradle.properties b/gradle.properties index 79bee945d..f645de2d4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,14 +2,22 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui version=1.11.0-SNAPSHOT -shibboleth.version=3.4.4 -opensaml.version=3.4.3 - -spring-boot.version=2.4.2 - -hibernate.version=5.5.0.Final - -lucene.version=8.1.1 +### library versions ### +commonsCollections4Version=4.4 +cryptacularVersion=1.2.4 +hibernateVersion=5.5.0.Final +#hibernateVersion=5.6.9.Final +luceneVersion=8.1.1 +log4JVersion=2.17.2 +lombokVersion=5.3.3.3 +opensamlVersion=4.2.0 +pac4JVersion=5.4.3 +pac4jSpringSecurityVersion=7.0.3 +shibbolethVersion=4.2.1 +springbootVersion=2.5.12 +#springbootVersion=2.7.0 +springSecurityVersion=5.6.3 +# springSecurityVersion=5.7.1 org.gradle.jvmargs=-Xmx1g -XX:-UseGCOverheadLimit @@ -19,3 +27,12 @@ i2.github.owner=TIER i2.github.repo=shib-idp-ui i2.github.apiEndpoint=https://github.internet2.edu/api/v3 +## NOTES +# pac4j spring security 7.0.3 here uses the pac4j 5.4.3 core, thus differences in versions (they used use the same versions, now +# keeping them in sync takes paying attention +# +# Springboot 2.7.0 and Hibernate 5.6.9 are current, but don't like all the columns named "value" in the db (along with H2), so don't +# update to these versions until ready to migrate the database columns. (the tests fail under these versions because the test database +# doesn't work). +# +# Additionally, springbootsecurity for tests doesn't like 5.7.1 \ No newline at end of file diff --git a/pac4j-module/build.gradle b/pac4j-module/build.gradle index 8803d22c9..6a1295758 100644 --- a/pac4j-module/build.gradle +++ b/pac4j-module/build.gradle @@ -1,20 +1,30 @@ plugins { id 'groovy' id 'jacoco' - id 'org.springframework.boot' version '2.4.2' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.7.RELEASE' - id 'io.freefair.lombok' version '5.3.0' + id 'io.freefair.lombok' } sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + mavenCentral() maven { url 'https://build.shibboleth.net/nexus/content/groups/public' artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] } + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } +} + +test { + useJUnitPlatform() // Needed by spock to find specification tests } dependencyManagement { @@ -28,27 +38,24 @@ generateLombokConfig.enabled = false dependencies { compileOnly project(':backend') - compile "org.pac4j:spring-security-pac4j:4.0.0" - compile "org.pac4j:pac4j-core:3.3.0" - compile "org.pac4j:pac4j-http:3.3.0" - compile "org.pac4j:pac4j-saml:3.3.0", { + compile "org.pac4j:spring-security-pac4j:${project.'pac4jSpringSecurityVersion'}" + compile "org.pac4j:pac4j-core:${project.'pac4JVersion'}" + compile "org.pac4j:pac4j-http:${project.'pac4JVersion'}" + compile "org.pac4j:pac4j-saml:${project.'pac4JVersion'}", { // opensaml libraries are provided exclude group: 'org.opensaml' + exclude group: 'commons-collections' } - -// These updated versions don't play well with the opensaml 3.4.6 version - until we can update openSAML.... -// compile "org.pac4j:spring-security-pac4j:6.0.0" // pac4j is "off" - spring 6.0.0 here uses 5.1 core, thus differences in versions -// compile "org.pac4j:pac4j-core:5.1.0" -// compile "org.pac4j:pac4j-http:5.1.0" -// compile "org.pac4j:pac4j-saml:5.1.0", { -// // opensaml libraries are provided -// exclude group: 'org.opensaml' -// } + compile "org.apache.commons:commons-collections4:${project.'commonsCollections4Version'}" testCompile project(':backend') - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + testCompile "org.opensaml:opensaml-saml-api:${project.'opensamlVersion'}" + + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" - annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor:${project.'springbootVersion'}" } \ No newline at end of file diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java index c0c9048fa..c7ed5fd71 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java @@ -11,10 +11,12 @@ import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.pac4j.core.context.J2EContext; import org.pac4j.core.context.WebContext; -import org.pac4j.core.matching.Matcher; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.matching.matcher.Matcher; import org.pac4j.core.profile.CommonProfile; +import org.pac4j.jee.context.JEEContext; +import org.pac4j.jee.context.session.JEESessionStore; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCrypt; @@ -103,8 +105,10 @@ public void destroy() { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - WebContext context = new J2EContext((HttpServletRequest)request, (HttpServletResponse)response); - if (!matcher.matches(context)) { + WebContext context = new JEEContext((HttpServletRequest)request, (HttpServletResponse)response); + Optional optionalSession = JEESessionStore.INSTANCE.buildFromTrackableSession(context, ((HttpServletRequest) request).getSession()); + SessionStore session = optionalSession.isPresent() ? (SessionStore) optionalSession.get() : null; + if (!matcher.matches(context, session)) { return; } Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java index 5d9642409..4ec901998 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java @@ -4,7 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import org.pac4j.core.authorization.generator.AuthorizationGenerator; import org.pac4j.core.context.WebContext; -import org.pac4j.core.profile.CommonProfile; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.profile.UserProfile; import java.util.Optional; @@ -16,9 +17,9 @@ public LocalUserProfileAuthorizationGenerator(UserRepository userRepository) { } @Override - public CommonProfile generate(WebContext context, CommonProfile profile) { + public Optional generate(WebContext context, SessionStore sessionStore, UserProfile profile) { Optional user = userRepository.findByUsername(profile.getUsername()); user.ifPresent(u -> profile.addRole(u.getRole())); - return profile; + return Optional.of(profile); } } \ No newline at end of file diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java index 26d32708f..fd018d4b6 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java @@ -8,11 +8,11 @@ import net.unicon.shibui.pac4j.authenticator.ShibuiSAML2Authenticator; import org.pac4j.core.client.Clients; import org.pac4j.core.config.Config; -import org.pac4j.core.matching.PathMatcher; +import org.pac4j.core.matching.matcher.PathMatcher; import org.pac4j.core.profile.definition.CommonProfileDefinition; import org.pac4j.http.client.direct.HeaderClient; import org.pac4j.saml.client.SAML2Client; -import org.pac4j.saml.client.SAML2ClientConfiguration; +import org.pac4j.saml.config.SAML2Configuration; import org.pac4j.saml.credentials.authenticator.SAML2Authenticator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -69,7 +69,7 @@ public Config config(final Pac4jConfigurationProperties pac4jConfigProps, case "SAML2": default: log.info("**** Configuring PAC4J SAML2"); - final SAML2ClientConfiguration saml2Config = new SAML2ClientConfiguration(); + final SAML2Configuration saml2Config = new SAML2Configuration(); saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath()); saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword()); saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword()); diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java index 17bc554ff..a67bf4a96 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java @@ -7,7 +7,7 @@ import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; import static net.unicon.shibui.pac4j.Pac4jConfiguration.PAC4J_CLIENT_NAME; import org.pac4j.core.config.Config; -import org.pac4j.core.matching.Matcher; +import org.pac4j.core.matching.matcher.Matcher; import org.pac4j.springframework.security.web.CallbackFilter; import org.pac4j.springframework.security.web.SecurityFilter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java index 1109b5d72..0c1a9e084 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.pac4j.core.context.WebContext; +import org.pac4j.core.context.session.SessionStore; import org.pac4j.core.credentials.Credentials; import org.pac4j.core.credentials.TokenCredentials; import org.pac4j.core.credentials.authenticator.Authenticator; @@ -18,7 +19,7 @@ public class ShibuiPac4JHeaderClientAuthenticator implements Authenticator { private UserService userService; @Override - public void validate(Credentials credentials, WebContext context) { + public void validate(Credentials credentials, WebContext context, SessionStore sessionStore) { { if (credentials instanceof TokenCredentials) { TokenCredentials creds = (TokenCredentials) credentials; diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java index c5eb8f18b..f2d2738e0 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java @@ -1,10 +1,10 @@ package net.unicon.shibui.pac4j.authenticator; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; -import lombok.AllArgsConstructor; import org.pac4j.core.context.WebContext; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.credentials.Credentials; import org.pac4j.core.profile.CommonProfile; -import org.pac4j.saml.credentials.SAML2Credentials; import org.pac4j.saml.credentials.authenticator.SAML2Authenticator; import java.util.Map; @@ -23,9 +23,9 @@ public ShibuiSAML2Authenticator(final String attributeAsId, final Map