/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.audit; import org.candlepin.audit.Event.Target; import org.candlepin.audit.Event.Type; import org.candlepin.common.config.Configuration; import org.candlepin.config.ConfigProperties; import com.google.inject.Inject; import java.util.HashSet; import java.util.List; import java.util.Set; /** * This class is used to filter audit events so that they cannot enter * HornetQ queues. * This functionality is introduced as a hack to limit number of * audited events. Many users of Candlepin reported high memory usage * and crashes. Those issues were challenging to reproduce and * we believe the root cause is overload of our auditing system. * This filter is used as a tool to confirm that suspicion on * running systems. * * This feature is implicitly disabled, use ConfigProperties.AUDIT_FILTER_ENABLED * to enable it. * * @author fnguyen */ public class EventFilter { private FilterPolicy defaultFilterPolicy; /** * DO_FILTER - in case inclusion and exclusion doesn't contain the event, then * the event will be filtered * DO_NOT_FILTER - the event will not be filtered * @author fnguyen * */ public enum FilterPolicy { DO_FILTER, DO_NOT_FILTER } /** * Events that must not be filtered. */ private Set<EventTypeAndTarget> toNotFilter = new HashSet<EventTypeAndTarget>(); /** * Events that must be filtered. */ private Set<EventTypeAndTarget> toFilter = new HashSet<EventTypeAndTarget>(); private Configuration config; @Inject public EventFilter(Configuration config) { this.config = config; String policyString = config.getString(ConfigProperties.AUDIT_FILTER_DEFAULT_POLICY); try { defaultFilterPolicy = Enum.valueOf(FilterPolicy.class, policyString.trim()); } catch (Exception ex) { throw new IllegalArgumentException("Unknown default policy settings: " + policyString); } List<String> toNotFilterConfig = config.getList(ConfigProperties.AUDIT_FILTER_DO_NOT_FILTER); List<String> toFilterConfig = config.getList(ConfigProperties.AUDIT_FILTER_DO_FILTER); fillEventTypeAndTargetFromConfig(toNotFilter, toNotFilterConfig); fillEventTypeAndTargetFromConfig(toFilter, toFilterConfig); } /** * Parses the toupes type-target from the config file. * * @param includes2 * @param includesConfig */ private void fillEventTypeAndTargetFromConfig(Set<EventTypeAndTarget> set, List<String> stringList) { for (String item : stringList) { if (item.trim().equals("")) { continue; } String[] split = item.split("-"); if (split.length != 2) { throw new IllegalArgumentException("Invalid include/exclude rule: " + item + "Each filter auditing" + "include/exclude must be in format TYPE-TARGET. For example MODIFIED-CONSUMER."); } try { Type type = Enum.valueOf(Type.class, split[0].trim()); Target target = Enum.valueOf(Target.class, split[1].trim()); set.add(new EventTypeAndTarget(type, target)); } catch (Exception ex) { throw new IllegalArgumentException("Invalid filtering tuple: " + item + " . Please use only enum values of Type and Target enums, e.g. MODIFIED-CONSUMER"); } } } public boolean shouldFilter(Event event) { boolean enabled = config.getBoolean(ConfigProperties.AUDIT_FILTER_ENABLED); if (!enabled) { return false; } EventTypeAndTarget eventKey = new EventTypeAndTarget(event.getType(), event.getTarget()); if (toNotFilter.contains(eventKey)) { return false; } if (toFilter.contains(eventKey)) { return true; } if (defaultFilterPolicy == FilterPolicy.DO_FILTER) { return true; } else if (defaultFilterPolicy == FilterPolicy.DO_NOT_FILTER) { return false; } else { throw new IllegalArgumentException("Unknown default filtering policy: " + defaultFilterPolicy); } } private static class EventTypeAndTarget { private Type type; private Target target; EventTypeAndTarget(Type type, Target target) { super(); this.type = type; this.target = target; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((target == null) ? 0 : target.hashCode()); result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } EventTypeAndTarget other = (EventTypeAndTarget) obj; if (target == null) { if (other.target != null) { return false; } } else if (!target.equals(other.target)) { return false; } if (type == null) { if (other.type != null) { return false; } } else if (!type.equals(other.type)) { return false; } return true; } } }