diff --git a/docker-compose.yaml b/docker-compose.yaml
new file mode 100644
index 0000000..66f1e07
--- /dev/null
+++ b/docker-compose.yaml
@@ -0,0 +1,12 @@
+version: "3"
+services:
+ tests:
+ tty: true
+ entrypoint:
+ bash -c "cd soldr-modules && ./tests_framework/lua/bin/busted.linux64.cmd tests/."
+ build:
+ context: .
+ dockerfile: tests/Dockerfile
+ volumes:
+ - .:/soldr-modules
+# command: tail -f /dev/null
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/bmodule/main.vue b/osquery_linux/1.0.0/bmodule/main.vue
new file mode 100644
index 0000000..e4da48a
--- /dev/null
+++ b/osquery_linux/1.0.0/bmodule/main.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/osquery_linux/1.0.0/cmodule/args.json b/osquery_linux/1.0.0/cmodule/args.json
new file mode 100644
index 0000000..6d99e88
--- /dev/null
+++ b/osquery_linux/1.0.0/cmodule/args.json
@@ -0,0 +1,3 @@
+{
+ "debug": ["true"]
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/cmodule/data/binaries/deb/osquery.deb b/osquery_linux/1.0.0/cmodule/data/binaries/deb/osquery.deb
new file mode 100644
index 0000000..ed8aa6c
Binary files /dev/null and b/osquery_linux/1.0.0/cmodule/data/binaries/deb/osquery.deb differ
diff --git a/osquery_linux/1.0.0/cmodule/data/binaries/rpm/osquery.rpm b/osquery_linux/1.0.0/cmodule/data/binaries/rpm/osquery.rpm
new file mode 100644
index 0000000..df7c545
Binary files /dev/null and b/osquery_linux/1.0.0/cmodule/data/binaries/rpm/osquery.rpm differ
diff --git a/osquery_linux/1.0.0/cmodule/helpers.lua b/osquery_linux/1.0.0/cmodule/helpers.lua
new file mode 100644
index 0000000..01548d1
--- /dev/null
+++ b/osquery_linux/1.0.0/cmodule/helpers.lua
@@ -0,0 +1,226 @@
+require("system")
+require("engine")
+
+local fs = require("fs")
+local cjson = require("cjson.safe")
+
+-- variables to initialize event and action engines
+local prefix_db = __gid .. "."
+local fields_schema = __config.get_fields_schema()
+local current_event_config = __config.get_current_event_config()
+local module_info = __config.get_module_info()
+
+-- event and action engines initialization
+local action_engine = CActionEngine(
+ {},
+ __args["debug"][1] == "true"
+)
+
+local event_engine = CEventEngine(
+ fields_schema,
+ current_event_config,
+ module_info,
+ prefix_db,
+ __args["debug"][1] == "true"
+)
+
+local function exec_cmd(cmd, raw)
+ __log.debugf("cmd to exec: %s", tostring(cmd))
+ local f = assert(io.popen(cmd, 'r'))
+ local s = assert(f:read('*a'))
+ f:close()
+ __log.debugf("cmd output: %s", tostring(s))
+ if raw or raw == nil then return s end
+ s = string.gsub(s, '^%s+', '')
+ s = string.gsub(s, '%s+$', '')
+ s = string.gsub(s, '[\n\r]+', ' ')
+ return s
+end
+
+local module_config = cjson.decode(__config.get_current_config())
+
+local function reread_module_info()
+ module_config = cjson.decode(__config.get_current_config())
+end
+
+local function get_opt_cfg__osquery_config()
+ return module_config["osquery_config"]
+end
+
+local function get_opt_cfg__replace_current_osquery_config()
+ return module_config["replace_current_osquery_config"]
+end
+
+-- return string with raw content of file (use if agent run with admin permissions)
+local function get_file_content(path)
+ local content = ''
+ local file = io.open(path, "r")
+ if file then
+ content = file:read("*a")
+ file:close()
+ end
+
+ return content
+end
+
+-- events executor by event name and data
+local function push_event(event_name, event_data)
+ assert(type(event_name) == "string", "event_name must be a string")
+ assert(type(event_data) == "table", "event_data must be a table")
+
+ -- push the event to the engine
+ local info = {
+ ["name"] = event_name,
+ ["data"] = event_data,
+ ["actions"] = {},
+ }
+ local result, list = event_engine:push_event(info)
+ -- check result return variable as marker is there need to execute actions
+ if result then
+ local data = action_engine:exec(__aid, list)
+ for action_id, action_result in ipairs(data) do
+ __log.debugf("action '%s' was requested: '%s'", action_id, action_result)
+ end
+ end
+end
+
+local function push_event__osquery_already_installed(event_data)
+ return push_event("osquery_linux_already_installed", event_data)
+end
+
+local function push_event__osquery_already_started(event_data)
+ return push_event("osquery_linux_already_started", event_data)
+end
+
+local function push_event__osquery_config_updated_error(event_data)
+ return push_event("osquery_linux_config_updated_error", event_data)
+end
+
+local function push_event__osquery_config_updated_success(event_data)
+ return push_event("osquery_linux_config_updated_success", event_data)
+end
+
+local function push_event__osquery_installed_error(event_data)
+ return push_event("osquery_linux_installed_error", event_data)
+end
+
+local function push_event__osquery_installed_success(event_data)
+ return push_event("osquery_linux_installed_success", event_data)
+end
+
+local function push_event__osquery_started_error(event_data)
+ return push_event("osquery_linux_started_error", event_data)
+end
+
+local function push_event__osquery_started_success(event_data)
+ return push_event("osquery_linux_started_success", event_data)
+end
+
+local function push_event__osquery_unexpected_stopped(event_data)
+ return push_event("osquery_linux_unexpected_stopped", event_data)
+end
+
+local function push_event__osquery_unexpected_uninstalled(event_data)
+ return push_event("osquery_linux_unexpected_uninstalled", event_data)
+end
+
+local function push_event__osquery_uninstalled_error(event_data)
+ return push_event("osquery_linux_uninstalled_error", event_data)
+end
+
+local function push_event__osquery_uninstalled_success(event_data)
+ return push_event("osquery_linux_uninstalled_success", event_data)
+end
+
+-- arguments:
+-- * path - path to removed dir
+-- return bool
+local function is_file_exist(path)
+ local isfile = fs.is(path, 'file')
+
+ return isfile
+end
+
+-- return true or false
+local function create_file(path)
+ local f, err, errcode = fs.open(path, 'w+')
+ if not f then
+ __log.errorf("error creating file (errcode %s) %s: %s", errcode, path, err)
+ return false
+ end
+ f:close()
+
+ return true
+end
+
+-- return 'deb' or 'rpm' or ''
+local function detect_package_manager()
+ local cmd = "which dpkg"
+ local out = exec_cmd(cmd)
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ if out ~= "" then
+ return "deb"
+ end
+
+ local cmd = "which rpm"
+ local out = exec_cmd(cmd)
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ if out ~= "" then
+ return "rpm"
+ end
+
+ return ""
+end
+
+local package_manager = detect_package_manager()
+
+local function data_osquery_pkg_path()
+ local osquery_pkg_prefix = "osquery."
+ return tostring(__tmpdir) .. "/data/binaries/" .. package_manager .. '/' .. osquery_pkg_prefix .. package_manager
+end
+
+-- TODO: remake for package manager
+local function get_provided_version_osquery()
+ local cmd = "dpkg -f " .. data_osquery_pkg_path() .. " version"
+ if package_manager == 'rpm' then
+ cmd = 'rpm -qip ' .. data_osquery_pkg_path()
+ end
+
+ local out = exec_cmd(cmd)
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ local result = out:match("%d+.%d+.%d+") or ""
+
+ if result == "" then __log.warnf("provided version osquery: %s", result) end
+
+ return result
+end
+
+return {
+ exec_cmd = exec_cmd,
+ get_opt_cfg__osquery_config = get_opt_cfg__osquery_config,
+ get_opt_cfg__replace_current_osquery_config = get_opt_cfg__replace_current_osquery_config,
+
+ push_event__osquery_already_installed = push_event__osquery_already_installed,
+ push_event__osquery_already_started = push_event__osquery_already_started,
+ push_event__osquery_config_updated_error = push_event__osquery_config_updated_error,
+ push_event__osquery_config_updated_success = push_event__osquery_config_updated_success,
+ push_event__osquery_installed_error = push_event__osquery_installed_error,
+ push_event__osquery_installed_success = push_event__osquery_installed_success,
+ push_event__osquery_started_error = push_event__osquery_started_error,
+ push_event__osquery_started_success = push_event__osquery_started_success,
+ push_event__osquery_unexpected_stopped = push_event__osquery_unexpected_stopped,
+ push_event__osquery_unexpected_uninstalled = push_event__osquery_unexpected_uninstalled,
+ push_event__osquery_uninstalled_error = push_event__osquery_uninstalled_error,
+ push_event__osquery_uninstalled_success = push_event__osquery_uninstalled_success,
+
+ create_file = create_file,
+ get_file_content = get_file_content,
+ is_file_exist = is_file_exist,
+ reread_module_info = reread_module_info,
+ package_manager = package_manager,
+ data_osquery_pkg_path = data_osquery_pkg_path,
+ get_provided_version_osquery = get_provided_version_osquery,
+}
diff --git a/osquery_linux/1.0.0/cmodule/main.lua b/osquery_linux/1.0.0/cmodule/main.lua
new file mode 100644
index 0000000..2ca899b
--- /dev/null
+++ b/osquery_linux/1.0.0/cmodule/main.lua
@@ -0,0 +1,298 @@
+require("engine")
+require("system")
+
+local osquery = require("osquery")
+local helpers = require("helpers")
+
+__log.debugf("path to temp dir '%s'", __tmpdir)
+
+-- return bool
+local function need_to_update_config()
+ return helpers.get_opt_cfg__replace_current_osquery_config() and
+ helpers.get_opt_cfg__osquery_config() ~= osquery:get_config()
+end
+
+-- ########## PHASES ##########
+
+-- return 'install'/'configure'/'controll'
+local function preparing_phase()
+ if not osquery:is_installed() or not osquery:is_version_correct() then return 'install' end
+
+ if osquery:state() ~= "running" and not osquery:start() then
+ helpers.push_event__osquery_installed_error({
+ reason = "osquery is already installed but can not start",
+ version = osquery:get_version(),
+ })
+
+ return "control"
+ end
+
+ helpers.push_event__osquery_already_installed({
+ reason = "service osqueryd has already installed",
+ version = osquery:get_version(),
+ })
+
+ if need_to_update_config() then return 'configure' end
+
+ return "control"
+end
+
+-- installed osquery, check it and push all events
+-- return 'configure'/'control'
+local function install_phase()
+ __log.debug("call install_phase")
+ local success, reason = osquery:install()
+
+ if success then
+ local state = osquery:state()
+ if state ~= "running" and not osquery:start() then
+ __log.info("osquery was not installed")
+
+ helpers.push_event__osquery_installed_error({
+ reason = "osquery was installed but can not start",
+ version = osquery:get_version(),
+ })
+
+ return "control"
+ end
+
+ __log.info("osquery was installed success")
+ helpers.push_event__osquery_installed_success({
+ version = osquery:get_version(),
+ reason = "",
+ })
+
+ if need_to_update_config() then return 'configure' end
+
+ return 'control'
+ end
+
+ __log.info("osquery was not installed")
+ helpers.push_event__osquery_installed_error({
+ version = helpers.get_provided_version_osquery(),
+ reason = reason,
+ })
+
+ return 'control'
+end
+
+-- update osquery config
+-- return 'control'
+local function configure_phase()
+ __log.debug("call configure_phase")
+
+ local replace_current_osquery_config = helpers.get_opt_cfg__replace_current_osquery_config()
+
+ if not replace_current_osquery_config then
+ __log.debug("skip configure phase, replace_current_osquery_config: %s", replace_current_osquery_config)
+ return 'control'
+ end
+
+ local version = osquery:get_version()
+ local config_path = osquery:get_config_path()
+
+ if config_path == '' then
+ local err = "failed to update osquery config file, can't find or create config path"
+ __log.error(err)
+ helpers.push_event__osquery_config_updated_error({
+ reason = err,
+ version = version,
+ })
+
+ return "control"
+ end
+
+ if not osquery:update_config_file() then
+ local err = "failed to update config file to module directory"
+ __log.error(err)
+
+ helpers.push_event__osquery_config_updated_error({
+ reason = err,
+ version = version,
+ })
+
+ return "control"
+ end
+
+ if not osquery:stop() then
+ local err = "can not restart osquery after update config (can not stop osquery)"
+ __log.error(err)
+
+ helpers.push_event__osquery_config_updated_error({
+ reason = err,
+ version = version,
+ })
+
+ return "control"
+ end
+
+ if not osquery:start() then
+ local err = "can not restart osquery after update config (can not start osquery)"
+ __log.error(err)
+
+ helpers.push_event__osquery_config_updated_error({
+ reason = err,
+ version = version,
+ })
+
+ return "control"
+ end
+
+ __log.info("osquery config updated success")
+ helpers.push_event__osquery_config_updated_success({
+ version = version,
+ })
+
+ return "control"
+end
+
+-- return 'install' or nothing
+local function control_phase()
+ local last_state = osquery:state()
+ local version = helpers.get_provided_version_osquery()
+ if last_state == "running" then
+ version = osquery:get_version()
+ end
+
+ local change_state
+
+ while not __api.is_close() do
+ local current_state = osquery:state()
+ if last_state == current_state then goto continue end
+
+ change_state = "from: " .. last_state .. ", to: " .. current_state
+
+ if current_state == "unknown" then
+ __log.warnf("osquery was unexpected uninstalled (state: %s)", change_state)
+
+ helpers.push_event__osquery_unexpected_uninstalled({
+ version = version,
+ reason = change_state,
+ })
+
+ return "install"
+ end
+
+ if current_state == "stopped" then
+ __log.warnf("osquery was unexpected stopped (state: %s)", change_state)
+
+ __log.info("osquery is stopped and should be running")
+ helpers.push_event__osquery_unexpected_stopped({
+ reason = change_state,
+ version = version,
+ })
+
+ if not osquery:start() then
+ local err = "failed to start osquery, change state: " .. change_state
+ __log.error(err)
+
+ helpers.push_event__osquery_started_error({
+ reason = err,
+ version = version,
+ })
+
+ last_state = "stopped"
+ goto continue
+ end
+
+ version = osquery:get_version()
+ __log.infof("osquery %s started success, change state: %s", version, change_state)
+
+ helpers.push_event__osquery_started_success({
+ reason = change_state,
+ version = version,
+ })
+
+ last_state = "running"
+ goto continue
+ end
+
+ if current_state == "running" then
+ version = osquery:get_version()
+ helpers.push_event__osquery_already_started({
+ reason = change_state,
+ version = version,
+ })
+
+ last_state = "running"
+ end
+
+ ::continue::
+ __api.await(10000)
+ end
+end
+
+-- ########## SYSTEM FUNCTIONS AND CALLBACKS ##########
+
+-- set default timeout to wait exit on blocking of recv_* functions
+__api.set_recv_timeout(5000) -- 5s
+
+__api.add_cbs({
+
+ -- data = function(src, data)
+ -- file = function(src, path, name)
+ -- text = function(src, text, name)
+ -- msg = function(src, msg, mtype)
+ -- action = function(src, data, name)
+
+ control = function(cmtype, data)
+ __log.infof("receive control msg '%s' with payload: %s", cmtype, data)
+
+ if cmtype == 'update_config' then
+ helpers.reread_module_info()
+ configure_phase()
+
+ return true
+ end
+
+ if cmtype == 'quit' then
+ if not osquery:is_installed() then
+ __log.info("quit from module without uninstalation osquery")
+ return true
+ end
+
+ local version = osquery:get_version()
+ local success, reason = osquery:uninstall()
+
+ if success then
+ __log.info("osquery was uninstalled success")
+ helpers.push_event__osquery_uninstalled_success({
+ version = version,
+ })
+
+ return true
+ end
+
+ __log.errorf("osquery was not uninstalled, reason: %s", reason)
+ helpers.push_event__osquery_uninstalled_error({
+ version = version,
+ reason = reason,
+ })
+ end
+
+ return true
+ end,
+})
+
+
+__log.infof("module '%s' was started", __config.ctx.name)
+
+local next_phase = preparing_phase()
+
+while next_phase do
+ __log.debugf("the next phase '%s'", next_phase)
+ if next_phase == "install" then
+ next_phase = install_phase()
+ elseif next_phase == "configure" then
+ next_phase = configure_phase()
+ elseif next_phase == "control" then
+ next_phase = control_phase()
+ else
+ __log.errorf("unexpected next handler: %s", next_phase)
+ break
+ end
+end
+
+__log.infof("module '%s' was stopped", __config.ctx.name)
+
+return 'success'
diff --git a/osquery_linux/1.0.0/cmodule/osquery.lua b/osquery_linux/1.0.0/cmodule/osquery.lua
new file mode 100644
index 0000000..ab8248d
--- /dev/null
+++ b/osquery_linux/1.0.0/cmodule/osquery.lua
@@ -0,0 +1,166 @@
+require("system")
+local helpers = require("helpers")
+
+--local sysinfo = CSystemInfo({})
+
+-- Module immutable global variables
+local osquery_config_name = "osquery.conf"
+local path_to_dumped_config = tostring(__tmpdir) .. "/" .. osquery_config_name
+
+local Osquery = {}
+
+-- linux
+-- return string with path to config of installed osquery
+function Osquery:get_config_path()
+ local path = '/etc/osquery/osquery.conf'
+
+ if helpers.is_file_exist(path) or helpers.create_file(path) then return path end
+
+ return ''
+end
+
+-- linux
+-- return bool
+function Osquery:is_installed()
+ return self:get_version() ~= ""
+end
+
+-- linux
+-- return string like '5.5.1'
+function Osquery:get_version()
+ local cmd = "osqueryd --version"
+ local out = helpers.exec_cmd(cmd)
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ local result = out:match("%d+.%d+.%d+") or ""
+
+ return result
+end
+
+-- linux
+-- return bool
+function Osquery:is_version_correct()
+ local version = self:get_version()
+ __log.infof("found osquery version '%s'", version)
+
+ return version == helpers.get_provided_version_osquery()
+end
+
+-- linux
+-- return string contaned raw config by installed osquery
+function Osquery:get_config()
+ local path = self:get_config_path()
+
+ if path == '' then return '' end
+
+ return helpers.get_file_content(path)
+end
+
+-- linux
+-- return boolean
+function Osquery:update_config_file()
+ local config_path = self:get_config_path()
+ local file = io.open(config_path, "w+")
+ if not file then
+ return false
+ end
+
+ local _ = file:write(helpers.get_opt_cfg__osquery_config())
+ file:close()
+
+ return self:get_config() == helpers.get_opt_cfg__osquery_config()
+end
+
+-- linux
+-- returns 2 agrs: bool, string (reason)
+function Osquery:install()
+ local cmd = "dpkg -i " .. helpers.data_osquery_pkg_path()
+ if helpers.package_manager == 'rpm' then
+ cmd = 'rpm -i ' .. helpers.data_osquery_pkg_path()
+ end
+
+ local out = helpers.exec_cmd(cmd) or ""
+ __log.infof("out of cmd '%s': %s", cmd, out)
+
+ local success = self:is_installed()
+
+ local reason = ""
+ if not success then reason = "osquery can not installed" end
+
+ return success, reason
+end
+
+-- linux
+-- remove osquery from machine
+-- returns
+-- * bool: result of uninstalation
+-- * string: reason of failed uninstalation
+function Osquery:uninstall()
+ local cmd = 'systemctl stop osqueryd'
+ local out = helpers.exec_cmd(cmd) or ""
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ cmd = 'dpkg --force-all -P osquery'
+ if helpers.package_manager == 'rpm' then
+ cmd = 'rpm -e osquery'
+ end
+
+ out = helpers.exec_cmd(cmd) or ""
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ os.execute("sleep 2")
+ if not self:is_installed() then return true, "" end
+
+ local state = self:state()
+ return false, "error uninstalation osquery, current state: " .. state
+end
+
+-- linux
+-- return: string of running, stopped, unknown
+function Osquery:state()
+ if not self:is_installed() then return 'unknown' end
+
+ local cmd = 'systemctl is-active osqueryd'
+ local out = helpers.exec_cmd(cmd) or ''
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ if out == "unknown\n" then return "unknown" end
+ if out == "active\n" then return "running" end
+
+ return "stopped"
+end
+
+-- linux
+-- return true/false
+function Osquery:start()
+ local cmd = 'systemctl start osqueryd'
+ local out = helpers.exec_cmd(cmd) or ""
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ local state = self:state()
+ if state == 'running' then return true end
+
+ cmd = 'systemctl enable osqueryd'
+ out = helpers.exec_cmd(cmd) or ""
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ state = self:state()
+ if state == 'running' then return true end
+
+ return false
+end
+
+-- linux
+-- return true/false
+function Osquery:stop()
+ local cmd = 'systemctl stop osqueryd'
+ local out = helpers.exec_cmd(cmd) or ""
+ __log.debugf("out of cmd '%s': %s", cmd, out)
+
+ local state = self:state()
+ if state ~= 'stopped' then return false end
+
+ return true
+end
+
+return Osquery
diff --git a/osquery_linux/1.0.0/config/action_config_schema.json b/osquery_linux/1.0.0/config/action_config_schema.json
new file mode 100644
index 0000000..01d441c
--- /dev/null
+++ b/osquery_linux/1.0.0/config/action_config_schema.json
@@ -0,0 +1,6 @@
+{
+ "additionalProperties": false,
+ "properties": {},
+ "required": [],
+ "type": "object"
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/changelog.json b/osquery_linux/1.0.0/config/changelog.json
new file mode 100644
index 0000000..cc73102
--- /dev/null
+++ b/osquery_linux/1.0.0/config/changelog.json
@@ -0,0 +1,14 @@
+{
+ "1.0.0": {
+ "en": {
+ "date": "01-09-2023",
+ "title": "Base functionality",
+ "description": "Added installation and configure osquery on agent for linux"
+ },
+ "ru": {
+ "date": "09.01.2023",
+ "title": "Базовая функциональность",
+ "description": "Добавлена возможность установки и конфигурирования osquery на агенте для ОС linux"
+ }
+ }
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/config_schema.json b/osquery_linux/1.0.0/config/config_schema.json
new file mode 100644
index 0000000..ee0ee52
--- /dev/null
+++ b/osquery_linux/1.0.0/config/config_schema.json
@@ -0,0 +1,31 @@
+{
+ "additionalProperties": false,
+ "properties": {
+ "osquery_config": {
+ "rules": {},
+ "type": "string",
+ "ui": {
+ "widget": "textarea",
+ "widgetConfig": {
+ "autoSize": {
+ "maxRows": 20,
+ "minRows": 10
+ },
+ "rows": 10
+ }
+ }
+ },
+ "replace_current_osquery_config": {
+ "rules": {},
+ "type": "boolean",
+ "ui": {
+ "widgetConfig": {}
+ }
+ }
+ },
+ "required": [
+ "osquery_config",
+ "replace_current_osquery_config"
+ ],
+ "type": "object"
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/current_action_config.json b/osquery_linux/1.0.0/config/current_action_config.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/osquery_linux/1.0.0/config/current_action_config.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/current_config.json b/osquery_linux/1.0.0/config/current_config.json
new file mode 100644
index 0000000..79af50b
--- /dev/null
+++ b/osquery_linux/1.0.0/config/current_config.json
@@ -0,0 +1,4 @@
+{
+ "osquery_config": "{\n \"options\": {\n \"logger_plugin\": \"windows_event_log\"\n },\n \"schedule\": {\n \"system_info\": {\n \"query\": \"SELECT hostname, cpu_brand, physical_memory FROM system_info;\",\n \"interval\": 3600\n }\n },\n\n \"decorators\": {\n \"load\": [\n \"SELECT uuid AS host_uuid FROM system_info;\",\n \"SELECT user AS username FROM logged_in_users ORDER BY time DESC LIMIT 1;\"\n ]\n },\n\n // Add default osquery packs or install your own.\n //\n // There are several 'default' packs installed via\n // packages and/or Homebrew.\n //\n // Linux: /opt/osquery/share/osquery/packs\n // OS X: /var/osquery/packs\n // Homebrew: /usr/local/share/osquery/packs\n // make install: {PREFIX}/share/osquery/packs\n //\n \"packs\": {\n // \"osquery-monitoring\": \"/opt/osquery/share/osquery/packs/osquery-monitoring.conf\",\n // \"incident-response\": \"/opt/osquery/share/osquery/packs/incident-response.conf\",\n // \"it-compliance\": \"/opt/osquery/share/osquery/packs/it-compliance.conf\",\n // \"osx-attacks\": \"/var/osquery/packs/osx-attacks.conf\",\n // \"vuln-management\": \"/opt/osquery/share/osquery/packs/vuln-management.conf\",\n // \"hardware-monitoring\": \"/opt/osquery/share/osquery/packs/hardware-monitoring.conf\",\n // \"ossec-rootkit\": \"/opt/osquery/share/osquery/packs/ossec-rootkit.conf\",\n // \"windows-hardening\": \"C:\\\\Program Files\\\\osquery\\\\packs\\\\windows-hardening.conf\",\n // \"windows-attacks\": \"C:\\\\Program Files\\\\osquery\\\\packs\\\\windows-attacks.conf\"\n },\n\n // Provides feature vectors for osquery to leverage in simple statistical \n // analysis of results data. \n //\n // Currently this configuration is only used by Windows in the Powershell\n // Events table, wherein character_frequencies is a list of doubles \n // representing the aggregate occurrence of character values in Powershell \n // Scripts. A default configuration is provided which was adapated from \n // Lee Holmes cobbr project: \n // https://gist.github.com/cobbr/acbe5cc7a186726d4e309070187beee6\n // \n \"feature_vectors\": {\n \"character_frequencies\": [\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.00045, 0.01798,\n 0.0, 0.03111, 0.00063, 0.00027, 0.0, 0.01336, 0.0133,\n 0.00128, 0.0027, 0.00655, 0.01932, 0.01917, 0.00432, 0.0045,\n 0.00316, 0.00245, 0.00133, 0.001029, 0.00114, 0.000869, 0.00067,\n 0.000759, 0.00061, 0.00483, 0.0023, 0.00185, 0.01342, 0.00196,\n 0.00035, 0.00092, 0.027875, 0.007465, 0.016265, 0.013995, 0.0490895,\n 0.00848, 0.00771, 0.00737, 0.025615, 0.001725, 0.002265, 0.017875,\n 0.016005, 0.02533, 0.025295, 0.014375, 0.00109, 0.02732, 0.02658,\n 0.037355, 0.011575, 0.00451, 0.005865, 0.003255, 0.005965, 0.00077,\n 0.00621, 0.00222, 0.0062, 0.0, 0.00538, 0.00122, 0.027875,\n 0.007465, 0.016265, 0.013995, 0.0490895, 0.00848, 0.00771, 0.00737,\n 0.025615, 0.001725, 0.002265, 0.017875, 0.016005, 0.02533, 0.025295,\n 0.014375, 0.00109, 0.02732, 0.02658, 0.037355, 0.011575, 0.00451,\n 0.005865, 0.003255, 0.005965, 0.00077, 0.00771, 0.002379, 0.00766,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0\n ]\n } \n}\n",
+ "replace_current_osquery_config": true
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/current_event_config.json b/osquery_linux/1.0.0/config/current_event_config.json
new file mode 100644
index 0000000..8311b96
--- /dev/null
+++ b/osquery_linux/1.0.0/config/current_event_config.json
@@ -0,0 +1,179 @@
+{
+ "osquery_linux_already_installed": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_already_started": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_config_updated_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_config_updated_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_installed_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_installed_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_started_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_started_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_unexpected_stopped": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_unexpected_uninstalled": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_uninstalled_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_uninstalled_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ }
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/default_action_config.json b/osquery_linux/1.0.0/config/default_action_config.json
new file mode 100644
index 0000000..9e26dfe
--- /dev/null
+++ b/osquery_linux/1.0.0/config/default_action_config.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/default_config.json b/osquery_linux/1.0.0/config/default_config.json
new file mode 100644
index 0000000..79af50b
--- /dev/null
+++ b/osquery_linux/1.0.0/config/default_config.json
@@ -0,0 +1,4 @@
+{
+ "osquery_config": "{\n \"options\": {\n \"logger_plugin\": \"windows_event_log\"\n },\n \"schedule\": {\n \"system_info\": {\n \"query\": \"SELECT hostname, cpu_brand, physical_memory FROM system_info;\",\n \"interval\": 3600\n }\n },\n\n \"decorators\": {\n \"load\": [\n \"SELECT uuid AS host_uuid FROM system_info;\",\n \"SELECT user AS username FROM logged_in_users ORDER BY time DESC LIMIT 1;\"\n ]\n },\n\n // Add default osquery packs or install your own.\n //\n // There are several 'default' packs installed via\n // packages and/or Homebrew.\n //\n // Linux: /opt/osquery/share/osquery/packs\n // OS X: /var/osquery/packs\n // Homebrew: /usr/local/share/osquery/packs\n // make install: {PREFIX}/share/osquery/packs\n //\n \"packs\": {\n // \"osquery-monitoring\": \"/opt/osquery/share/osquery/packs/osquery-monitoring.conf\",\n // \"incident-response\": \"/opt/osquery/share/osquery/packs/incident-response.conf\",\n // \"it-compliance\": \"/opt/osquery/share/osquery/packs/it-compliance.conf\",\n // \"osx-attacks\": \"/var/osquery/packs/osx-attacks.conf\",\n // \"vuln-management\": \"/opt/osquery/share/osquery/packs/vuln-management.conf\",\n // \"hardware-monitoring\": \"/opt/osquery/share/osquery/packs/hardware-monitoring.conf\",\n // \"ossec-rootkit\": \"/opt/osquery/share/osquery/packs/ossec-rootkit.conf\",\n // \"windows-hardening\": \"C:\\\\Program Files\\\\osquery\\\\packs\\\\windows-hardening.conf\",\n // \"windows-attacks\": \"C:\\\\Program Files\\\\osquery\\\\packs\\\\windows-attacks.conf\"\n },\n\n // Provides feature vectors for osquery to leverage in simple statistical \n // analysis of results data. \n //\n // Currently this configuration is only used by Windows in the Powershell\n // Events table, wherein character_frequencies is a list of doubles \n // representing the aggregate occurrence of character values in Powershell \n // Scripts. A default configuration is provided which was adapated from \n // Lee Holmes cobbr project: \n // https://gist.github.com/cobbr/acbe5cc7a186726d4e309070187beee6\n // \n \"feature_vectors\": {\n \"character_frequencies\": [\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.00045, 0.01798,\n 0.0, 0.03111, 0.00063, 0.00027, 0.0, 0.01336, 0.0133,\n 0.00128, 0.0027, 0.00655, 0.01932, 0.01917, 0.00432, 0.0045,\n 0.00316, 0.00245, 0.00133, 0.001029, 0.00114, 0.000869, 0.00067,\n 0.000759, 0.00061, 0.00483, 0.0023, 0.00185, 0.01342, 0.00196,\n 0.00035, 0.00092, 0.027875, 0.007465, 0.016265, 0.013995, 0.0490895,\n 0.00848, 0.00771, 0.00737, 0.025615, 0.001725, 0.002265, 0.017875,\n 0.016005, 0.02533, 0.025295, 0.014375, 0.00109, 0.02732, 0.02658,\n 0.037355, 0.011575, 0.00451, 0.005865, 0.003255, 0.005965, 0.00077,\n 0.00621, 0.00222, 0.0062, 0.0, 0.00538, 0.00122, 0.027875,\n 0.007465, 0.016265, 0.013995, 0.0490895, 0.00848, 0.00771, 0.00737,\n 0.025615, 0.001725, 0.002265, 0.017875, 0.016005, 0.02533, 0.025295,\n 0.014375, 0.00109, 0.02732, 0.02658, 0.037355, 0.011575, 0.00451,\n 0.005865, 0.003255, 0.005965, 0.00077, 0.00771, 0.002379, 0.00766,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,\n 0.0, 0.0, 0.0\n ]\n } \n}\n",
+ "replace_current_osquery_config": true
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/default_event_config.json b/osquery_linux/1.0.0/config/default_event_config.json
new file mode 100644
index 0000000..8311b96
--- /dev/null
+++ b/osquery_linux/1.0.0/config/default_event_config.json
@@ -0,0 +1,179 @@
+{
+ "osquery_linux_already_installed": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_already_started": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_config_updated_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_config_updated_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_installed_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_installed_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_started_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_started_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_unexpected_stopped": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_unexpected_uninstalled": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_uninstalled_error": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "type": "atomic"
+ },
+ "osquery_linux_uninstalled_success": {
+ "actions": [
+ {
+ "fields": [],
+ "module_name": "this",
+ "name": "log_to_db",
+ "priority": 10
+ }
+ ],
+ "fields": [
+ "version"
+ ],
+ "type": "atomic"
+ }
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/dynamic_dependencies.json b/osquery_linux/1.0.0/config/dynamic_dependencies.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/osquery_linux/1.0.0/config/dynamic_dependencies.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/event_config_schema.json b/osquery_linux/1.0.0/config/event_config_schema.json
new file mode 100644
index 0000000..33fe00b
--- /dev/null
+++ b/osquery_linux/1.0.0/config/event_config_schema.json
@@ -0,0 +1,386 @@
+{
+ "additionalProperties": false,
+ "properties": {
+ "osquery_linux_already_installed": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_already_started": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_config_updated_error": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_config_updated_success": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 1,
+ "minItems": 1,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_installed_error": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_installed_success": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 1,
+ "minItems": 1,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_started_error": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_started_success": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_unexpected_stopped": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_unexpected_uninstalled": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_uninstalled_error": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "reason",
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "reason",
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 2,
+ "minItems": 2,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ },
+ "osquery_linux_uninstalled_success": {
+ "allOf": [
+ {
+ "$ref": "#/definitions/events.atomic"
+ },
+ {
+ "properties": {
+ "fields": {
+ "default": [
+ "version"
+ ],
+ "items": {
+ "enum": [
+ "version"
+ ],
+ "type": "string"
+ },
+ "maxItems": 1,
+ "minItems": 1,
+ "type": "array"
+ }
+ },
+ "required": [
+ "fields"
+ ],
+ "type": "object"
+ }
+ ]
+ }
+ },
+ "required": [
+ "osquery_linux_already_installed",
+ "osquery_linux_already_started",
+ "osquery_linux_config_updated_error",
+ "osquery_linux_config_updated_success",
+ "osquery_linux_installed_error",
+ "osquery_linux_installed_success",
+ "osquery_linux_started_error",
+ "osquery_linux_started_success",
+ "osquery_linux_unexpected_stopped",
+ "osquery_linux_unexpected_uninstalled",
+ "osquery_linux_uninstalled_error",
+ "osquery_linux_uninstalled_success"
+ ],
+ "type": "object"
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/fields_schema.json b/osquery_linux/1.0.0/config/fields_schema.json
new file mode 100644
index 0000000..c4ccae3
--- /dev/null
+++ b/osquery_linux/1.0.0/config/fields_schema.json
@@ -0,0 +1,23 @@
+{
+ "additionalProperties": true,
+ "properties": {
+ "reason": {
+ "rules": {},
+ "type": "string",
+ "ui": {
+ "widgetConfig": {}
+ }
+ },
+ "version": {
+ "rules": {},
+ "type": "string",
+ "ui": {
+ "widgetConfig": {}
+ }
+ }
+ },
+ "required": [
+ "version"
+ ],
+ "type": "object"
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/info.json b/osquery_linux/1.0.0/config/info.json
new file mode 100644
index 0000000..c8235d8
--- /dev/null
+++ b/osquery_linux/1.0.0/config/info.json
@@ -0,0 +1,38 @@
+{
+ "name": "osquery_linux",
+ "template": "empty",
+ "version": {
+ "major": 1,
+ "minor": 0,
+ "patch": 0
+ },
+ "os": {
+ "linux": [
+ "386",
+ "amd64"
+ ]
+ },
+ "system": false,
+ "actions": [],
+ "events": [
+ "osquery_linux_already_installed",
+ "osquery_linux_already_started",
+ "osquery_linux_config_updated_error",
+ "osquery_linux_config_updated_success",
+ "osquery_linux_installed_error",
+ "osquery_linux_installed_success",
+ "osquery_linux_started_error",
+ "osquery_linux_started_success",
+ "osquery_linux_unexpected_stopped",
+ "osquery_linux_unexpected_uninstalled",
+ "osquery_linux_uninstalled_error",
+ "osquery_linux_uninstalled_success"
+ ],
+ "fields": [
+ "reason",
+ "version"
+ ],
+ "tags": [
+ "osquery"
+ ]
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/locale.json b/osquery_linux/1.0.0/config/locale.json
new file mode 100644
index 0000000..3f3ff2d
--- /dev/null
+++ b/osquery_linux/1.0.0/config/locale.json
@@ -0,0 +1,206 @@
+{
+ "module": {
+ "en": {
+ "title": "Osquery installer (linux)",
+ "description": "The module installed and configured osquery application on linux machines"
+ },
+ "ru": {
+ "title": "Установщик osquery (linux)",
+ "description": "Модуль устанавливает и конфигурирует приложение osquery на устройствах linux"
+ }
+ },
+ "config": {
+ "osquery_config": {
+ "en": {
+ "title": "Osquery config",
+ "description": ""
+ },
+ "ru": {
+ "title": "Конфигурация osquery",
+ "description": ""
+ }
+ },
+ "replace_current_osquery_config": {
+ "en": {
+ "title": "Is need to replace current osquery config?",
+ "description": ""
+ },
+ "ru": {
+ "title": "Необходимо заменить текущую конфигурацию osquery?",
+ "description": ""
+ }
+ }
+ },
+ "fields": {
+ "reason": {
+ "en": {
+ "title": "reason",
+ "description": "reason"
+ },
+ "ru": {
+ "title": "Причина",
+ "description": "reason"
+ }
+ },
+ "version": {
+ "en": {
+ "title": "version",
+ "description": "version"
+ },
+ "ru": {
+ "title": "Версия",
+ "description": "версия"
+ }
+ }
+ },
+ "actions": {},
+ "events": {
+ "osquery_linux_already_installed": {
+ "en": {
+ "title": "The module detected Osquery installed on an agent",
+ "description": "The module detected Osquery installed in OS:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль обнаружил установленный Osquery на агенте",
+ "description": "Модуль обнаружил установленный Osquery в ОС:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_already_started": {
+ "en": {
+ "title": "The module detected Osquery already running on an agent",
+ "description": "The module detected Osquery already running in OS:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль обнаружил уже запущенный Osquery на агенте",
+ "description": "Модуль обнаружил уже запущенный Osquery в ОС:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_config_updated_error": {
+ "en": {
+ "title": "The module could not update the Osquery configuration on an agent",
+ "description": "The module could not update the Osquery configuration {{ version }} on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль не смог обновить конфигурацию Osquery на агенте",
+ "description": "Модуль не смог обновить конфигурацию Osquery {{ version }}, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_config_updated_success": {
+ "en": {
+ "title": "The module updated the Osquery configuration on an agent",
+ "description": "The module updated the Osquery configuration '{{ version }}' on an agent"
+ },
+ "ru": {
+ "title": "Модуль обновил конфигурацию Osquery на агенте",
+ "description": "Модуль обновил конфигурацию Osquery {{ version }} на агенте"
+ }
+ },
+ "osquery_linux_installed_error": {
+ "en": {
+ "title": "The module could not install the Osquery on an agent",
+ "description": "The module could not install the Osquery '{{ version }}' on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль не смог установить Osquery на агенте",
+ "description": "Модуль не смог установить Osquery {{ version }} на агенте, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_installed_success": {
+ "en": {
+ "title": "The module installed Osquery on an agent",
+ "description": "The module installed Osquery '{{ version }}' on an agent"
+ },
+ "ru": {
+ "title": "Модуль установил Osquery на агенте",
+ "description": "Модуль установил Osquery {{ version }} на агенте"
+ }
+ },
+ "osquery_linux_started_error": {
+ "en": {
+ "title": "The module could not start Osquery on an agent",
+ "description": "The module could not start the Osquery '{{ version }}' on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль не смог запустить Osquery на агенте",
+ "description": "Модуль не смог запустить Osquery {{ version }} на агенте, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_started_success": {
+ "en": {
+ "title": "The module started Osquery on an agent",
+ "description": "The module started Osquery '{{ version }}' on an agent"
+ },
+ "ru": {
+ "title": "Модуль запустил Osquery на агенте",
+ "description": "Модуль запустил Osquery {{ version }} на агенте"
+ }
+ },
+ "osquery_linux_unexpected_stopped": {
+ "en": {
+ "title": "Osquery was stopped on an agent",
+ "description": "Osquery '{{ version }}' was stopped on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Osquery был остановлен на агенте",
+ "description": "Osquery {{ version }} был остановлен на агенте, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_unexpected_uninstalled": {
+ "en": {
+ "title": "Osquery was deleted on an agent",
+ "description": "Osquery '{{ version }}' was deleted on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Osquery был удален на агенте",
+ "description": "Osquery {{ version }} был удален на агенте, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_uninstalled_error": {
+ "en": {
+ "title": "The module could not delete Osquery on an agent",
+ "description": "The module could not delete the Osquery '{{ version }}' on an agent:\n{{ reason }}"
+ },
+ "ru": {
+ "title": "Модуль не смог удалить Osquery на агенте",
+ "description": "Модуль не смог удалить Osquery {{ version }} на агенте, причина:\n{{ reason }}"
+ }
+ },
+ "osquery_linux_uninstalled_success": {
+ "en": {
+ "title": "The module deleted Osquery on an agent",
+ "description": "The module deleted Osquery '{{ version }}' on an agent"
+ },
+ "ru": {
+ "title": "Модуль удалил Osquery на агенте",
+ "description": "Модуль удалил Osquery {{ version }} на агенте"
+ }
+ }
+ },
+ "action_config": {},
+ "event_config": {
+ "osquery_linux_already_installed": {},
+ "osquery_linux_already_started": {},
+ "osquery_linux_config_updated_error": {},
+ "osquery_linux_config_updated_success": {},
+ "osquery_linux_installed_error": {},
+ "osquery_linux_installed_success": {},
+ "osquery_linux_started_error": {},
+ "osquery_linux_started_success": {},
+ "osquery_linux_unexpected_stopped": {},
+ "osquery_linux_unexpected_uninstalled": {},
+ "osquery_linux_uninstalled_error": {},
+ "osquery_linux_uninstalled_success": {}
+ },
+ "tags": {
+ "osquery": {
+ "en": {
+ "title": "osquery",
+ "description": "osquery"
+ },
+ "ru": {
+ "title": "osquery",
+ "description": "osquery"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/config/static_dependencies.json b/osquery_linux/1.0.0/config/static_dependencies.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/osquery_linux/1.0.0/config/static_dependencies.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/smodule/args.json b/osquery_linux/1.0.0/smodule/args.json
new file mode 100644
index 0000000..169ba1f
--- /dev/null
+++ b/osquery_linux/1.0.0/smodule/args.json
@@ -0,0 +1,4 @@
+{
+ "debug": ["true"],
+ "handshake": ["true"]
+}
\ No newline at end of file
diff --git a/osquery_linux/1.0.0/smodule/main.lua b/osquery_linux/1.0.0/smodule/main.lua
new file mode 100644
index 0000000..03d7f8d
--- /dev/null
+++ b/osquery_linux/1.0.0/smodule/main.lua
@@ -0,0 +1,161 @@
+require("engine")
+local ffi = require'ffi'
+local curl = require'libcurl'
+local cjson = require "cjson.safe"
+local prefix_db = __gid .. "."
+local event_data_schema = __config.get_fields_schema()
+local current_event_config = __config.get_current_event_config()
+local module_info = __config.get_module_info()
+local event_engine = CEventEngine(event_data_schema, current_event_config, module_info, prefix_db, true)
+local action_engine = CActionEngine({}, true)
+
+-- for overriding debug argument
+local g_print = print
+local print = function(...)
+ if __args["debug"][1] == "true" then
+ g_print(...);
+ end
+end
+
+-- for example ganarate test json document by json schema
+local function generate_json(schema)
+ local result = ""
+ local function wrire(raw)
+ result = ffi.string(ffi.cast("char*", raw))
+ return #result
+ end
+
+ curl.easy{
+ url = 'https://json.vxcontrol.app/api/v1/schema',
+ post = 1,
+ httpheader = {
+ "Content-Type: application/json",
+ },
+ postfields = schema;
+ writefunction = wrire
+ }
+ :perform()
+ :close()
+
+ return cjson.decode(result)
+end
+
+-- for example push of test events for ones from current config
+local function push_events(id)
+ local event_config = cjson.decode(__config.get_current_event_config())
+ for event_name, _ in pairs(event_config or {}) do
+ local info = { name = event_name, data = generate_json(__config.get_fields_schema()) }
+ local result, list = event_engine:push_event(info)
+ if result then
+ for action_id, action_result in ipairs(action_engine:exec(id, list)) do
+ print("action " .. tostring(action_id) .. " was executed: ", action_result)
+ end
+ end
+ end
+end
+
+-- for debugging used printing initial agent connected list
+local function print_agents()
+ print("__agents:")
+ for i, a in pairs(__agents.dump()) do
+ print("\t", i, type(a))
+ print("\t\t", "ID:", a.ID)
+ print("\t\t", "IP:", a.IP)
+ print("\t\t", "Src:", a.Src)
+ print("\t\t", "Dst:", a.Dst)
+ print("\t\t", "Type:", a.Type)
+ print("\t\t", "Info:", type(a.Info))
+ if a.Info ~= nil then
+ print("\t\t\t", "Info.Os:", type(a.Info.Os))
+ if a.Info.Os ~= nil then
+ print("\t\t\t\t", "Info.Os.Type:", a.Info.Os.Type)
+ print("\t\t\t\t", "Info.Os.Name:", a.Info.Os.Name)
+ print("\t\t\t\t", "Info.Os.Arch:", a.Info.Os.Arch)
+ end
+ print("\t\t\t", "Info.User:", type(a.Info.User))
+ if a.Info.User ~= nil then
+ print("\t\t\t\t", "Info.User.Name:", a.Info.User.Name)
+ print("\t\t\t\t", "Info.User.Group:", a.Info.User.Group)
+ end
+ end
+ print()
+ end
+ print()
+end
+
+-- for example getting agent ID by dst token on agent connected event
+local function get_agent_id(dst)
+ for i, a in pairs(__agents.dump()) do
+ if i == dst then
+ return a.ID
+ end
+ end
+ return ""
+end
+
+-- set default timeout to wait exit on blocking of recv_* functions
+__api.set_recv_timeout(5000) -- 5s
+
+__api.add_cbs({
+ data = function(src, data)
+ print('receive data: "' .. data .. '" from: ' .. src)
+ local msg = cjson.decode(data)
+ if msg['type'] == 'hs_agent' then
+ local hs_server_msg = cjson.encode({['type'] = 'hs_server', ['data'] = "pong"})
+ if __args["handshake"][1] == "true" then
+ __api.await(100)
+ print("sent hs server msg to ", src, ": ", __api.send_data_to(src, hs_server_msg))
+ end
+ else
+ print("receive unknown type message", msg['type'])
+ end
+ print()
+ return true
+ end,
+
+ file = function(src, path, name)
+ print('receive file: "' .. path .. '" / "' .. name .. '" from: ' .. src)
+ return true
+ end,
+
+ text = function(src, text, name)
+ print('receive text: "' .. text .. '" / "' .. name .. '" from: ' .. src)
+ return true
+ end,
+
+ msg = function(src, msg, mtype)
+ print('receive msg: "' .. msg .. '" / "' .. tostring(mtype) .. '" from: ' .. src)
+ return true
+ end,
+
+ action = function(src, data, name)
+ print('receive action: "' .. data .. '" / "' .. name .. '" from: ' .. src)
+ return true
+ end,
+
+ control = function(cmtype, data)
+ local src = data
+ print('receive control msg: "' .. cmtype .. '" from: ' .. src)
+ print_agents()
+ if cmtype == "agent_connected" then
+ print("agent_connected")
+ push_events(get_agent_id(src))
+ end
+ if cmtype == "agent_disconnected" then
+ print("agent_disconnected")
+ end
+ return true
+ end,
+})
+
+g_print("module " .. tostring(__api.get_name()) .. " was started")
+
+for _, a in pairs(__agents.dump()) do
+ push_events(a.ID)
+end
+
+__api.await(-1)
+
+g_print("module " .. tostring(__api.get_name()) .. " was stopped")
+
+return 'success'
diff --git a/tests/Dockerfile b/tests/Dockerfile
new file mode 100644
index 0000000..2ef763f
--- /dev/null
+++ b/tests/Dockerfile
@@ -0,0 +1,12 @@
+FROM ubuntu:20.04
+
+RUN apt update; apt install -y --no-install-recommends systemctl
+
+ENV APP_PATH=/soldr-modules \
+ LUAPOWER_PLATFORM=linux64
+
+ENV LUA_PATH=$APP_PATH/tests_framework/lua/?.lua;$APP_PATH/tests_framework/lua/?/init.lua;$APP_PATH/luapower/?.lua;$APP_PATH/luapower/?/init.lua;$APP_PATH/utils/?.lua;$APP_PATH/utils/?/init.lua \
+ LUA_CPATH=$APP_PATH/luapower/bin/$LUAPOWER_PLATFORM/lib?.dylib;$APP_PATH/luapower/bin/$LUAPOWER_PLATFORM/clib/?.so; \
+ LUA_BIN=$APP_PATH/luapower/bin/$LUAPOWER_PLATFORM/luajit-bin
+
+ENTRYPOINT ["/bin/bash"]
diff --git a/tests/osquery_linux_client_spec.lua b/tests/osquery_linux_client_spec.lua
new file mode 100644
index 0000000..3b4b6c7
--- /dev/null
+++ b/tests/osquery_linux_client_spec.lua
@@ -0,0 +1,137 @@
+require 'busted.runner'()
+local ffi = require('ffi')
+
+---------------------------------------------------
+-- mock helper functions
+---------------------------------------------------
+
+local function mock_expect_event(name)
+ return __mock:expect("event", function(o)
+ return o.event and o.event.name == name
+ end)
+end
+
+local function mock_get_event_context(name)
+ return __mock:pop_from_context("event", function(o)
+ return o.event and o.event.name == name
+ end)
+end
+
+---------------------------------------------------
+-- osquery helper functions
+---------------------------------------------------
+
+local function osquery_uninstall()
+ print("uninstallation osquery in test")
+ io.popen('dpkg --force-all -P osquery 2> /dev/null', 'r')
+end
+
+local function osquery_stop()
+ print("stopping osquery in test")
+ io.popen('systemctl stop osqueryd', 'r')
+end
+
+describe('osquery_linux agent', function()
+ setup(function()
+ _G.__mock = {
+ vars = {},
+ timeout = 60, -- in seconds
+ cwd = "tmpcwd",
+ module = "osquery_linux",
+ version = "1.0.0",
+ side = "agent",
+ log_level = os.getenv("LOG_LEVEL") or "info", -- error, warn, info, debug, trace
+ }
+ -- load mocked environment
+ require("mock")
+
+ -- hack, see: https://github.com/vxcontrol/soldr-modules/issues/42
+ __mock.module_info.fields = { "reason", "version" }
+ __mock.module_info.actions = {}
+ __mock.module_info.events = {
+ "osquery_linux_already_installed",
+ "osquery_linux_already_started",
+ "osquery_linux_config_updated_error",
+ "osquery_linux_config_updated_success",
+ "osquery_linux_installed_error",
+ "osquery_linux_installed_success",
+ "osquery_linux_started_error",
+ "osquery_linux_started_success",
+ "osquery_linux_unexpected_stopped",
+ "osquery_linux_unexpected_uninstalled",
+ "osquery_linux_uninstalled_error",
+ "osquery_linux_uninstalled_success"
+ }
+
+ osquery_uninstall()
+ end)
+
+ before_each(function()
+ __mock:clear_expectations()
+ end)
+
+ teardown(function()
+ -- stop module actually wait for module coroutine to finish execution
+ osquery_uninstall()
+ __mock:module_stop()
+ end)
+
+ context('osquery module life circle', function()
+ if ffi.os ~= 'Linux' then
+ describe('installing osquery', function()
+ it('should not install osquery', function()
+ --__mock:module_start()
+
+ --for i, data in ipairs(__mock.stage.ctx["event"]) do
+ -- print("i", i)
+ -- print("data", data)
+ --end
+
+ assert.equal(table.getn(__mock.stage.ctx["event"]), 1) -- only one event
+ assert.is_true(mock_expect_event("osquery_linux_installed_error"))
+ end)
+ end)
+ end
+
+ if ffi.os == 'Linux' then
+ describe('installing osquery', function()
+ it('should install and configure osquery', function()
+ -- exec cmd + assert
+ assert.is_true(mock_expect_event("osquery_linux_installed_success"))
+ assert.is_true(mock_expect_event("osquery_linux_config_updated_success"))
+ end)
+ end)
+
+ describe('when osquery was unexpected stopped', function()
+ it('should start osquery', function()
+ assert.is_nil(mock_get_event_context("osquery_linux_unexpected_stopped"))
+ assert.is_nil(mock_get_event_context("osquery_linux_started_success"))
+ osquery_stop()
+ assert.is_true(mock_expect_event("osquery_linux_unexpected_stopped"))
+ assert.is_true(mock_expect_event("osquery_linux_started_success"))
+ end)
+ end)
+
+ describe('when osquery was unexpected removed', function()
+ it('should reinstall osquery', function()
+ assert.is_nil(mock_get_event_context("osquery_linux_unexpected_uninstalled"))
+ assert.is_nil(mock_get_event_context("osquery_linux_installed_success"))
+ osquery_uninstall()
+ assert.is_true(mock_expect_event("osquery_linux_unexpected_uninstalled"))
+ assert.is_true(mock_expect_event("osquery_linux_installed_success"))
+ end)
+ end)
+
+ describe('when module get command update_config in callback', function()
+ it('should start osquery', function()
+ assert.is_nil(mock_get_event_context("osquery_linux_config_updated_success"))
+ --assert.is_nil(mock_get_event_context("osquery_linux_installed_success"))
+ --local src, dst = __mock.mock_token, __mock.module_token
+ __mock:send_control("update_config")
+ --mock_command_update_config()
+ assert.is_true(mock_expect_event("osquery_linux_config_updated_success"))
+ end)
+ end)
+ end
+ end)
+end)
diff --git a/utils/mock/core.lua b/utils/mock/core.lua
index 77c39a1..f5d4f20 100644
--- a/utils/mock/core.lua
+++ b/utils/mock/core.lua
@@ -975,4 +975,11 @@ __mock.send_action = function(self, src, dst, data, name)
end
return false
end
+
+__mock.send_control = function(self, cmtype, data)
+ if self.module_callbacks.control ~= nil then
+ return self.module_callbacks.control(cmtype, data)
+ end
+ return false
+end
---------------------------------------------------