diff --git a/README.md b/README.md
index a03a53d0b..4ec4f8196 100644
--- a/README.md
+++ b/README.md
@@ -47,12 +47,7 @@ The easiest way to do this in a servlet container is through the use of system p
## Authentication
Currently, the application is wired with very simple authentication. A password for the user `root`
-can be set with the `shibui.default-password` property. If none is set, a default password
-will be generated and logged:
-
-```
-Using default security password: a3d9ab96-9c63-414f-b199-26fcf59e1ffa
-```
+can be set with the `shibui.default-password` property.
## Default Properties
diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/UserBootstrap.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/UserBootstrap.groovy
index 33d93564c..4ca5b435b 100644
--- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/UserBootstrap.groovy
+++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/UserBootstrap.groovy
@@ -46,7 +46,7 @@ class UserBootstrap {
it.password = password
it.firstName = firstName
it.lastName = lastName
- it.roles.add(role)
+ it.roles = [role]
it.emailAddress = email
it
}
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java
index 1dcdc6ce7..5d64ab623 100644
--- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java
@@ -1,6 +1,9 @@
package edu.internet2.tier.shibboleth.admin.ui.configuration.auto;
import edu.internet2.tier.shibboleth.admin.ui.security.DefaultAuditorAware;
+import edu.internet2.tier.shibboleth.admin.ui.security.model.Role;
+import edu.internet2.tier.shibboleth.admin.ui.security.model.User;
+import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository;
import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository;
import edu.internet2.tier.shibboleth.admin.ui.security.springsecurity.AdminUserService;
import org.springframework.beans.factory.annotation.Autowired;
@@ -23,6 +26,8 @@
import org.springframework.security.web.firewall.StrictHttpFirewall;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
+import java.util.Collections;
+
/**
* Web security configuration.
*
@@ -42,6 +47,9 @@ public class WebSecurityConfig {
@Autowired
private UserRepository userRepository;
+ @Autowired
+ private RoleRepository roleRepository;
+
@Bean
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
StrictHttpFirewall firewall = new StrictHttpFirewall();
@@ -72,6 +80,25 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// TODO: more configurable authentication
PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
if (defaultPassword != null && !"".equals(defaultPassword)) {
+ // TODO: yeah, this isn't good, but we gotta initialize this user for now
+ User adminUser = userRepository.findByUsername("root").orElseGet(() ->{
+ User u = new User();
+ u.setUsername("root");
+ u.setPassword(defaultPassword);
+ u.setFirstName("admin");
+ u.setLastName("user");
+ Role adminRole = roleRepository.findByName("ROLE_ADMIN").orElseGet(() -> {
+ Role r = new Role();
+ r.setName("ROLE_ADMIN");
+ return roleRepository.saveAndFlush(r);
+ });
+ u.setRoles(Collections.singleton(adminRole));
+ u.setEmailAddress("admin@localhost");
+ return userRepository.saveAndFlush(u);
+ });
+ adminUser.setPassword(defaultPassword);
+ userRepository.saveAndFlush(adminUser);
+
auth
.inMemoryAuthentication()
.withUser("root")
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RelyingPartyOverrideProperty.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RelyingPartyOverrideProperty.java
index 24432d1be..1808ab6ef 100644
--- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RelyingPartyOverrideProperty.java
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/RelyingPartyOverrideProperty.java
@@ -21,6 +21,7 @@ public class RelyingPartyOverrideProperty {
private String persistValue;
private String attributeName;
private String attributeFriendlyName;
+ private String invert;
@Override
public String toString() {
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 168e977a5..49823c008 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
@@ -660,7 +660,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope
!overrideProperty.getPersistType().equals(overrideProperty.getDisplayType())) {
attributeValues = overrideProperty.getPersistValue().equals(getValueFromXMLObject(jpaAttribute.getAttributeValues().get(0)));
} else {
- attributeValues = Boolean.valueOf(((XSBoolean) jpaAttribute.getAttributeValues()
+ attributeValues = Boolean.valueOf(overrideProperty.getInvert()) ^ Boolean.valueOf(((XSBoolean) jpaAttribute.getAttributeValues()
.get(0)).getStoredValue());
}
break;
diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java
index 7d9e9388c..7afbac551 100644
--- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java
+++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java
@@ -94,6 +94,51 @@ public List getAttributeListFromAttributeReleaseList(List att
return (List)(List extends Attribute>)attributeList;
}
+ edu.internet2.tier.shibboleth.admin.ui.domain.Attribute getAttributeFromObjectAndRelyingPartyOverrideProperty(Object o, RelyingPartyOverrideProperty overrideProperty) {
+ switch (ModelRepresentationConversions.AttributeTypes.valueOf(overrideProperty.getDisplayType().toUpperCase())) {
+ case BOOLEAN:
+ if ((o instanceof Boolean && ((Boolean)o)) ||
+ (o instanceof String) && Boolean.valueOf((String)o)) {
+ if (overrideProperty.getPersistType() != null &&
+ !overrideProperty.getPersistType().equalsIgnoreCase("boolean")) {
+ return attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ overrideProperty.getPersistValue());
+ } else {
+ if (o instanceof String) {
+ return attributeUtility.createAttributeWithBooleanValue(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ Boolean.valueOf((String) o));
+ } else {
+ Boolean value = Boolean.valueOf(overrideProperty.getInvert()) ^ (Boolean)o;
+ return attributeUtility.createAttributeWithBooleanValue(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ value);
+ }
+ }
+ }
+ return null;
+ case INTEGER:
+ return attributeUtility.createAttributeWithIntegerValue(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ Integer.valueOf((String) o));
+ case STRING:
+ return attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ (String) o);
+ case SET:
+ return attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ (List) o);
+ case LIST:
+ return attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
+ overrideProperty.getAttributeFriendlyName(),
+ (List) o);
+ default:
+ throw new UnsupportedOperationException("getAttributeListFromRelyingPartyOverridesRepresentation was called with an unsupported type (" + overrideProperty.getDisplayType() + ")!");
+ }
+ }
+
@Override
public List getAttributeListFromRelyingPartyOverridesRepresentation(Map relyingPartyOverridesRepresentation) {
List overridePropertyList = customPropertiesConfiguration.getOverrides();
@@ -102,50 +147,9 @@ public List getAttributeListFromRelyingPartyOverridesRepresentation(M
for (Map.Entry entry : relyingPartyOverridesRepresentation.entrySet()) {
String key = (String) entry.getKey();
RelyingPartyOverrideProperty overrideProperty = overridePropertyList.stream().filter(op -> op.getName().equals(key)).findFirst().get();
- switch (ModelRepresentationConversions.AttributeTypes.valueOf(overrideProperty.getDisplayType().toUpperCase())) {
- case BOOLEAN:
- if ((entry.getValue() instanceof Boolean && (Boolean)entry.getValue()) ||
- ((entry.getValue() instanceof String) && Boolean.valueOf((String)entry.getValue()))) {
- if (overrideProperty.getPersistType() != null &&
- !overrideProperty.getPersistType().equalsIgnoreCase("boolean")) {
- list.add(attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- overrideProperty.getPersistValue()));
- } else {
- if (entry.getValue() instanceof String) {
- list.add(attributeUtility.createAttributeWithBooleanValue(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- Boolean.valueOf((String) entry.getValue())));
- } else {
- list.add(attributeUtility.createAttributeWithBooleanValue(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- (Boolean) entry.getValue()));
- }
- }
- }
- break;
- case INTEGER:
- list.add(attributeUtility.createAttributeWithIntegerValue(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- Integer.valueOf((String) entry.getValue())));
- break;
- case STRING:
- list.add(attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- (String) entry.getValue()));
- break;
- case SET:
- list.add(attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- (List) entry.getValue()));
- break;
- case LIST:
- list.add(attributeUtility.createAttributeWithStringValues(overrideProperty.getAttributeName(),
- overrideProperty.getAttributeFriendlyName(),
- (List) entry.getValue()));
- break;
- default:
- throw new UnsupportedOperationException("getAttributeListFromRelyingPartyOverridesRepresentation was called with an unsupported type (" + overrideProperty.getDisplayType() + ")!");
+ edu.internet2.tier.shibboleth.admin.ui.domain.Attribute attribute = getAttributeFromObjectAndRelyingPartyOverrideProperty(entry.getValue(), overrideProperty);
+ if (attribute != null) {
+ list.add(attribute);
}
}
diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml
index 12bfd55cc..8e823e8a3 100644
--- a/backend/src/main/resources/application.yml
+++ b/backend/src/main/resources/application.yml
@@ -61,6 +61,7 @@ custom:
helpText: tooltip.dont-sign-response
attributeName: http://shibboleth.net/ns/profiles/saml2/sso/browser/signResponses
attributeFriendlyName: signResponses
+ invert: true
- name: turnOffEncryption
displayName: label.turn-off-encryption-of-response
displayType: boolean
@@ -68,6 +69,7 @@ custom:
helpText: tooltip.turn-off-encryption
attributeName: http://shibboleth.net/ns/profiles/encryptAssertions
attributeFriendlyName: encryptAssertions
+ invert: true
- name: useSha
displayName: label.use-sha1-signing-algorithm
displayType: boolean
@@ -93,6 +95,7 @@ custom:
helpText: tooltip.omit-not-before-condition
attributeName: http://shibboleth.net/ns/profiles/includeConditionsNotBefore
attributeFriendlyName: includeConditionsNotBefore
+ invert: true
- name: responderId
displayName: label.responder-id
displayType: string
diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy
new file mode 100644
index 000000000..92c2627aa
--- /dev/null
+++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy
@@ -0,0 +1,45 @@
+package edu.internet2.tier.shibboleth.admin.ui.service
+
+import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute
+import edu.internet2.tier.shibboleth.admin.ui.domain.RelyingPartyOverrideProperty
+import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean
+import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects
+import edu.internet2.tier.shibboleth.admin.util.AttributeUtility
+import spock.lang.Shared
+import spock.lang.Specification
+import spock.lang.Unroll
+
+class AuxiliaryJPAEntityServiceTests extends Specification {
+ @Shared
+ JPAEntityServiceImpl jpaEntityService
+
+ def setup() {
+ def openSamlObjects = new OpenSamlObjects().with {
+ it.init()
+ it
+ }
+
+ def attributeUtility = new AttributeUtility(openSamlObjects)
+
+ jpaEntityService = new JPAEntityServiceImpl(openSamlObjects, attributeUtility)
+ }
+
+ @Unroll
+ def "test invert #input"() {
+ setup:
+ RelyingPartyOverrideProperty overrideProperty = new RelyingPartyOverrideProperty(
+ attributeName: 'name',
+ attributeFriendlyName: 'friendlyName',
+ displayType: 'boolean',
+ invert: 'true'
+ )
+ Attribute att = jpaEntityService.getAttributeFromObjectAndRelyingPartyOverrideProperty(input, overrideProperty)
+
+ expect:
+ assert att && att.getAttributeValues()[0] instanceof XSBoolean && ((XSBoolean) att.getAttributeValues()[0]).value.value == output
+
+ where:
+ input | output
+ true | false
+ }
+}