From 759ac5f42c6aff901dbeede4fbf1a1d2e08cad0f Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Wed, 4 Dec 2019 19:43:32 +0100 Subject: common EGIZ code-style refactoring --- .../metadata/PvpEntityCategoryFilter.java | 251 +++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java (limited to 'eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java') diff --git a/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java new file mode 100644 index 00000000..2d81b1f8 --- /dev/null +++ b/eaaf_modules/eaaf_module_pvp2_core/src/main/java/at/gv/egiz/eaaf/modules/pvp2/impl/validation/metadata/PvpEntityCategoryFilter.java @@ -0,0 +1,251 @@ +/* + * Copyright 2017 Graz University of Technology EAAF-Core Components has been developed in a + * cooperation between EGIZ, A-SIT Plus, A-SIT, and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European + * Commission - subsequent versions of the EUPL (the "Licence"); You may not use this work except in + * compliance with the Licence. You may obtain a copy of the Licence at: + * https://joinup.ec.europa.eu/news/understanding-eupl-v12 + * + * Unless required by applicable law or agreed to in writing, software distributed under the Licence + * is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the Licence for the specific language governing permissions and limitations under + * the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text file for details on the + * various modules and licenses. The "NOTICE" text file is part of the distribution. Any derivative + * works that you distribute must include a readable copy of the "NOTICE" text file. +*/ + +package at.gv.egiz.eaaf.modules.pvp2.impl.validation.metadata; + +import java.util.ArrayList; +import java.util.List; +import at.gv.egiz.eaaf.core.impl.data.Trible; +import at.gv.egiz.eaaf.modules.pvp2.PvpConstants; +import at.gv.egiz.eaaf.modules.pvp2.exception.Pvp2MetadataException; +import at.gv.egiz.eaaf.modules.pvp2.impl.builder.PvpAttributeBuilder; +import at.gv.egiz.eaaf.modules.pvp2.impl.utils.Saml2Utils; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.common.Extensions; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.metadata.AttributeConsumingService; +import org.opensaml.saml2.metadata.EntitiesDescriptor; +import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.LocalizedString; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.saml2.metadata.SPSSODescriptor; +import org.opensaml.saml2.metadata.ServiceName; +import org.opensaml.saml2.metadata.provider.FilterException; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.samlext.saml2mdattr.EntityAttributes; +import org.opensaml.xml.XMLObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Metadata filter that inject requested attributes based on Metadata EntityCategories. + * + * @author tlenz + * + */ +public class PvpEntityCategoryFilter implements MetadataFilter { + private static final Logger log = LoggerFactory.getLogger(PvpEntityCategoryFilter.class); + + private boolean isUsed = false; + + /** + * Filter to map PVP EntityCategories into a set of single PVP attributes. + * + * @param isUsed if true PVP EntityCategories are mapped, otherwise they are ignored + * + */ + public PvpEntityCategoryFilter(final boolean isUsed) { + this.isUsed = isUsed; + } + + + /* + * (non-Javadoc) + * + * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) + */ + @Override + public void doFilter(final XMLObject metadata) throws FilterException { + + if (isUsed) { + log.trace("Map PVP EntityCategory to single PVP Attributes ... "); + final String entityId = null; + try { + if (metadata instanceof EntitiesDescriptor) { + log.trace("Find EnitiesDescriptor ... "); + final EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata; + if (entitiesDesc.getEntityDescriptors() != null) { + for (final EntityDescriptor el : entitiesDesc.getEntityDescriptors()) { + resolveEntityCategoriesToAttributes(el); + } + + } + + } else if (metadata instanceof EntityDescriptor) { + log.trace("Find EntityDescriptor"); + resolveEntityCategoriesToAttributes((EntityDescriptor) metadata); + + + } else { + throw new Pvp2MetadataException("pvp2.26", new Object[] { + "Invalid Metadata file Root element is no Entities- or EntityDescriptor"}); + } + + + + } catch (final Exception e) { + log.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: " + + entityId, e); + + } + + } else { + log.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated"); + } + + } + + private void resolveEntityCategoriesToAttributes(final EntityDescriptor metadata) { + log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ..."); + final Extensions extensions = metadata.getExtensions(); + if (extensions != null) { + final List listOfExt = extensions.getUnknownXMLObjects(); + if (listOfExt != null && !listOfExt.isEmpty()) { + log.trace("Find #" + listOfExt.size() + " 'Extension' elements "); + for (final XMLObject el : listOfExt) { + log.trace("Find ExtensionElement: " + el.getElementQName().toString()); + if (el instanceof EntityAttributes) { + final EntityAttributes entityAttrElem = (EntityAttributes) el; + if (entityAttrElem.getAttributes() != null) { + log.trace("Find EntityAttributes. Start attribute processing ..."); + for (final Attribute entityAttr : entityAttrElem.getAttributes()) { + if (entityAttr.getName().equals(PvpConstants.ENTITY_CATEGORY_ATTRIBITE)) { + if (!entityAttr.getAttributeValues().isEmpty()) { + final String entityAttrValue = + entityAttr.getAttributeValues().get(0).getDOM().getTextContent(); + if (PvpConstants.EGOVTOKEN.equals(entityAttrValue)) { + log.debug( + "Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... "); + addAttributesToEntityDescriptor(metadata, + buildAttributeList(PvpConstants.EGOVTOKEN_PVP_ATTRIBUTES), + entityAttrValue); + + + } else if (PvpConstants.CITIZENTOKEN.equals(entityAttrValue)) { + log.debug( + "Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... "); + addAttributesToEntityDescriptor(metadata, + buildAttributeList(PvpConstants.CITIZENTOKEN_PVP_ATTRIBUTES), + entityAttrValue); + + } else { + log.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!"); + } + + } else { + log.info("EntityAttribute: No attribute value"); + } + + } else { + log.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported"); + } + + } + + } else { + log.info( + "Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!"); + } + + } + } + + } else { + log.trace("'Extension' element is 'null' or empty"); + } + + } else { + log.trace("No 'Extension' element found"); + } + + } + + + private void addAttributesToEntityDescriptor(final EntityDescriptor metadata, + final List attrList, final String entityAttr) { + final SPSSODescriptor spSsoDesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); + if (spSsoDesc != null) { + if (spSsoDesc.getAttributeConsumingServices() == null + || spSsoDesc.getAttributeConsumingServices().isEmpty()) { + log.trace("No 'AttributeConsumingServices' found. Added it ..."); + + final AttributeConsumingService attributeService = + Saml2Utils.createSamlObject(AttributeConsumingService.class); + attributeService.setIndex(0); + attributeService.setIsDefault(true); + final ServiceName serviceName = Saml2Utils.createSamlObject(ServiceName.class); + serviceName.setName(new LocalizedString("Default Service", "en")); + attributeService.getNames().add(serviceName); + + if (attrList != null && !attrList.isEmpty()) { + attributeService.getRequestAttributes().addAll(attrList); + log.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr); + + } + + spSsoDesc.getAttributeConsumingServices().add(attributeService); + + } else { + log.debug("Find 'AttributeConsumingServices'. Starting updating process ... "); + for (final AttributeConsumingService el : spSsoDesc.getAttributeConsumingServices()) { + log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex()); + + // load currently requested attributes + final List currentlyReqAttr = new ArrayList<>(); + for (final RequestedAttribute reqAttr : el.getRequestAttributes()) { + currentlyReqAttr.add(reqAttr.getName()); + } + + + // check against EntityAttribute List + for (final RequestedAttribute entityAttrListEl : attrList) { + if (!currentlyReqAttr.contains(entityAttrListEl.getName())) { + el.getRequestAttributes().add(entityAttrListEl); + + } else { + log.debug("'AttributeConsumingService' already contains attr: " + + entityAttrListEl.getName()); + } + + } + + } + + } + + } else { + log.info("Can ONLY add 'EntityAttributes' to 'SPSSODescriptor'"); + } + + } + + private List buildAttributeList( + final List> attrSet) { + final List requestedAttributes = new ArrayList<>(); + for (final Trible el : attrSet) { + requestedAttributes + .add(PvpAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird())); + } + + return requestedAttributes; + + + } + +} -- cgit v1.2.3