/* * Copyright 2014 Federal Chancellery Austria * MOA-ID has been developed in a cooperation between BRZ, the Federal * Chancellery Austria - ICT staff unit, and Graz University of Technology. * * Licensed under the EUPL, Version 1.1 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: * http://www.osor.eu/eupl/ * * 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.egovernment.moa.id.protocols.pvp2x.verification.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 at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; import at.gv.egovernment.moa.id.data.Trible; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.protocols.pvp2x.builder.PVPAttributeBuilder; import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; import at.gv.egovernment.moaspss.logging.Logger; /** * @author tlenz * */ public class PVPEntityCategoryFilter implements MetadataFilter { 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) { Logger.trace("Map PVP EntityCategory to single PVP Attributes ... "); String entityId = null; try { if (metadata instanceof EntitiesDescriptor) { Logger.trace("Find EnitiesDescriptor ... "); EntitiesDescriptor entitiesDesc = (EntitiesDescriptor) metadata; if (entitiesDesc.getEntityDescriptors() != null) { for (EntityDescriptor el : entitiesDesc.getEntityDescriptors()) resolveEntityCategoriesToAttributes(el); } } else if (metadata instanceof EntityDescriptor) { Logger.trace("Find EntityDescriptor"); resolveEntityCategoriesToAttributes((EntityDescriptor)metadata); } else throw new MOAIDException("Invalid Metadata file Root element is no Entities- or EntityDescriptor", null); } catch (Exception e) { Logger.warn("SAML2 Metadata processing FAILED: Can not resolve EntityCategories for metadata: " + entityId, e); } } else Logger.trace("Filter to map PVP EntityCategory to single PVP Attributes is deactivated"); } private void resolveEntityCategoriesToAttributes(EntityDescriptor metadata) { Logger.debug("Resolving EntityCategorie for Entity: " + metadata.getEntityID() + " ..."); Extensions extensions = metadata.getExtensions(); if (extensions != null) { List listOfExt = extensions.getUnknownXMLObjects(); if (listOfExt != null && !listOfExt.isEmpty()) { for (XMLObject el : listOfExt) { Logger.trace("Find ExtensionElement: " + el.getElementQName().toString()); if (el instanceof EntityAttributes) { EntityAttributes entityAttrElem = (EntityAttributes)el; if (entityAttrElem.getAttributes() != null) { Logger.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)) { Logger.debug("Find 'EGOVTOKEN' EntityAttribute. Adding single pvp attributes ... "); addAttributesToEntityDescriptor(metadata, buildAttributeList(PVPConstants.EGOVTOKEN_PVP_ATTRIBUTES), entityAttrValue); } else if (PVPConstants.CITIZENTOKEN.equals(entityAttrValue)) { Logger.debug("Find 'CITIZENTOKEN' EntityAttribute. Adding single pvp attributes ... "); addAttributesToEntityDescriptor(metadata, buildAttributeList(PVPConstants.CITIZENTOKEN_PVP_ATTRIBUTES), entityAttrValue); } else Logger.info("EntityAttributeValue: " + entityAttrValue + " is UNKNOWN!"); } else Logger.info("EntityAttribute: No attribute value"); } else Logger.info("EntityAttribute: " + entityAttr.getName() + " is NOT supported"); } } else Logger.info("Can NOT resolve EntityAttributes! Reason: Only EntityAttributes are supported!"); } } } } } /** * @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()) { Logger.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); Logger.info("Add " + attrList.size() + " attributes for 'EntityAttribute': " + entityAttr); } spSSODesc.getAttributeConsumingServices().add(attributeService); } else { Logger.debug("Find 'AttributeConsumingServices'. Starting updating process ... "); for (AttributeConsumingService el : spSSODesc.getAttributeConsumingServices()) { Logger.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 Logger.debug("'AttributeConsumingService' already contains attr: " + entityAttrListEl.getName()); } } } } else Logger.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; } }