/******************************************************************************* * Copyright 2017 Graz University of Technology * EAAF-Core Components has been developed in a cooperation between EGIZ, * A-SIT+, 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 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; 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; /** * @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(boolean isUsed) { this.isUsed = isUsed; } /* (non-Javadoc) * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) */ @Override public void doFilter(XMLObject metadata) throws FilterException { if (isUsed) { log.trace("Map PVP EntityCategory to single PVP Attributes ... "); String entityId = null; try { if (metadata instanceof EntitiesDescriptor) { log.trace("Find EnitiesDescriptor ... "); EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata; if (entitiesDesc.getEntityDescriptors() != null) { for (EntityDescriptor el : entitiesDesc.getEntityDescriptors()) resolveEntityCategoriesToAttributes(el); } } else if (metadata instanceof EntityDescriptor) { log.trace("Find EntityDescriptor"); resolveEntityCategoriesToAttributes((EntityDescriptor)metadata); } else throw new PVP2MetadataException("Invalid Metadata file Root element is no Entities- or EntityDescriptor", null); } catch (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(EntityDescriptor metadata) { log.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ..."); Extensions extensions = metadata.getExtensions(); if (extensions != null) { List listOfExt = extensions.getUnknownXMLObjects(); if (listOfExt != null && !listOfExt.isEmpty()) { log.trace("Find #" + listOfExt.size() + " 'Extension' elements "); for (XMLObject el : listOfExt) { log.trace("Find ExtensionElement: " + el.getElementQName().toString()); if (el instanceof EntityAttributes) { EntityAttributes entityAttrElem = (EntityAttributes)el; if (entityAttrElem.getAttributes() != null) { log.trace("Find EntityAttributes. Start attribute processing ..."); for (Attribute entityAttr : entityAttrElem.getAttributes()) { if (entityAttr.getName().equals(PVPConstants.ENTITY_CATEGORY_ATTRIBITE)) { if (!entityAttr.getAttributeValues().isEmpty()) { 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"); } /** * @param metadata * @param attrList */ private void addAttributesToEntityDescriptor(EntityDescriptor metadata, List attrList, String entityAttr) { SPSSODescriptor spSSODesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); if (spSSODesc != null) { if (spSSODesc.getAttributeConsumingServices() == null || spSSODesc.getAttributeConsumingServices().isEmpty()) { log.trace("No 'AttributeConsumingServices' found. Added it ..."); AttributeConsumingService attributeService = SAML2Utils.createSAMLObject(AttributeConsumingService.class); attributeService.setIndex(0); attributeService.setIsDefault(true); 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 (AttributeConsumingService el : spSSODesc.getAttributeConsumingServices()) { log.debug("Update 'AttributeConsumingService' with Index: " + el.getIndex()); //load currently requested attributes List currentlyReqAttr = new ArrayList(); for (RequestedAttribute reqAttr : el.getRequestAttributes()) currentlyReqAttr.add(reqAttr.getName()); //check against EntityAttribute List for (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(List> attrSet) { List requestedAttributes = new ArrayList(); for (Trible el : attrSet) requestedAttributes.add(PVPAttributeBuilder.buildReqAttribute(el.getFirst(), el.getSecond(), el.getThird())); return requestedAttributes; } }