View Javadoc

    1   /*
    2    * Copyright 2008 University Corporation for Advanced Internet Development, Inc.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    * http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16
    17  package edu.internet2.middleware.shibboleth.wayf.plugins.provider;
    18
    19  import java.util.Collection;
    20  import java.util.HashSet;
    21  import java.util.Iterator;
    22  import java.util.List;
    23  import java.util.Set;
    24
    25  import org.opensaml.saml2.metadata.EntitiesDescriptor;
    26  import org.opensaml.saml2.metadata.EntityDescriptor;
    27  import org.opensaml.saml2.metadata.provider.FilterException;
    28  import org.opensaml.saml2.metadata.provider.MetadataFilter;
    29  import org.opensaml.xml.XMLObject;
    30  import org.slf4j.Logger;
    31  import org.slf4j.LoggerFactory;
    32  import org.w3c.dom.Element;
    33  import org.w3c.dom.NodeList;
    34
    35  import edu.internet2.middleware.shibboleth.wayf.XMLConstants;
    36
    37  /**
    38   * See SDSJ-57.  Explicit
    39   *
    40   * @author Rod Widdowson
    41   *
    42   */
    43  public class ListFilter implements MetadataFilter {
    44
    45      /**
    46       * Log for any messages.
    47       */
    48      private static final Logger LOG = LoggerFactory.getLogger(ListFilter.class.getName());
    49
    50      /**
    51       * Set if this is a blacklist.
    52       */
    53      private boolean excludeEntries;
    54
    55      /**
    56       * The list of entities.
    57       */
    58      private final Set<String> filterEntities;
    59
    60      /**
    61       * The name of the filter (needed for debug).
    62       */
    63      private final String filterName;
    64
    65      /**
    66       * Only the protected constructor should be visible.
    67       */
    68      private ListFilter() {
    69          this.excludeEntries = false;
    70          this.filterEntities = new HashSet<String>(0);
    71          this.filterName = "anonymous";
    72      }
    73
    74      /**
    75       * Initialize the filter.
    76       * @param config the configuration
    77       *
    78       * The configuration looks liken this
    79       * <code> <Filter identifier="WhiteList"
    80       *                type ="edu.internet2.middleware.shibboleth.wayf.plugins.provider.ListFilter"
    81       *                excludeEntries = "true" >
    82       *        <EntityId>foo</EntityId>
    83       *        [...]
    84       *        </Filter>
    85       *  </code>
    86       */
    87      public ListFilter(Element config) {
    88          String excludeEntriesValue;
    89          this.filterEntities = new HashSet<String>(10);
    90          this.filterName = config.getAttribute("identifier");
    91          excludeEntriesValue = config.getAttribute("excludeEntries");
    92
    93          if (null == excludeEntriesValue || 0 == excludeEntriesValue.length()) {
    94              this.excludeEntries = true;
    95          } else {
    96              this.excludeEntries = Boolean.parseBoolean(excludeEntriesValue);
    97          }
    98
    99          NodeList itemElements = config.getElementsByTagNameNS(XMLConstants.CONFIG_NS, "EntityId");
    100
    101         if (excludeEntries) {
    102             LOG.debug("Populating blacklist " + filterName);
    103         } else {
    104             LOG.debug("Populating whitelist " + filterName);
    105         }
    106
    107         for (int i = 0; i < itemElements.getLength(); i++) {
    108             Element element = (Element) itemElements.item(i);
    109             String entityId = element.getTextContent();
    110
    111             LOG.debug("\t" + entityId);
    112             this.filterEntities.add(entityId);
    113         }
    114     }
    115
    116     /**
    117      * Apply the filter.
    118      * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject)
    119      * @param metadata what to filter.
    120      * @throws FilterException if it sees any missed or bad bindings.
    121      */
    122     public void doFilter(XMLObject metadata) throws FilterException {
    123
    124         if (metadata instanceof EntitiesDescriptor) {
    125             filterEntities((EntitiesDescriptor)metadata);
    126         } else if (metadata instanceof EntityDescriptor) {
    127             EntityDescriptor entity = (EntityDescriptor) metadata;
    128             String entityName = entity.getEntityID();
    129
    130             if (excludeEntries) {
    131                 if (filterEntities.contains(entityName)) {
    132                     LOG.error("Metadata provider contains a single <EntityDescriptor> (" + entityName +
    133                               ") which is in exclude list");
    134                 }
    135             } else if (!filterEntities.contains(entity.getEntityID())) {
    136                 LOG.error("Metadata provider contains a single <EntityDescriptor>  (" + entityName +
    137                           ") which is not on include list");
    138             }
    139         }
    140     }
    141
    142     /**
    143      * Filter an EntitiesDescriptor .  We do this explictly for the Entities and call ourselves
    144      *  recursively for the EntitesDescriptors.
    145      *
    146      * @param entities what to check.
    147      */
    148     private void filterEntities(EntitiesDescriptor entities) {
    149         String entitiesName = entities.getName();
    150         List<EntitiesDescriptor> childEntities = entities.getEntitiesDescriptors();
    151         List<EntityDescriptor> children = entities.getEntityDescriptors();
    152         Collection<EntityDescriptor> excludes = new HashSet<EntityDescriptor>();
    153
    154         //
    155         // Go through and apply the filter
    156         //
    157
    158         if (children != null) {
    159             Iterator<EntityDescriptor> itr;
    160             EntityDescriptor entity;
    161             itr = children.iterator();
    162
    163             while (itr.hasNext()) {
    164                 entity = itr.next();
    165                 String entityName = entity.getEntityID();
    166                 if (excludeEntries) {
    167
    168                     if (filterEntities.contains(entityName)) {
    169                         LOG.debug("Filter " + filterName + ": Removing blacklisted "
    170                                 + entityName + " from " + entitiesName);
    171                         excludes.add(entity);
    172                     }
    173                 } else if (!filterEntities.contains(entityName)) {
    174                     LOG.debug("Filter " + filterName + ": Removing non-whitelisted "
    175                             + entityName + " from " + entitiesName);
    176
    177                     excludes.add(entity);
    178                 }
    179             }
    180             children.removeAll(excludes);
    181         }
    182
    183         if (childEntities != null) {
    184             for (EntitiesDescriptor descriptor : childEntities) {
    185                 filterEntities(descriptor);
    186             }
    187         }
    188     }
    189 }