From 9bcaf3819d24f58ef511e3b1663a194e1c11ad93 Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 09:56:41 -0600 Subject: [PATCH 1/9] [NOISSUE] missed update for role --- .../tier/shibboleth/admin/ui/service/UserBootstrap.groovy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 } From cd289d1a6dedd11b005abd63111f6db1acb10bbd Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 12:10:57 -0600 Subject: [PATCH 2/9] [NOISSUE] allow inverted storage of attributes --- .../domain/RelyingPartyOverrideProperty.java | 1 + .../ui/service/JPAEntityServiceImpl.java | 92 ++++++++++--------- .../AuxiliaryJPAEntityServiceTests.groovy | 46 ++++++++++ 3 files changed, 95 insertions(+), 44 deletions(-) create mode 100644 backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy 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/JPAEntityServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java index 7d9e9388c..4c761c739 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)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) || (!(Boolean)o && Boolean.valueOf(overrideProperty.getInvert()))) || + (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 : (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/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..dccf8c8fd --- /dev/null +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy @@ -0,0 +1,46 @@ +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 + false | true + } +} From e3c322aa103ff97e6e951965f75c549013ec6075 Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 12:35:28 -0600 Subject: [PATCH 3/9] [NOISSUE] allow inverted retrieve of attributes --- .../admin/ui/service/JPAEntityDescriptorServiceImpl.java | 2 +- .../tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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 4c761c739..5724e8dd4 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 @@ -110,7 +110,7 @@ edu.internet2.tier.shibboleth.admin.ui.domain.Attribute getAttributeFromObjectAn overrideProperty.getAttributeFriendlyName(), Boolean.valueOf((String) o)); } else { - Boolean value = Boolean.valueOf(overrideProperty.getInvert()) ? !(Boolean)o : (Boolean)o; + Boolean value = Boolean.valueOf(overrideProperty.getInvert()) ^ (Boolean)o; return attributeUtility.createAttributeWithBooleanValue(overrideProperty.getAttributeName(), overrideProperty.getAttributeFriendlyName(), value); From d15ed453be65974d5452cbb839297b281fd254f6 Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 14:40:16 -0600 Subject: [PATCH 4/9] [NOISSUE] mark default inverted booleans --- backend/src/main/resources/application.yml | 3 +++ 1 file changed, 3 insertions(+) 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 From 1985d3618aebdd3372b324a29b431edb1badc64d Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 14:40:35 -0600 Subject: [PATCH 5/9] [NOISSUE] fix logic --- .../tier/shibboleth/admin/ui/service/JPAEntityServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5724e8dd4..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 @@ -97,7 +97,7 @@ public List getAttributeListFromAttributeReleaseList(List att 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) || (!(Boolean)o && Boolean.valueOf(overrideProperty.getInvert()))) || + if ((o instanceof Boolean && ((Boolean)o)) || (o instanceof String) && Boolean.valueOf((String)o)) { if (overrideProperty.getPersistType() != null && !overrideProperty.getPersistType().equalsIgnoreCase("boolean")) { From da58b4d32598aadc520df369b01cda045842c9b7 Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 15:17:16 -0600 Subject: [PATCH 6/9] [NOISSUE] remove unneeded test --- .../admin/ui/service/AuxiliaryJPAEntityServiceTests.groovy | 1 - 1 file changed, 1 deletion(-) 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 index dccf8c8fd..92c2627aa 100644 --- 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 @@ -41,6 +41,5 @@ class AuxiliaryJPAEntityServiceTests extends Specification { where: input | output true | false - false | true } } From 88384a5468bdaa82cf68a0d4ffee993914e5e16a Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 15:49:39 -0600 Subject: [PATCH 7/9] [NOISSUE] bootstrap root user into database --- .../configuration/auto/WebSecurityConfig.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) 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..3858ad10e 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 + Role adminRole = roleRepository.findByName("ROLE_ADMIN").orElseGet(() -> { + Role r = new Role(); + r.setName("ROLE_ADMIN"); + return roleRepository.saveAndFlush(r); + }); + User adminUser = userRepository.findByUsername("root").orElseGet(() ->{ + User u = new User(); + u.setUsername("root"); + u.setPassword(defaultPassword); + u.setFirstName("admin"); + u.setLastName("user"); + u.setRoles(Collections.singleton(adminRole)); + u.setEmailAddress("admin@localhost"); + return userRepository.saveAndFlush(u); + }); + adminUser.setPassword(defaultPassword); + userRepository.saveAndFlush(adminUser); + auth .inMemoryAuthentication() .withUser("root") From 0b8bee12d2c30cfde6ef9411374e1d99a08f24a8 Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 15:52:46 -0600 Subject: [PATCH 8/9] [NOISSUE] move scope --- .../admin/ui/configuration/auto/WebSecurityConfig.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 3858ad10e..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 @@ -81,17 +81,17 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder(); if (defaultPassword != null && !"".equals(defaultPassword)) { // TODO: yeah, this isn't good, but we gotta initialize this user for now - Role adminRole = roleRepository.findByName("ROLE_ADMIN").orElseGet(() -> { - Role r = new Role(); - r.setName("ROLE_ADMIN"); - return roleRepository.saveAndFlush(r); - }); 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); From f4531f0830d23d269ef6ec24b2651bcf8fdbd8bc Mon Sep 17 00:00:00 2001 From: Jj! Date: Tue, 5 Mar 2019 16:57:41 -0600 Subject: [PATCH 9/9] [NOISSUE] update documentation --- README.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) 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