diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java index 386e37dea..edcfc4ccb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java @@ -69,7 +69,7 @@ public MetadataResolverService metadataResolverService() { @Bean public AttributeUtility attributeUtility() { - return new AttributeUtility(); + return new AttributeUtility(openSamlObjects()); } @Autowired diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilter.java index 9a89d33f9..d4c4bc878 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilter.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilter.java @@ -2,7 +2,9 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation; import edu.internet2.tier.shibboleth.admin.util.MDDCConstants; +import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; @@ -16,14 +18,19 @@ import javax.persistence.OneToOne; import javax.persistence.OrderColumn; import javax.persistence.PostLoad; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; import javax.persistence.Transient; import java.util.ArrayList; import java.util.List; +import static edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions.getAttributeListFromAttributeReleaseList; +import static edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions.getAttributeListFromRelyingPartyOverridesRepresentation; import static edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions.getAttributeReleaseListFromAttributeList; +import static edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions.getRelyingPartyOverridesRepresentationFromAttributeList; @Entity -@EqualsAndHashCode(callSuper = true) +@EqualsAndHashCode(callSuper = true, exclude={"attributeRelease", "relyingPartyOverrides"}) @NoArgsConstructor @Getter @Setter @@ -41,8 +48,22 @@ public class EntityAttributesFilter extends MetadataFilter { @Transient private List attributeRelease = new ArrayList<>(); + @Transient + private RelyingPartyOverridesRepresentation relyingPartyOverrides; + @PostLoad public void intoTransientRepresentation() { this.attributeRelease = getAttributeReleaseListFromAttributeList(this.attributes); + this.relyingPartyOverrides = getRelyingPartyOverridesRepresentationFromAttributeList(attributes); + } + + @PrePersist + @PreUpdate + public void fromTransientRepresentation() { + List attributeList = new ArrayList<>(); + attributeList.addAll(getAttributeListFromAttributeReleaseList(this.attributeRelease)); + attributeList.addAll(getAttributeListFromRelyingPartyOverridesRepresentation(this.relyingPartyOverrides)); + this.attributes = + (List)(List)attributeList; } } 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 53d0dc070..28fa8b3fd 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 @@ -30,7 +30,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.UIInfo; import edu.internet2.tier.shibboleth.admin.ui.domain.XSAny; import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean; -import edu.internet2.tier.shibboleth.admin.ui.domain.XSString; + import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ContactRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; @@ -42,7 +42,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.util.MDDCConstants; -import org.opensaml.core.xml.XMLObject; +import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions; + import org.opensaml.core.xml.schema.XSBooleanValue; import org.opensaml.xmlsec.signature.KeyInfo; import org.opensaml.xmlsec.signature.X509Certificate; @@ -540,54 +541,12 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope @Override public List getAttributeReleaseListFromAttributeList(List attributeList) { - return getAttributeReleaseListFromAttributeList(attributeList); + return ModelRepresentationConversions.getAttributeReleaseListFromAttributeList(attributeList); } @Override public RelyingPartyOverridesRepresentation getRelyingPartyOverridesRepresentationFromAttributeList(List attributeList) { - RelyingPartyOverridesRepresentation relyingPartyOverridesRepresentation = new RelyingPartyOverridesRepresentation(); - - for (org.opensaml.saml.saml2.core.Attribute attribute : attributeList) { - Attribute jpaAttribute = (Attribute) attribute; - // TODO: this is going to get real ugly real quick. clean it up, future Jj! - switch (jpaAttribute.getName()) { - case MDDCConstants.SIGN_ASSERTIONS: - relyingPartyOverridesRepresentation.setSignAssertion(getBooleanValueOfAttribute(jpaAttribute)); - break; - case MDDCConstants.SIGN_RESPONSES: - relyingPartyOverridesRepresentation.setDontSignResponse(!getBooleanValueOfAttribute(jpaAttribute)); - break; - case MDDCConstants.ENCRYPT_ASSERTIONS: - relyingPartyOverridesRepresentation.setTurnOffEncryption(!getBooleanValueOfAttribute(jpaAttribute)); - break; - case MDDCConstants.SECURITY_CONFIGURATION: - if (getStringListValueOfAttribute(jpaAttribute).contains("shibboleth.SecurityConfiguration.SHA1")) { - relyingPartyOverridesRepresentation.setUseSha(true); - } - break; - case MDDCConstants.DISALLOWED_FEATURES: - if ((Integer.decode(getStringListValueOfAttribute(jpaAttribute).get(0)) & 0x1) == 0x1) { - relyingPartyOverridesRepresentation.setIgnoreAuthenticationMethod(true); - } - break; - case MDDCConstants.INCLUDE_CONDITIONS_NOT_BEFORE: - relyingPartyOverridesRepresentation.setOmitNotBefore(!getBooleanValueOfAttribute(jpaAttribute)); - break; - case MDDCConstants.RESPONDER_ID: - relyingPartyOverridesRepresentation.setResponderId(getStringListValueOfAttribute(jpaAttribute).get(0)); - break; - case MDDCConstants.NAME_ID_FORMAT_PRECEDENCE: - relyingPartyOverridesRepresentation.setNameIdFormats(getStringListValueOfAttribute(jpaAttribute)); - break; - case MDDCConstants.DEFAULT_AUTHENTICATION_METHODS: - relyingPartyOverridesRepresentation.setAuthenticationMethods(getStringListValueOfAttribute(jpaAttribute)); - break; - default: - break; - } - } - - return relyingPartyOverridesRepresentation; + return ModelRepresentationConversions.getRelyingPartyOverridesRepresentationFromAttributeList(attributeList); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/AttributeUtility.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/AttributeUtility.java index 0849bfb42..2282b04e2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/AttributeUtility.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/AttributeUtility.java @@ -15,10 +15,9 @@ */ public class AttributeUtility { - @Autowired private OpenSamlObjects openSamlObjects; - public void setOpenSamlObjects(OpenSamlObjects openSamlObjects) { + public AttributeUtility(OpenSamlObjects openSamlObjects) { this.openSamlObjects = openSamlObjects; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/ModelRepresentationConversions.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/ModelRepresentationConversions.java index 42db38e77..27fd92445 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/ModelRepresentationConversions.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/ModelRepresentationConversions.java @@ -2,6 +2,9 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute; import edu.internet2.tier.shibboleth.admin.ui.domain.XSBoolean; +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.RelyingPartyOverridesRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; +import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import org.opensaml.core.xml.XMLObject; import java.util.ArrayList; @@ -13,6 +16,20 @@ */ public abstract class ModelRepresentationConversions { + private static final AttributeUtility ATTRIBUTE_UTILITY; + + static { + OpenSamlObjects openSamlObjects = new OpenSamlObjects(); + try { + openSamlObjects.init(); + } + catch (ComponentInitializationException e) { + throw new IllegalStateException(e); + } + ATTRIBUTE_UTILITY = new AttributeUtility(openSamlObjects); + + } + public static List getStringListOfAttributeValues(List attributeValues) { List stringAttributeValues = new ArrayList<>(); for (XMLObject attributeValue : attributeValues) { @@ -48,5 +65,104 @@ public static List getStringListValueOfAttribute(Attribute attribute) { return getStringListOfAttributeValues(attribute.getAttributeValues()); } + public static RelyingPartyOverridesRepresentation getRelyingPartyOverridesRepresentationFromAttributeList(List attributeList) { + RelyingPartyOverridesRepresentation relyingPartyOverridesRepresentation = new RelyingPartyOverridesRepresentation(); + for (org.opensaml.saml.saml2.core.Attribute attribute : attributeList) { + Attribute jpaAttribute = (Attribute) attribute; + // TODO: this is going to get real ugly real quick. clean it up, future Jj! + switch (jpaAttribute.getName()) { + case MDDCConstants.SIGN_ASSERTIONS: + relyingPartyOverridesRepresentation.setSignAssertion(getBooleanValueOfAttribute(jpaAttribute)); + break; + case MDDCConstants.SIGN_RESPONSES: + relyingPartyOverridesRepresentation.setDontSignResponse(!getBooleanValueOfAttribute(jpaAttribute)); + break; + case MDDCConstants.ENCRYPT_ASSERTIONS: + relyingPartyOverridesRepresentation.setTurnOffEncryption(!getBooleanValueOfAttribute(jpaAttribute)); + break; + case MDDCConstants.SECURITY_CONFIGURATION: + if (getStringListValueOfAttribute(jpaAttribute).contains("shibboleth.SecurityConfiguration.SHA1")) { + relyingPartyOverridesRepresentation.setUseSha(true); + } + break; + case MDDCConstants.DISALLOWED_FEATURES: + if ((Integer.decode(getStringListValueOfAttribute(jpaAttribute).get(0)) & 0x1) == 0x1) { + relyingPartyOverridesRepresentation.setIgnoreAuthenticationMethod(true); + } + break; + case MDDCConstants.INCLUDE_CONDITIONS_NOT_BEFORE: + relyingPartyOverridesRepresentation.setOmitNotBefore(!getBooleanValueOfAttribute(jpaAttribute)); + break; + case MDDCConstants.RESPONDER_ID: + relyingPartyOverridesRepresentation.setResponderId(getStringListValueOfAttribute(jpaAttribute).get(0)); + break; + case MDDCConstants.NAME_ID_FORMAT_PRECEDENCE: + relyingPartyOverridesRepresentation.setNameIdFormats(getStringListValueOfAttribute(jpaAttribute)); + break; + case MDDCConstants.DEFAULT_AUTHENTICATION_METHODS: + relyingPartyOverridesRepresentation.setAuthenticationMethods(getStringListValueOfAttribute(jpaAttribute)); + break; + default: + break; + } + } + + return relyingPartyOverridesRepresentation; + } + + public static List getAttributeListFromAttributeReleaseList(List attributeReleaseList) { + List attributeList = new ArrayList<>(); + + if (attributeReleaseList != null && attributeReleaseList.size() > 0) { + attributeList.add(ATTRIBUTE_UTILITY.createAttributeWithStringValues(MDDCConstants.RELEASE_ATTRIBUTES, attributeReleaseList)); + } + + return (List)(List)attributeList; + } + + public static List getAttributeListFromRelyingPartyOverridesRepresentation + (RelyingPartyOverridesRepresentation relyingPartyOverridesRepresentation) { + List list = new ArrayList<>(); + + if (relyingPartyOverridesRepresentation != null) { + if (relyingPartyOverridesRepresentation.isSignAssertion()) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithBooleanValue(MDDCConstants.SIGN_ASSERTIONS, MDDCConstants.SIGN_ASSERTIONS_FN, true)); + } + if (relyingPartyOverridesRepresentation.isDontSignResponse()) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithBooleanValue(MDDCConstants.SIGN_RESPONSES, MDDCConstants.SIGN_RESPONSES_FN, false)); + } + if (relyingPartyOverridesRepresentation.isTurnOffEncryption()) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithBooleanValue(MDDCConstants.ENCRYPT_ASSERTIONS, MDDCConstants.ENCRYPT_ASSERTIONS_FN, false)); + } + if (relyingPartyOverridesRepresentation.isUseSha()) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithArbitraryValues(MDDCConstants.SECURITY_CONFIGURATION, MDDCConstants + .SECURITY_CONFIGURATION_FN, "shibboleth.SecurityConfiguration.SHA1")); + } + if (relyingPartyOverridesRepresentation.isIgnoreAuthenticationMethod()) { + // this is actually going to be wrong, but it will work for the time being. this should be a bitmask value that we calculate + // TODO: fix + list.add(ATTRIBUTE_UTILITY.createAttributeWithArbitraryValues(MDDCConstants.DISALLOWED_FEATURES, MDDCConstants.DISALLOWED_FEATURES_FN, + "0x1")); + } + if (relyingPartyOverridesRepresentation.isOmitNotBefore()) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithBooleanValue(MDDCConstants.INCLUDE_CONDITIONS_NOT_BEFORE, MDDCConstants + .INCLUDE_CONDITIONS_NOT_BEFORE_FN, false)); + } + if (relyingPartyOverridesRepresentation.getResponderId() != null && !"".equals(relyingPartyOverridesRepresentation.getResponderId())) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithArbitraryValues(MDDCConstants.RESPONDER_ID, MDDCConstants.RESPONDER_ID_FN, + relyingPartyOverridesRepresentation.getResponderId())); + } + if (relyingPartyOverridesRepresentation.getNameIdFormats() != null && relyingPartyOverridesRepresentation.getNameIdFormats().size() > 0) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithArbitraryValues(MDDCConstants.NAME_ID_FORMAT_PRECEDENCE, MDDCConstants + .NAME_ID_FORMAT_PRECEDENCE_FN, relyingPartyOverridesRepresentation.getNameIdFormats())); + } + if (relyingPartyOverridesRepresentation.getAuthenticationMethods() != null && relyingPartyOverridesRepresentation.getAuthenticationMethods().size() > 0) { + list.add(ATTRIBUTE_UTILITY.createAttributeWithArbitraryValues(MDDCConstants.DEFAULT_AUTHENTICATION_METHODS, MDDCConstants + .DEFAULT_AUTHENTICATION_METHODS_FN, relyingPartyOverridesRepresentation.getAuthenticationMethods())); + } + } + + return (List) (List) list; + } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy index d554a1726..8e3b02a68 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/PolymorphicFiltersJacksonHandlingTests.groovy @@ -21,14 +21,10 @@ class PolymorphicFiltersJacksonHandlingTests extends Specification { mapper = new ObjectMapper() mapper.enable(SerializationFeature.INDENT_OUTPUT) - attributeUtility = new AttributeUtility().with { - it.openSamlObjects = new OpenSamlObjects().with { - it.init() - it - } + attributeUtility = new AttributeUtility(new OpenSamlObjects().with { + it.init() it - } - + }) testObjectGenerator = new TestObjectGenerator(attributeUtility) } @@ -81,4 +77,5 @@ class PolymorphicFiltersJacksonHandlingTests extends Specification { json } + } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy index b577042a6..7324ab23c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/MetadataResolverRepositoryTest.groovy @@ -9,6 +9,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityDescriptorServiceImpl import edu.internet2.tier.shibboleth.admin.ui.service.JPAEntityServiceImpl +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest @@ -34,10 +35,10 @@ class MetadataResolverRepositoryTest extends Specification { @Autowired EntityManager entityManager - OpenSamlObjects openSamlObjects = new OpenSamlObjects().with { - init() - it - } + @Autowired + OpenSamlObjects openSamlObjects + + AttributeUtility attributeUtility def service = new JPAEntityDescriptorServiceImpl(openSamlObjects, new JPAEntityServiceImpl(openSamlObjects)) @@ -90,4 +91,5 @@ class MetadataResolverRepositoryTest extends Specification { then: item1.hashCode() == item2.hashCode() } + }