/** * 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 org.codice.ddf.catalog.security; import static ddf.catalog.Constants.OPERATION_TRANSACTION_KEY; import java.io.Serializable; import java.net.URI; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ddf.catalog.data.Metacard; import ddf.catalog.data.Result; import ddf.catalog.operation.OperationTransaction; import ddf.catalog.operation.Query; import ddf.catalog.operation.ResourceRequest; import ddf.catalog.operation.ResourceResponse; import ddf.catalog.plugin.PolicyPlugin; import ddf.catalog.plugin.PolicyResponse; import ddf.catalog.plugin.StopProcessingException; import ddf.catalog.plugin.impl.PolicyResponseImpl; import ddf.catalog.util.impl.Requests; import ddf.security.permission.Permissions; /** * Restricts how resource URIs are updated and created. * There are security risk to allowing users to update URIs as well as allowing users to * pass in a URI when the metacard is created. */ public class ResourceUriPolicy implements PolicyPlugin { private static final Logger LOGGER = LoggerFactory.getLogger(ResourceUriPolicy.class); private String[] createPermissions; private String[] updatePermissions; public ResourceUriPolicy() { } public ResourceUriPolicy(String[] createPermissions, String[] updatePermissions) { setCreatePermissions(createPermissions); setUpdatePermissions(updatePermissions); } @Override public PolicyResponse processPreCreate(Metacard input, Map<String, Serializable> properties) throws StopProcessingException { if (!Requests.isLocal(properties)) { return new PolicyResponseImpl(); } if (input.getResourceURI() != null && StringUtils.isNotEmpty(input.getResourceURI() .toString())) { return new PolicyResponseImpl(null, Permissions.parsePermissionsFromString(getCreatePermissions())); } return new PolicyResponseImpl(); } @Override public PolicyResponse processPreUpdate(Metacard input, Map<String, Serializable> properties) throws StopProcessingException { if (!Requests.isLocal(properties)) { return new PolicyResponseImpl(); } PolicyResponseImpl policyResponse = new PolicyResponseImpl(null, Permissions.parsePermissionsFromString(getUpdatePermissions())); List<Metacard> previousStateMetacards = ((OperationTransaction) properties.get( OPERATION_TRANSACTION_KEY)).getPreviousStateMetacards(); Metacard previous; try { previous = previousStateMetacards.stream() .filter((x) -> x.getId() .equals(input.getId())) .findFirst() .get(); } catch (NoSuchElementException e) { LOGGER.debug("Cannot locate metacard {} for update. Applying permissions to the item", input.getId()); return policyResponse; } return requiresPermission(input.getResourceURI(), previous.getResourceURI()) ? policyResponse : new PolicyResponseImpl(); } private boolean requiresPermission(URI input, URI catalog) { return !uriToString(input).equals(uriToString(catalog)); } private String uriToString(URI uri) { return uri == null ? "" : uri.toString(); } @Override public PolicyResponse processPreDelete(List<Metacard> metacards, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostDelete(Metacard input, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPreQuery(Query query, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostQuery(Result input, Map<String, Serializable> properties) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPreResource(ResourceRequest resourceRequest) throws StopProcessingException { return new PolicyResponseImpl(); } @Override public PolicyResponse processPostResource(ResourceResponse resourceResponse, Metacard metacard) throws StopProcessingException { return new PolicyResponseImpl(); } public String[] getCreatePermissions() { return createPermissions == null ? null : createPermissions.clone(); } public void setCreatePermissions(String[] createPermissions) { this.createPermissions = createPermissions == null ? null : createPermissions.clone(); } public String[] getUpdatePermissions() { return updatePermissions == null ? null : updatePermissions.clone(); } public void setUpdatePermissions(String[] updatePermissions) { this.updatePermissions = updatePermissions == null ? null : updatePermissions.clone(); } }