/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wps.security; import static org.geoserver.security.impl.DataAccessRule.ANY; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.logging.Logger; import org.geoserver.config.ConfigurationListenerAdapter; import org.geoserver.config.GeoServer; import org.geoserver.config.ServiceInfo; import org.geoserver.security.AccessMode; import org.geoserver.security.CatalogMode; import org.geoserver.security.impl.SecureTreeNode; import org.geoserver.wps.ProcessGroupInfo; import org.geoserver.wps.ProcessInfo; import org.geoserver.wps.WPSInfo; import org.geoserver.wps.process.GeoServerProcessors; import org.geotools.process.ProcessFactory; import org.geotools.util.logging.Logging; import org.opengis.feature.type.Name; /** * Allows to manage the rules used by the WPS security subsystem * */ public class WpsAccessRuleDAO extends ConfigurationListenerAdapter { private static final Logger LOGGER = Logging.getLogger(WpsAccessRuleDAO.class); /** * property file name */ static final String WPS_PROP_FILE = "wps.xml"; private GeoServer gs; /** * Default to the highest security mode */ CatalogMode catalogMode = CatalogMode.HIDE; List<WpsAccessRule> rules; private SecureTreeNode root; public WpsAccessRuleDAO(GeoServer gs) throws IOException { this.gs = gs; gs.addListener(this); } public CatalogMode getMode() { if (root == null) { loadRules(); } return catalogMode; } public SecureTreeNode getSecurityTreeRoot() { if (root == null) { loadRules(); } return root; } /* * Loads rules from in memory WPSInfo and builds the WPS access rules tree */ protected void loadRules() { WPSInfo wps = this.gs.getService(WPSInfo.class); TreeSet<WpsAccessRule> result = new TreeSet<WpsAccessRule>(); if (wps != null) { catalogMode = CatalogMode.HIDE; if (wps.getCatalogMode() != null) { catalogMode = wps.getCatalogMode(); } for (ProcessGroupInfo group : wps.getProcessGroups()) { Set<String> prefixes = new HashSet<String>(); ProcessFactory pf = GeoServerProcessors.getProcessFactory(group.getFactoryClass(), false); if (pf != null) { Set<Name> names = pf.getNames(); for (Name name : names) { prefixes.add(name.getNamespaceURI()); } } for (String prefix : prefixes) { if (group.getRoles() != null && !group.getRoles().isEmpty()) { result.add(new WpsAccessRule(prefix, ANY, new HashSet<String>(group .getRoles()))); } } for (ProcessInfo process : group.getFilteredProcesses()) { if (process.getRoles() != null && !process.getRoles().isEmpty()) { result.add(new WpsAccessRule(process.getName().getNamespaceURI(), process .getName().getLocalPart(), new HashSet<String>(process.getRoles()))); } } } } // make sure the single basic rules if the set is empty if (result.size() == 0) { result.add(new WpsAccessRule(WpsAccessRule.EXECUTE_ALL)); } root = buildAuthorizationTree(result); } private SecureTreeNode buildAuthorizationTree(Collection<WpsAccessRule> rules) { SecureTreeNode root = new SecureTreeNode(); for (WpsAccessRule rule : rules) { String group = rule.getGroupName(); String name = rule.getWpsName(); // look for the node where the rules will have to be set SecureTreeNode node; // check for the * group definition if (ANY.equals(group)) { node = root; } else { // get or create the group SecureTreeNode ws = root.getChild(group); if (ws == null) { ws = root.addChild(group); } // if WPS is "*" the rule applies to the group, otherwise // get/create the WPS if ("*".equals(name)) { node = ws; } else { SecureTreeNode layerNode = ws.getChild(name); if (layerNode == null) layerNode = ws.addChild(name); node = layerNode; } } // actually set the rule, but don't complain for the default root contents if (node != root) { LOGGER.warning("Rule " + rule + " is overriding another rule targetting the same resource"); } node.setAuthorizedRoles(AccessMode.READ, rule.getRoles()); node.setAuthorizedRoles(AccessMode.WRITE, Collections.singleton("NO_ONE")); node.setAuthorizedRoles(AccessMode.ADMIN, Collections.singleton("NO_ONE")); } root.setAuthorizedRoles(AccessMode.READ, Collections.singleton("*")); root.setAuthorizedRoles(AccessMode.WRITE, Collections.singleton("NO_ONE")); root.setAuthorizedRoles(AccessMode.ADMIN, Collections.singleton("NO_ONE")); return root; } @Override public void reloaded() { this.root = null; } @Override public void handlePostServiceChange(ServiceInfo service) { if (service instanceof WPSInfo) { this.root = null; } } }