/* * Copyright 2011 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.siem.script; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import org.krakenapps.api.Script; import org.krakenapps.api.ScriptArgument; import org.krakenapps.api.ScriptContext; import org.krakenapps.api.ScriptUsage; import org.krakenapps.dom.api.ProgramApi; import org.krakenapps.dom.model.Program; import org.krakenapps.dom.model.ProgramPack; import org.krakenapps.dom.model.ProgramProfile; import org.krakenapps.event.api.Event; import org.krakenapps.event.api.EventDispatcher; import org.krakenapps.event.api.EventSeverity; import org.krakenapps.log.api.LoggerFactoryRegistry; import org.krakenapps.log.api.LoggerRegistry; import org.krakenapps.logstorage.Log; import org.krakenapps.siem.CandidateTextFileLogger; import org.krakenapps.siem.LogFileScanner; import org.krakenapps.siem.LogFileScannerRegistry; import org.krakenapps.siem.LogServer; import org.krakenapps.siem.engine.EventResponseMapper; import org.krakenapps.siem.engine.IscHttpRuleManager; import org.krakenapps.siem.engine.ResponseKey; import org.krakenapps.siem.model.ManagedLogger; import org.krakenapps.siem.response.ResponseAction; import org.krakenapps.siem.response.ResponseActionManager; import org.krakenapps.siem.response.ResponseConfigOption; import org.krakenapps.siem.response.ResponseServer; import org.krakenapps.xmlrpc.XmlRpcFaultException; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SiemScript implements Script { private final Logger slog = LoggerFactory.getLogger(SiemScript.class.getName()); private BundleContext bc; private ScriptContext context; public SiemScript(BundleContext bc) { this.bc = bc; } @Override public void setScriptContext(ScriptContext context) { this.context = context; } public void install(String[] args) { String domain = "localhost"; if (args.length > 0) domain = args[0]; ServiceReference ref = bc.getServiceReference(ProgramApi.class.getName()); ProgramApi programApi = (ProgramApi) bc.getService(ref); if (programApi.findProgramPack(domain, "radar") == null) { ProgramPack pack = new ProgramPack(); pack.setName("Radar"); pack.setDll("radar"); pack.setStarter("starter"); pack.setSeq(1); programApi.createProgramPack(domain, pack); } List<Program> programs = new ArrayList<Program>(); programs.add(createProgram(programApi, domain, "Radar", "Log Query", "logquery", 1)); programs.add(createProgram(programApi, domain, "Radar", "Log Source", "logsource", 2)); ProgramProfile pp = programApi.findProgramProfile(domain, "all"); pp.getPrograms().addAll(programs); programApi.updateProgramProfile(domain, pp); context.println("installed"); } private Program createProgram(ProgramApi programApi, String domain, String pack, String name, String path, int seq) { Program program = new Program(); program.setPack(pack); program.setName(name); program.setPath(path); program.setSeq(seq); program.setVisible(true); programApi.createProgram(domain, program); return program; } public void loggers(String[] args) { try { LogServer logServer = getLogServer(); context.println("Managed Loggers"); context.println("-------------------"); for (ManagedLogger m : logServer.getManagedLoggers()) { context.println(m.toString()); } } catch (Exception e) { context.println(e.getMessage()); } } public void updateHttpRules(String[] args) { IscHttpRuleManager manager = getIscHttpRuleManager(); try { manager.update(); context.println("update successful"); } catch (XmlRpcFaultException e) { context.println("failed: " + e.getFaultString()); } catch (Exception e) { context.println("failed: " + e); slog.error("kraken siem: cannot update rules", e); } } @ScriptUsage(description = "insert dummy log", arguments = { @ScriptArgument(name = "table name", type = "string", description = "logger full name"), @ScriptArgument(name = "word", type = "string", description = "any kinds of text") }) public void insertDummyLog(String[] args) { String tableName = args[0]; Date date = new Date(); String line = args[1]; LogServer logServer = getLogServer(); Map<String, Object> data = new HashMap<String, Object>(); data.put("line", line); logServer.write(new Log(tableName, date, data)); context.println("wrote one log"); } @ScriptUsage(description = "insert dummy event", arguments = { @ScriptArgument(type = "string", name = "org", description = "organization domain"), @ScriptArgument(type = "string", name = "severity", description = "severity"), @ScriptArgument(type = "string", name = "src ip", description = "src ip"), @ScriptArgument(type = "string", name = "dst ip", description = "dst ip"), @ScriptArgument(type = "string", name = "cve", description = "cve") }) public void insertDummyEvent(String[] args) throws UnknownHostException { String domain = args[0]; EventSeverity severity = EventSeverity.valueOf(args[1]); InetAddress src = InetAddress.getByName(args[2]); InetAddress dst = InetAddress.getByName(args[3]); Event e = new Event(); e.setOrgDomain(domain); e.setCategory("Attack"); e.setSourceIp(src); e.setDestinationIp(dst); e.setDestinationPort(80); e.setFirstSeen(new Date()); e.setLastSeen(new Date()); e.setSeverity(severity); e.setMessageKey("http-request-attack"); e.setCount(1); EventDispatcher d = getEventDispatcher(); d.dispatch(e); } @ScriptUsage(description = "create managed logger", arguments = { @ScriptArgument(name = "org domain", type = "string", description = "org domain"), @ScriptArgument(name = "logger fullname", type = "string", description = "logger fullname") }) public void createLogger(String[] args) { try { LogServer logServer = getLogServer(); ManagedLogger ml = new ManagedLogger(); ml.setOrgDomain(args[0]); ml.setFullName(args[1]); logServer.createManagedLogger(ml); context.println("created"); } catch (Exception e) { context.println(e.getMessage()); slog.error("kraken siem: cannot create logger", e); } } @ScriptUsage(description = "remove managed logger", arguments = { @ScriptArgument(name = "logger fullname", type = "string", description = "logger fullname") }) public void removeLogger(String[] args) { try { LogServer logServer = getLogServer(); ManagedLogger m = logServer.getManagedLogger(args[0]); if (m == null) { context.println("logger not found"); return; } logServer.removeManagedLogger(m); context.println("removed"); } catch (Exception e) { context.println(e.getMessage()); slog.error("kraken siem: cannot remove logger", e); } } @ScriptUsage(description = "print all response action managers") public void responseManagers(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } context.println("Response Action Managers"); context.println("-------------------------"); for (ResponseActionManager manager : responseServer.getResponseActionManagers()) { context.println(manager.toString()); } } @ScriptUsage(description = "create new response action", arguments = { @ScriptArgument(name = "manager name", type = "string", description = "the name of response action manager"), @ScriptArgument(name = "namespace", type = "string", description = "namespace"), @ScriptArgument(name = "name", type = "string", description = "name") }) public void createResponseAction(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } String managerName = args[0]; String namespace = args[1]; String name = args[2]; ResponseActionManager manager = responseServer.getResponseActionManager(managerName); if (manager == null) { context.println("manager not found"); return; } try { Properties config = new Properties(); for (ResponseConfigOption option : manager.getConfigOptions()) { String label = option.getDisplayName(Locale.ENGLISH); if (!option.isRequired()) label += " (optional)"; context.print(label + ": "); String value = context.readLine(); if (!value.isEmpty()) config.put(option.getName(), value); else if (option.isRequired()) { context.println("this is required option"); return; } } manager.newAction(namespace, name, null, config); context.println("created"); } catch (InterruptedException e) { context.println(""); context.println("interrupted"); } catch (Exception e) { context.println(e.getMessage()); slog.error("kraken siem: cannot create new action", e); } } @ScriptUsage(description = "remove response action", arguments = { @ScriptArgument(name = "manager", type = "string", description = "manager name"), @ScriptArgument(name = "namespace", type = "string", description = "action namespace"), @ScriptArgument(name = "name", type = "string", description = "action name") }) public void removeResponseAction(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } String managerName = args[0]; String namespace = args[1]; String name = args[2]; ResponseActionManager manager = responseServer.getResponseActionManager(managerName); if (manager == null) { context.println("manager not found"); return; } manager.deleteAction(namespace, name); context.println("deleted"); } @ScriptUsage(description = "print response actions", arguments = { @ScriptArgument(name = "manager name", type = "string", description = "name of the response manager"), @ScriptArgument(name = "namespace", type = "string", description = "action namespace", optional = true) }) public void responseActions(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } ResponseActionManager manager = responseServer.getResponseActionManager(args[0]); if (manager == null) { context.println("manager not found"); return; } Collection<ResponseAction> actions = null; if (args.length > 1) actions = manager.getActions(args[1]); else actions = manager.getActions(); context.println("Response Actions"); context.println("------------------"); for (ResponseAction action : actions) { context.println("manager=" + action.getManager() + ", namespace=" + action.getNamespace() + ", name=" + action.getName() + " => " + action.toString()); } } @ScriptUsage(description = "print all response mappings") public void responseMappings(String[] args) { EventResponseMapper mapper = getEventResponseMapper(); if (mapper == null) { context.println("mapper not ready"); return; } context.println("Event-Response Mappings"); context.println("-------------------------"); for (ResponseKey key : mapper.getKeys()) { context.println(key.toString()); Collection<ResponseAction> actions = mapper.getActions(key); for (ResponseAction action : actions) { context.println(" " + action.toString()); } context.println(""); } } @ScriptUsage(description = "create event-response mapping", arguments = { @ScriptArgument(name = "category", type = "string", description = "event category name"), @ScriptArgument(name = "manager", type = "string", description = "manager name"), @ScriptArgument(name = "namespace", type = "string", description = "namespace"), @ScriptArgument(name = "name", type = "string", description = "name") }) public void createResponseMapping(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } EventResponseMapper mapper = getEventResponseMapper(); if (mapper == null) { context.println("mapper not ready"); return; } String category = args[0]; String managerName = args[1]; String namespace = args[2]; String name = args[3]; ResponseActionManager manager = responseServer.getResponseActionManager(managerName); ResponseAction action = manager.getAction(namespace, name); if (action == null) { context.println("action not found"); return; } mapper.addResponse(new ResponseKey(category), action); context.println("created"); } @ScriptUsage(description = "remove event-response mapping", arguments = { @ScriptArgument(name = "category", type = "string", description = "event category name"), @ScriptArgument(name = "manager", type = "string", description = "manager name"), @ScriptArgument(name = "namespace", type = "string", description = "namespace"), @ScriptArgument(name = "name", type = "string", description = "name") }) public void removeResponseMapping(String[] args) { ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } EventResponseMapper mapper = getEventResponseMapper(); if (mapper == null) { context.println("mapper not ready"); return; } String category = args[0]; String managerName = args[1]; String namespace = args[2]; String name = args[3]; ResponseActionManager manager = responseServer.getResponseActionManager(managerName); ResponseAction action = manager.getAction(namespace, name); mapper.removeResponse(new ResponseKey(category), action); context.println("removed"); } public void configure(String[] args) { final String orgDomain = "localhost"; LogFileScannerRegistry registry = getLogFileScannerRegistry(); if (registry == null) { context.println("log file scanner registry not ready"); return; } LoggerFactoryRegistry loggerFactoryRegistry = getLoggerFactoryRegistry(); if (loggerFactoryRegistry == null) { context.println("logger factory registry not ready"); return; } org.krakenapps.log.api.LoggerRegistry loggerRegistry = getLoggerRegistry(); if (loggerRegistry == null) { context.println("logger registry not ready"); return; } org.krakenapps.log.api.LoggerFactory factory = loggerFactoryRegistry.getLoggerFactory("textfile"); if (factory == null) { context.println("text logger factory not found"); return; } LogServer logServer = getLogServer(); if (logServer == null) { context.println("log server not ready"); return; } ResponseServer responseServer = getResponseServer(); if (responseServer == null) { context.println("response server not ready"); return; } EventResponseMapper eventResponseMapper = getEventResponseMapper(); if (eventResponseMapper == null) { context.println("event response mapper not ready"); return; } // add default event-response ResponseActionManager manager = responseServer.getResponseActionManager("firewall"); if (manager.getAction("local", "all") == null) { Properties config = new Properties(); config.put("group_name", "all"); config.put("minutes", "60"); manager.newAction("local", "all", "", config); context.println("created default firewall response action"); } ResponseKey responseKey = new ResponseKey("Attack"); if (eventResponseMapper.getActions(responseKey) == null) { ResponseAction action = manager.getAction("local", "all"); eventResponseMapper.addResponse(responseKey, action); context.println("firewall will block source ip which are detected as attack event"); } // find and add loggers for (LogFileScanner scanner : registry.getScanners()) { context.println("running " + scanner.getName() + " scanner"); for (CandidateTextFileLogger candidate : scanner.scan()) { try { context.println(" " + candidate.toString()); org.krakenapps.log.api.Logger logger = loggerRegistry.getLogger("local", candidate.getName()); if (logger != null) { context.println(" " + candidate.getName() + " logger already exists"); } else { Properties config = new Properties(candidate.getMetadata()); config.put("file.path", candidate.getFile().getAbsolutePath()); logger = factory.newLogger(candidate.getName(), "", config); context.println(" logger [" + logger.getFullName() + "] created"); } if (logServer.getManagedLogger(logger.getFullName()) == null) { ManagedLogger ml = new ManagedLogger(); ml.setOrgDomain(orgDomain); ml.setFullName(logger.getFullName()); ml.setMetadata(toMap(candidate.getMetadata())); context.println(" managed logger [org=" + orgDomain + ", " + logger.getFullName() + "] created"); } if (!logger.isRunning()) { logger.start(1000); // check every 1sec context.println(" logger [" + logger.getFullName() + "] started"); } } catch (Exception e) { context.println(e.getMessage()); } } } } private Map<String, String> toMap(Properties p) { Map<String, String> m = new HashMap<String, String>(); for (Object key : p.keySet()) m.put(key.toString(), p.getProperty(key.toString())); return m; } public void logFileScanners(String[] args) { LogFileScannerRegistry registry = getLogFileScannerRegistry(); if (registry == null) { context.println("log file scanner registry not ready"); return; } context.println("Log File Scanners"); context.println("-------------------------"); for (LogFileScanner scanner : registry.getScanners()) { context.println(scanner.getName() + ": " + scanner.toString()); } } private ProgramApi getProgramApi() { return getService(ProgramApi.class, "program api"); } private LoggerFactoryRegistry getLoggerFactoryRegistry() { return getService(LoggerFactoryRegistry.class, "logger factory registry"); } private LoggerRegistry getLoggerRegistry() { return getService(LoggerRegistry.class, "logger registry"); } private LogFileScannerRegistry getLogFileScannerRegistry() { return getService(LogFileScannerRegistry.class, "log file scanner registry"); } private EventResponseMapper getEventResponseMapper() { return getService(EventResponseMapper.class, "event-response mapper"); } private LogServer getLogServer() { return getService(LogServer.class, "log server"); } private ResponseServer getResponseServer() { return getService(ResponseServer.class, "response server"); } private EventDispatcher getEventDispatcher() { return getService(EventDispatcher.class, "event dispatcher"); } private IscHttpRuleManager getIscHttpRuleManager() { return getService(IscHttpRuleManager.class, "isc http-rule manager"); } @SuppressWarnings("unchecked") private <T> T getService(Class<T> cls, String name) { ServiceReference ref = bc.getServiceReference(cls.getName()); if (ref == null) throw new IllegalStateException(name + " not ready"); return (T) bc.getService(ref); } }