package codeine.servlets.api_servlets.angular; import codeine.ConfigurationManagerServer; import codeine.jsons.collectors.CollectorInfo; import codeine.jsons.command.CommandInfo; import codeine.jsons.project.ProjectJson; import codeine.model.Constants; import codeine.permissions.IUserWithPermissions; import codeine.permissions.UserPermissionsGetter; import codeine.plugins.AfterProjectModifyPlugin; import codeine.plugins.AfterProjectModifyPlugin.StatusChange; import codeine.servlet.AbstractApiServlet; import codeine.utils.JsonUtils; import codeine.utils.MiscUtils; import codeine.utils.StringUtils; import codeine.utils.exceptions.UnAuthorizedException; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.apache.log4j.Logger; import javax.inject.Inject; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; public class ProjectConfigurationApiServlet extends AbstractApiServlet { private static final Logger log = Logger.getLogger(ProjectConfigurationApiServlet.class); private static final long serialVersionUID = 1L; @Inject private ConfigurationManagerServer configurationManager; @Inject private UserPermissionsGetter permissionsManager; @Inject private AfterProjectModifyPlugin afterProjectModifyPlugin; @Override protected boolean checkPermissions(HttpServletRequest request) { if (request.getMethod().equals("DELETE")) { return permissionsManager.user(request).isAdministrator(); } if (request.getMethod().equals("PUT")) { return canConfigureProject(request); } if (request.getMethod().equals("POST")) { return canConfigureProject(request); } return canReadProject(request); } @Override protected void myGet(HttpServletRequest request, HttpServletResponse response) { writeResponseJson(response, configurationManager.getProjectForName(getParameter(request, Constants.UrlParameters.PROJECT_NAME))); } @Override protected void myPut(HttpServletRequest request, HttpServletResponse resp) { ProjectJson projectJson = readBodyJson(request, ProjectJson.class); log.info("Updating configuration of " + projectJson.name() + ", new configuration is " + projectJson); ProjectJson currentProject = configurationManager.getProjectForName(projectJson.name()); if (null != currentProject && !isAdministrator(request) && (!MiscUtils.equals(currentProject.nodes_discovery_script(), projectJson.nodes_discovery_script()) || !MiscUtils.equals(currentProject.node_discovery_startegy(), projectJson.node_discovery_startegy()))) { log.warn("user tried to change discovery script in " + projectJson.name() + " user " + getUser(request).user().username()); throw new RuntimeException("only admin can change discovery script"); } if (null != currentProject && !isAdministrator(request) && !checkForRootPermissions(projectJson, currentProject)) { log.warn("user tried to change command or collector in " + projectJson.name() + " user " + getUser(request).user().username() + " to run as root"); throw new RuntimeException("only admin can set commands and collectors to run as root"); } boolean exists = configurationManager.updateProject(projectJson); afterProjectModifyPlugin.call(projectJson, exists ? StatusChange.modify : StatusChange.add, getUser(request).user().username()); writeResponseJson(resp,projectJson); } @Override protected void myDelete(HttpServletRequest request, HttpServletResponse response) { log.info("got delete request"); IUserWithPermissions user = permissionsManager.user(request); String projectName = getParameter(request, Constants.UrlParameters.PROJECT_NAME); log.info("project " + projectName + " user " + user.user().username()); ProjectJson projectToDelete = JsonUtils.cloneJson(configurationManager.getProjectForName(projectName), ProjectJson.class); configurationManager.deleteProject(projectToDelete); log.info("Project " + projectToDelete.name() + " was deleted by user " + user); afterProjectModifyPlugin.call(projectToDelete, StatusChange.remove, getUser(request).user().username()); getWriter(response).write("{}"); } @Override protected void myPost(HttpServletRequest request, HttpServletResponse response) { log.info("got post (reload) request"); IUserWithPermissions user = permissionsManager.user(request); String projectName = getParameter(request, Constants.UrlParameters.PROJECT_NAME); log.info("reloading project " + projectName + " user " + user.user().username()); ProjectJson projectJson = configurationManager.reloadProject(projectName); writeResponseJson(response, projectJson); } private boolean checkForRootPermissions(ProjectJson newProjectConf, ProjectJson currentProjectConf) { List<CollectorInfo> rootCollectors = Lists.newArrayList(Iterables.filter(newProjectConf.collectors(), rootCollectorPredicate())); List<CommandInfo> rootCommands = Lists.newArrayList(Iterables.filter(newProjectConf.commands(), rootCommandPredicate())); log.info("updated configuration has " + rootCollectors.size() + " collectors and " + rootCommands.size() + " commands running has root"); List<CollectorInfo> currentRootCollectors = Lists.newArrayList(Iterables.filter(currentProjectConf.collectors(), rootCollectorPredicate())); List<CommandInfo> currentRootCommands = Lists.newArrayList(Iterables.filter(currentProjectConf.commands(), rootCommandPredicate())); rootCollectors.removeAll(currentRootCollectors); if (rootCollectors.size() > 0) { log.info("Found " + rootCollectors.size() + " collectors that changed to root permissions " + rootCollectors); return false; } rootCommands.removeAll(currentRootCommands); if (rootCommands.size() > 0) { log.info("Found " + rootCommands.size() + " collectors that changed to root permissions " + rootCommands); return false; } return true; } private Predicate<CommandInfo> rootCommandPredicate() { return new Predicate<CommandInfo>() { @Override public boolean apply(CommandInfo commandInfo) { return !StringUtils.isEmpty(commandInfo.cred()) && commandInfo.cred().equals("root"); } }; } private Predicate<CollectorInfo> rootCollectorPredicate() { return new Predicate<CollectorInfo>() { @Override public boolean apply(CollectorInfo collectorInfo) { return !StringUtils.isEmpty(collectorInfo.cred()) && collectorInfo.cred().equals("root"); } }; } }