/**
* Copyright (c) Codice Foundation
* <p/>
* This is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or any later version.
* <p/>
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. A copy of the GNU Lesser General Public License
* is distributed along with this program and can be found at
* <http://www.gnu.org/licenses/lgpl.html>.
*/
package ddf.catalog.security.filter.plugin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ddf.catalog.data.Attribute;
import ddf.catalog.data.Metacard;
import ddf.catalog.data.Result;
import ddf.catalog.operation.QueryResponse;
import ddf.catalog.plugin.PluginExecutionException;
import ddf.catalog.plugin.PostQueryPlugin;
import ddf.catalog.plugin.StopProcessingException;
import ddf.security.SecurityConstants;
import ddf.security.common.audit.SecurityLogger;
import ddf.security.permission.KeyValueCollectionPermission;
/**
* This {@link PostQueryPlugin} performs redaction and filtering on {@link QueryResponse} objects as
* they pass through the framework.
*
*/
public class FilterPlugin implements PostQueryPlugin {
private final Logger logger = LoggerFactory.getLogger(FilterPlugin.class);
/**
* Processes a {@link ddf.catalog.operation.QueryResponse} after the execution of the
* {@link ddf.catalog.operation.Query}.
*
* @param input
* the {@link ddf.catalog.operation.QueryResponse} to process
* @return the value of the processed {@link ddf.catalog.operation.QueryResponse} to pass to the
* next {@link ddf.catalog.plugin.PostQueryPlugin}, or if this is the last
* {@link ddf.catalog.plugin.PostQueryPlugin} to be called
* @throws ddf.catalog.plugin.PluginExecutionException
* thrown when an error occurs while processing the
* {@link ddf.catalog.operation.QueryResponse}
* @throws ddf.catalog.plugin.StopProcessingException
* thrown to halt processing when a critical issue occurs during processing. This is
* intended to prevent other plugins from processing as well.
*/
@Override
public QueryResponse process(QueryResponse input)
throws PluginExecutionException, StopProcessingException {
if (input.getRequest() == null || input.getRequest().getProperties() == null) {
throw new StopProcessingException(
"Unable to filter contents of current message, no user Subject available.");
}
Object securityAssertion = input.getRequest().getProperties()
.get(SecurityConstants.SECURITY_SUBJECT);
Subject subject;
if (securityAssertion instanceof Subject) {
subject = (Subject) securityAssertion;
logger.debug("Filter plugin found Subject for query response.");
} else {
throw new StopProcessingException(
"Unable to filter contents of current message, no user Subject available.");
}
List<Result> results = input.getResults();
List<Result> newResults = new ArrayList<Result>(results.size());
Metacard metacard;
KeyValueCollectionPermission securityPermission = new KeyValueCollectionPermission();
for (Result result : results) {
metacard = result.getMetacard();
Attribute attr = metacard.getAttribute(Metacard.SECURITY);
Map<String, List<String>> map = null;
if (null != attr) {
map = (Map<String, List<String>>) attr.getValue();
}
securityPermission.clear();
if (map != null) {
securityPermission.addAll(map);
}
if (!subject.isPermitted(securityPermission)) {
logger.debug("Filtering metacard {}", metacard.getId());
SecurityLogger.logInfo("Filtering metacard " + metacard.getId());
} else {
SecurityLogger.logInfo("Allowing metacard " + metacard.getId());
newResults.add(result);
}
}
input.getResults().clear();
input.getResults().addAll(newResults);
newResults.clear();
newResults = null;
return input;
}
}