From 610f6f49ce7dd066549c6ef0a37571a4c6149916 Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Tue, 3 Sep 2019 11:15:35 +0200 Subject: [PATCH 01/14] add debug to S3 repository creation in elasticsearch image Former-commit-id: 0c571ad3f9b80381066de6cd60ac2d3d81038073 --- elasticsearch/config/configure_s3.sh | 18 +++++++++--------- elasticsearch/config/load_settings.sh | 9 ++++++--- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/elasticsearch/config/configure_s3.sh b/elasticsearch/config/configure_s3.sh index 1a160f8e..b09df73b 100644 --- a/elasticsearch/config/configure_s3.sh +++ b/elasticsearch/config/configure_s3.sh @@ -76,15 +76,15 @@ function CreateRepo() repository="$repository_name-$version" s3_path="$path/$version" - curl ${auth} -X PUT "$elastic_ip_port/_snapshot/$repository" -H 'Content-Type: application/json' -d' - { - "type": "s3", - "settings": { - "bucket": "'$bucket_name'", - "base_path": "'$s3_path'" - } - } - ' + >&2 echo "Create S3 repository" + + until curl ${auth} -X PUT "$elastic_ip_port/_snapshot/$repository" -H 'Content-Type: application/json' -d' {"type": "s3", "settings": { "bucket": "'$bucket_name'", "base_path": "'$s3_path'"} }'; do + >&2 echo "Elastic is unavailable, S3 repository not created - sleeping" + sleep 5 + done + + >&2 echo "S3 repository created" + } diff --git a/elasticsearch/config/load_settings.sh b/elasticsearch/config/load_settings.sh index 831fda28..e5a22bdc 100644 --- a/elasticsearch/config/load_settings.sh +++ b/elasticsearch/config/load_settings.sh @@ -100,13 +100,16 @@ done if [ $ENABLE_CONFIGURE_S3 ]; then #Wait for Elasticsearch to be ready to create the repository sleep 10 - + >&2 echo "Configure S3" if [ "x$S3_PATH" != "x" ]; then - + >&2 echo "S3_PATH" + >&2 echo $S3_PATH if [ "x$S3_ELASTIC_MAJOR" != "x" ]; then + >&2 echo "Elasticsearch major version:" + >&2 echo $S3_ELASTIC_MAJOR bash /usr/share/elasticsearch/config/configure_s3.sh $el_url $S3_BUCKET_NAME $S3_PATH $S3_REPOSITORY_NAME $S3_ELASTIC_MAJOR - else + >&2 echo "Elasticserach major version not given" bash /usr/share/elasticsearch/config/configure_s3.sh $el_url $S3_BUCKET_NAME $S3_PATH $S3_REPOSITORY_NAME fi From 9d71a6cbccd4e73768d0a0799d77248818619e5e Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Tue, 3 Sep 2019 11:50:30 +0200 Subject: [PATCH 02/14] install wazuh without custom package Former-commit-id: db733fc849f9ce3b876ce254ffc856072fb5b6bf --- wazuh/Dockerfile | 7 ++----- .../wazuh-manager_3.9.3-3.9.3-2_amd64.deb.REMOVED.git-id | 1 - 2 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 wazuh/config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb.REMOVED.git-id diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index 92081350..b4e32e3a 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -9,8 +9,6 @@ ARG WAZUH_VERSION=3.9.3-1 ENV API_USER="foo" \ API_PASS="bar" -COPY config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb /tmp/wazuh-manager_3.9.3-3.9.3-2_amd64.deb - # Install packages RUN set -x && \ echo "deb https://packages.wazuh.com/3.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list && \ @@ -25,8 +23,8 @@ RUN set -x && \ apt-get upgrade -y -o Dpkg::Options::="--force-confold" && \ apt-get --no-install-recommends --no-install-suggests -y install openssl apt-transport-https vim expect python-boto python-pip python-cryptography && \ apt-get --no-install-recommends --no-install-suggests -y install postfix bsd-mailx mailutils libsasl2-2 ca-certificates libsasl2-modules && \ - apt-get --no-install-recommends --no-install-suggests -y install /tmp/wazuh-manager_3.9.3-3.9.3-2_amd64.deb -RUN apt-get --no-install-recommends --no-install-suggests -y install nodejs wazuh-api=${WAZUH_VERSION} && \ + apt-get --no-install-recommends --no-install-suggests -y install wazuh-manager=${WAZUH_VERSION} && \ + apt-get --no-install-recommends --no-install-suggests -y install nodejs wazuh-api=${WAZUH_VERSION} && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ rm -f /var/ossec/logs/alerts/*/*/* && \ @@ -39,7 +37,6 @@ RUN apt-get --no-install-recommends --no-install-suggests -y install nodejs wazu curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${FILEBEAT_VERSION}-amd64.deb && \ dpkg -i filebeat-${FILEBEAT_VERSION}-amd64.deb && rm -f filebeat-${FILEBEAT_VERSION}-amd64.deb - # Services RUN mkdir /etc/service/wazuh && \ mkdir /etc/service/wazuh-api && \ diff --git a/wazuh/config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb.REMOVED.git-id b/wazuh/config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb.REMOVED.git-id deleted file mode 100644 index 79120799..00000000 --- a/wazuh/config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -a43185ce7f2251e7592c4f686f514881f5a48127 \ No newline at end of file From abfe5097537dec4787f2c2e2e026f523073b4307 Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Tue, 3 Sep 2019 16:21:16 +0200 Subject: [PATCH 03/14] workaround for wazuh-api issue 440 and 443 Former-commit-id: d3cfd2234a3670c703a47755df85d84bf47ff75a --- wazuh/Dockerfile | 7 + wazuh/config/agents.js | 1258 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1265 insertions(+) create mode 100644 wazuh/config/agents.js diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index b4e32e3a..8787646d 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -94,5 +94,12 @@ COPY config/01-wazuh.sh /entrypoint-scripts/01-wazuh.sh RUN chmod 755 /entrypoint.sh && \ chmod 755 /entrypoint-scripts/01-wazuh.sh +# Workaround. +# Issues: +# https://github.com/wazuh/wazuh-api/issues/440 +# https://github.com/wazuh/wazuh-api/issues/443 +COPY --chown=root:ossec config/agents.js /var/ossec/api/controllers/agents.js +RUN chmod 770 /var/ossec/api/controllers/agents.js + # Run all services ENTRYPOINT ["/entrypoint.sh"] diff --git a/wazuh/config/agents.js b/wazuh/config/agents.js new file mode 100644 index 00000000..e0313412 --- /dev/null +++ b/wazuh/config/agents.js @@ -0,0 +1,1258 @@ +/** + * Wazuh RESTful API + * Copyright (C) 2015-2019 Wazuh, Inc. All rights reserved. + * Wazuh.com + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 2) as published by the FSF - Free Software + * Foundation. + */ + + +var router = require('express').Router(); + +/** + * @api {get} /agents Get all agents + * @apiName GetAgents + * @apiGroup Info + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [select] List of selected fields separated by commas. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. Use commas to enter multiple statuses. + * @apiParam {String} [q] Query to filter results by. For example q="status=Active" + * @apiParam {String} [older_than] Filters out disconnected agents for longer than specified. Time in seconds, '[n_days]d', '[n_hours]h', '[n_minutes]m' or '[n_seconds]s'. For never connected agents, uses the register date. + * @apiParam {String} [os.platform] Filters by OS platform. + * @apiParam {String} [os.version] Filters by OS version. + * @apiParam {String} [os.name] Filters by OS name. + * @apiParam {String} [manager] Filters by manager hostname to which agents are connected. + * @apiParam {String} [version] Filters by agents version. + * @apiParam {String} [group] Filters by group of agents. + * @apiParam {String} [node_name] Filters by node name. + * @apiParam {String} [name] Filters by agent name. + * @apiParam {String} [ip] Filters by agent IP. + * + * @apiDescription Returns a list with the available agents. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents?pretty&offset=0&limit=5&sort=-ip,name" + * + */ +router.get('/', cache(), function(req, res) { + var query_checks = {'status':'alphanumeric_param', 'os.platform':'alphanumeric_param', + 'os.version':'alphanumeric_param', 'manager':'alphanumeric_param', + 'version':'alphanumeric_param', 'node_name': 'alphanumeric_param', + 'older_than':'timeframe_type', 'group':'alphanumeric_param', + 'name': 'alphanumeric_param', 'ip': 'ips', + 'os.name':'alphanumeric_param' }; + templates.array_request("/agents", req, res, "agents", {}, query_checks); +}) + +/** + * @api {get} /agents/summary Get agents summary + * @apiName GetAgentsSummary + * @apiGroup Info + * + * + * @apiDescription Returns a summary of the available agents. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/summary?pretty" + * + */ +router.get('/summary', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/summary"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/summary', 'arguments': {}}; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/summary/os Get OS summary + * @apiName GetOSSummary + * @apiGroup Info + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns a summary of the OS. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/summary/os?pretty" + * + */ +router.get('/summary/os', cache(), function(req, res) { + templates.single_field_array_request("/agents/summary/os", req, res, "agents"); +}) + +/** + * @api {get} /agents/no_group Get agents without group + * @apiName GetAgentsWithoutGroup + * @apiGroup Groups + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns a list with the available agents without group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/no_group?pretty" + * + */ +router.get('/no_group', cache(), function (req, res) { + query_checks = {'status': 'alphanumeric_param'} + templates.array_request('/agents/no_group', req, res, "agents", {}, query_checks); +}) + +/** + * @api {get} /agents/groups Get groups + * @apiName GetAgentGroups + * @apiGroup Groups + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [hash] Select algorithm to generate the sum. + * + * @apiDescription Returns the list of existing agent groups. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups?pretty" + * + */ +router.get('/groups', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers', 'sort':'sort_param', + 'search':'search_param', 'hash':'names'}; + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + if ('sort' in req.query) + data_request['arguments']['sort'] = filter.sort_param_to_json(req.query.sort); + if ('search' in req.query) + data_request['arguments']['search'] = filter.search_param_to_json(req.query.search); + if ('hash' in req.query) + data_request['arguments']['hash_algorithm'] = req.query.hash + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id Get agents in a group + * @apiName GetAgentGroupID + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. + * @apiParam {String} [q] Query to filter results by. + * + * @apiDescription Returns the list of agents in a group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/dmz?pretty" + * + */ +router.get('/groups/:group_id', cache(), function(req, res) { + param_checks = {'group_id':'names'}; + query_checks = {'status': 'alphanumeric_param'} + + templates.array_request('/agents/groups/:group_id', req, res, "agents", param_checks, query_checks); +}); + + +/** + * @api {get} /agents/groups/:group_id/configuration Get group configuration + * @apiName GetAgentGroupConfiguration + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * + * @apiDescription Returns the group configuration (agent.conf). + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/dmz/configuration?pretty" + * + */ +router.get('/groups/:group_id/configuration', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/configuration"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/configuration', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers'}; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/groups/:group_id/configuration Put configuration file (agent.conf) into a group + * @apiName PostAgentGroupConfiguration + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Upload the group configuration (agent.conf). + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -X POST -H 'Content-type: application/xml' -d @agent.conf.xml "https://127.0.0.1:55000/agents/groups/dmz/configuration?pretty" -k + * + */ +router.post('/groups/:group_id/configuration', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/groups/:group_id/configuration"); + + var data_request = {'function': 'POST/agents/groups/:group_id/configuration', 'arguments': {}}; + var filters = {'group_id': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + if (!filter.check_xml(req.body, req, res)) return; + + data_request['arguments']['group_id'] = req.params.group_id; + try { + data_request['arguments']['tmp_file'] = require('../helpers/files').tmp_file_creator(req.body); + } catch(err) { + res_h.bad_request(req, res, 702, err); + return; + } + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/groups/:group_id/files/:file_name Upload file into a group + * @apiName PostAgentGroupFile + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {String} file_name File name. + * + * @apiDescription Upload a file to a group. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -X POST -H 'Content-type: application/xml' -d @agent.conf.xml "https://127.0.0.1:55000/agents/groups/dmz/files/agent.conf?pretty" -k + * + */ +router.post('/groups/:group_id/files/:file_name', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/groups/:group_id/files/:file_name"); + + var data_request = {'function': 'POST/agents/groups/:group_id/files/:file_name', 'arguments': {}}; + var filters = {'group_id': 'names', 'file_name': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + if (!filter.check_xml(req.body, req, res)) return; + + data_request['arguments']['group_id'] = req.params.group_id; + try { + data_request['arguments']['tmp_file'] = require('../helpers/files').tmp_file_creator(req.body); + } catch(err) { + res_h.bad_request(req, res, 702, err); + return; + } + data_request['arguments']['file_name'] = req.params.file_name; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id/files/:filename Get a file in group + * @apiName GetAgentGroupFile + * @apiGroup Groups + * + * @apiParam {String} [group_id] Group ID. + * @apiParam {String} [file_name] Filename + * @apiParam {String="conf","rootkit_files", "rootkit_trojans", "rcl"} [type] Type of file. + * @apiParam {String="json","xml"} [format] Optional. Output format (JSON, XML). + * + * @apiDescription Returns the specified file belonging to the group parsed to JSON. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/webserver/files/cis_debian_linux_rcl.txt?pretty" + * + */ +router.get('/groups/:group_id/files/:filename', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/files/:filename"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/files/:filename', 'arguments': {}}; + var filters = {'group_id': 'names', 'filename': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['filename'] = req.params.filename; + + if (!filter.check(req.query, {'type': 'names', 'format': 'format'}, req, res)) // Filter with error + return; + + if ('type' in req.query) + data_request['arguments']['type_conf'] = req.query.type; + + if ('format' in req.query) + data_request['arguments']['return_format'] = req.query.format; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id/files Get group files + * @apiName GetAgentGroupFiles + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [hash] Hash algorithm to use to calculate files checksums. + * + * @apiDescription Returns the files belonging to the group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/default/files?pretty" + * + */ +router.get('/groups/:group_id/files', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/files"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/files', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers', 'sort':'sort_param', 'search':'search_param', 'hash':'names'}; + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + if ('sort' in req.query) + data_request['arguments']['sort'] = filter.sort_param_to_json(req.query.sort); + if ('search' in req.query) + data_request['arguments']['search'] = filter.search_param_to_json(req.query.search); + if ('hash' in req.query) + data_request['arguments']['hash_algorithm'] = req.query.hash; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/outdated Get outdated agents + * @apiName GetOutdatedAgents + * @apiGroup Upgrade + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns the list of outdated agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/outdated?pretty" + * + */ +router.get('/outdated', cache(), function(req, res) { + templates.array_request("/agents/outdated",req,res,"agents"); +}) + + +/** + * @api {get} /agents/name/:agent_name Get an agent by its name + * @apiName GetAgentsName + * @apiGroup Info + * + * @apiParam {String} agent_name Agent name. + * @apiParam {String} [select] List of selected fields separated by commas. + * + * @apiDescription Returns various information from an agent called :agent_name. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/name/NewHost?pretty" + * + */ +router.get('/name/:agent_name', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/name/:agent_name"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/name/:agent_name', 'arguments': {}}; + var filters = {'select':'select_param'}; + + if (!filter.check(req.params, {'agent_name':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_name'] = req.params.agent_name; + + if(!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('select' in req.query) + data_request['arguments']['select'] = + filter.select_param_to_json(req.query.select); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + +}) + +/** + * @api {get} /agents/:agent_id Get an agent + * @apiName GetAgentsID + * @apiGroup Info + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String} [select] List of selected fields separated by commas. + * + * @apiDescription Returns various information from an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/000?pretty" + * + */ +router.get('/:agent_id', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/:agent_id', 'arguments': {}}; + var filters = {'select':'select_param'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + if(!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('select' in req.query) + data_request['arguments']['select'] = + filter.select_param_to_json(req.query.select); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + +}) + +/** + * @api {get} /agents/:agent_id/key Get agent key + * @apiName GetAgentsKey + * @apiGroup Key + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Returns the key of an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/004/key?pretty" + * + */ +router.get('/:agent_id/key', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/key"); + + var data_request = {'function': '/agents/:agent_id/key', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/:agent_id/upgrade_result Get upgrade result from agent + * @apiName GetUpgradeResult + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {Number} [timeout=3] Seconds to wait for the agent to respond. + * + * @apiDescription Returns the upgrade result from an agent. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/003/upgrade_result?pretty" + * + */ +router.get('/:agent_id/upgrade_result', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/upgrade_result"); + + var data_request = {'function': '/agents/:agent_id/upgrade_result', 'arguments': {}}; + + if (!filter.check(req.query, {'timeout':'numbers'}, req, res)) // Filter with error + return; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('timeout' in req.query) + data_request['arguments']['timeout'] = req.query.timeout; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {get} /agents/:agent_id/config/:component/:configuration Get active configuration + * @apiName GetConfig + * @apiGroup Config + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String="agent","agentless","analysis","auth","com","csyslog","integrator","logcollector","mail","monitor","request","syscheck","wmodules"} component Selected component. + * @apiParam {String="client","buffer","labels","internal","agentless","global","active_response","alerts","command","rules","decoders","internal","auth","active-response","internal","cluster","csyslog","integration","localfile","socket","remote","syscheck","rootcheck","wmodules"} configuration Configuration to read. + * + * @apiDescription Returns the active configuration in JSON format. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/001/config/logcollector/localfile?pretty" + * + */ + router.get('/:agent_id/config/:component/:configuration', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/config/:component/:configuration"); + + var data_request = {'function': '/agents/:agent_id/config/:component/:configuration', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers', 'component':'names', 'configuration':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['component'] = req.params.component; + data_request['arguments']['configuration'] = req.params.configuration; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + /** + * @api {get} /agents/:agent_id/group/is_sync Get sync status of agent + * @apiName GetSync + * @apiGroup Group + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Returns the sync status in JSON format + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/001/group/is_sync?pretty" + * + */ +router.get('/:agent_id/group/is_sync', function(req, res) { + param_checks = {'agent_id': 'numbers'}; + templates.array_request('/agents/:agent_id/group/is_sync', req, res, "agents", param_checks); +}) + + +/** + * @api {put} /agents/restart Restart all agents + * @apiName PutAgentsRestart + * @apiGroup Restart + * + * @apiDescription Restarts all agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/restart?pretty" + * + */ +router.put('/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/restart"); + + var data_request = {'function': 'PUT/agents/restart', 'arguments': {}}; + + data_request['arguments']['restart_all'] = 'True'; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/restart Restart a list of agents + * @apiName PostAgentListRestart + * @apiGroup Restart + * + * @apiParam {String[]} ids Array of agent ID's. + * + * @apiDescription Restarts a list of agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X POST -H "Content-Type:application/json" -d '{"ids":["002","004"]}' "https://127.0.0.1:55000/agents/restart?pretty" + * + */ +router.post('/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/restart"); + + var data_request = {'function': 'POST/agents/restart', 'arguments': {}}; + + if (!filter.check(req.body, {'ids':'array_numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.body.ids; + + if ('ids' in req.body){ + data_request['arguments']['agent_id'] = req.body.ids; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + +/** + * @api {put} /agents/:agent_id/restart Restart an agent + * @apiName PutAgentsRestartId + * @apiGroup Restart + * + * @apiParam {Number} agent_id Agent unique ID. + * + * @apiDescription Restarts the specified agent. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/007/restart?pretty" + * + */ +router.put('/:agent_id/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/restart"); + + var data_request = {'function': 'PUT/agents/:agent_id/restart', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/upgrade Upgrade agent using online repository + * @apiName PutAgentsUpgradeId + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} [wpk_repo] WPK repository. + * @apiParam {String} [version] Wazuh version. + * @apiParam {Boolean} [use_http] Use protocol HTTP. If it is false use HTTPS. By default the value is set to false. + * @apiParam {number="0","1"} [force] Force upgrade. + * + * @apiDescription Upgrade the agent using a WPK file from online repository. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/002/upgrade?pretty" + * + */ +router.put('/:agent_id/upgrade', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/upgrade"); + + var data_request = {'function': 'PUT/agents/:agent_id/upgrade', 'arguments': {}}; + var filters = { 'wpk_repo': 'paths', 'version': 'alphanumeric_param', 'force': 'numbers', 'use_http': 'boolean'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) + return; + + if (!filter.check(req.query, filters, req, res)) + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('wpk_repo' in req.query) + data_request['arguments']['wpk_repo'] = req.query.wpk_repo; + if ('version' in req.query) + data_request['arguments']['version'] = req.query.version; + if ('force' in req.query) + data_request['arguments']['force'] = req.query.force; + if ('use_http' in req.query) + data_request['arguments']['use_http'] = (req.query.use_http == true || req.query.use_http == 'true'); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/upgrade_custom Upgrade agent using custom file + * @apiName PutAgentsUpgradeCustomId + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} file_path Path to the WPK file. The file must be on a folder on the Wazuh's installation directory (by default, ``/var/ossec``). + * @apiParam {String} installer Installation script. + * + * @apiDescription Upgrade the agent using a custom file. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/002/upgrade_custom?pretty" + * + */ +router.put('/:agent_id/upgrade_custom', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/upgrade_custom"); + + var data_request = {'function': 'PUT/agents/:agent_id/upgrade_custom', 'arguments': {}}; + var filters = {'file_path':'paths', 'installer':'alphanumeric_param'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) + return; + + if (!filter.check(req.query, filters, req, res)) + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('file_path' in req.query) + data_request['arguments']['file_path'] = req.query.file_path; + if ('installer' in req.query) + data_request['arguments']['installer'] = req.query.installer; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_name Add agent (quick method) + * @apiName PutAddAgentName + * @apiGroup Add + * + * @apiParam {String} agent_name Agent name. + * + * @apiDescription Adds a new agent with name :agent_name. This agent will use ANY as IP. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/myNewAgent?pretty" + * + */ +router.put('/:agent_name', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_name"); + + var data_request = {'function': 'PUT/agents/:agent_name', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_name':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['name'] = req.params.agent_name; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/groups/:group_id Create a group + * @apiName PutGroup + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Creates a new group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/groups/pciserver?pretty" + * + */ +router.put('/groups/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/groups/:group_id"); + + var data_request = {'function': 'PUT/agents/groups/:group_id', 'arguments': {}}; + var filters = {'group_id':'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/group/:group_id Add agent group + * @apiName PutGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} group_id Group ID. + * @apiParam {Boolean} force_single_group Wheter to append new group to current agent's group or replace it. + * + * @apiDescription Adds an agent to the specified group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/004/group/dmz?pretty" + * + */ +router.put('/:agent_id/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/group/:group_id"); + + var data_request = {'function': 'PUT/agents/:agent_id/group/:group_id', 'arguments': {}}; + var filters = {'agent_id':'numbers', 'group_id':'names', 'force_single_group': 'empty_boolean'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['replace'] = 'force_single_group' in req.query && req.query.replace != 'false' ? true : false; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {post} /agents/group/:group_id Add a list of agents to a group + * @apiName PostGroupAgents + * @apiGroup Groups + * + * @apiParam {String[]} ids List of agents ID. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Adds a list of agents to the specified group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -X POST -H "Content-Type:application/json" -d '{"ids":["001","002"]}' "https://localhost:55000/agents/group/dmz?pretty" -k + * + */ +router.post('/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/group/:group_id"); + + var data_request = {'function': 'POST/agents/group/:group_id', 'arguments': {}}; + var filters = {'group_id': 'names', 'ids': 'array_numbers'} + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['agent_id_list'] = req.body.ids; + + if ('ids' in req.body){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + + +/** + * @api {delete} /agents/groups Delete a list of groups + * @apiName DeleteAgentsGroups + * @apiGroup Delete + * + * @apiParam {String} ids Name of groups separated by commas. + * + * @apiDescription Removes a list of groups. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/groups?ids=webserver,database&pretty" + * + */ +router.delete('/groups', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/groups"); + + var data_request = {'function': 'DELETE/agents/groups', 'arguments': {}}; + + if (!filter.check(req.query, {'ids': 'array_names'}, req, res)) // Filter with error + return; + + if ('ids' in req.query){ + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['group_id'] = req.query.ids.split(','); + } else { + data_request['arguments']['group_id'] = req.query.ids; + } + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + + +/** + * @api {delete} /agents/:agent_id Delete an agent + * @apiName DeleteAgentId + * @apiGroup Delete + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {Boolean} purge Delete an agent from the key store. This parameter is only valid if purge is set to no in the manager's ossec.conf. + * + * @apiDescription Removes an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/008?pretty&purge" + * + */ +router.delete('/:agent_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id"); + + var data_request = {'function': 'DELETE/agents/:agent_id', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['purge'] = 'purge' in req.query && req.query.purge != 'false' ? true : false; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/:agent_id/group Remove all agent groups. + * @apiName DeleteGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Removes the group of the agent. The agent will automatically revert to the 'default' group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/004/group?pretty" + * + */ +router.delete('/:agent_id/group', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id/group"); + + var data_request = {'function': 'DELETE/agents/:agent_id/group', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/:agent_id/group/:group_id Remove a single group of an agent + * @apiName DeleteGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Remove the group of the agent but will leave the rest of its group if it belongs to a multigroup. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/004/group/dmz?pretty" + * + */ +router.delete('/:agent_id/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id/group/:group_id"); + + var data_request = {'function': 'DELETE/agents/:agent_id/group/:group_id', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers', 'group_id': 'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/group/:group_id Remove a single group of multiple agents + * @apiName DeleteGroupAgents + * @apiGroup Groups + * + * @apiParam {String} ids Agent IDs separated by commas. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Remove a list of agents of a group + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://localhost:55000/agents/group/dmz?ids=001,002&pretty" + * + */ +router.delete('/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/group/:group_id"); + + var data_request = {'function': 'DELETE/agents/group/:group_id', 'arguments': {}}; + var filters_param = {'group_id': 'names'} + var filters_query = {'ids': 'array_numbers'} + + if (!filter.check(req.params, filters_param, req, res)) // Filter with error (path params) + return; + if (!filter.check(req.query, filters_query, req, res)) // Filter with error (query params) + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + if ('ids' in req.query) { + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['agent_id_list'] = req.query.ids.split(','); + } else { + data_request['arguments']['agent_id_list'] = req.query.ids; + } + } + + if ('ids' in req.query){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + +/** + * @api {delete} /agents/groups/:group_id Remove group + * @apiName DeleteGroupAgents + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Removes the group. Agents that were assigned to the removed group will automatically revert to the 'default' group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/groups/dmz?pretty" + * + */ +router.delete('/groups/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/groups/:group_id"); + + var data_request = {'function': 'DELETE/agents/groups/:group_id', 'arguments': {}}; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents Delete agents + * @apiName DeleteAgents + * @apiGroup Delete + * + * @apiParam {String} ids Agent IDs separated by commas. + * @apiParam {Boolean} purge Delete an agent from the key store. This parameter is only valid if purge is set to no in the manager's ossec.conf. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. Use commas to enter multiple statuses. + * @apiParam {String} older_than Filters out disconnected agents for longer than specified. Time in seconds, '[n_days]d', '[n_hours]h', '[n_minutes]m' or '[n_seconds]s'. For never connected agents, uses the register date. Default value: 7d. + * + * @apiDescription Removes agents, using a list of them or a criterion based on the status or time of the last connection. The Wazuh API must be restarted after removing an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents?older_than=10s&purge&ids=003,005&pretty" + * + */ +router.delete('/', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents"); + + var data_request = {'function': 'DELETE/agents/', 'arguments': {}}; + var filters_query = {'older_than': 'timeframe_type', 'status': 'alphanumeric_param', 'purge': 'empty_boolean', + 'ids': 'array_numbers'}; + + if (!filter.check(req.query, filters_query, req, res)) // Filter with error + return; + + if (!('ids' in req.query) && !('status' in req.query)){ + res_h.bad_request(req, res, 604, "Missing field: You have to specified 'ids' or status."); + return; + } + + if ('purge' in req.query && req.query.purge != 'false') + data_request['arguments']['purge'] = true; + else + data_request['arguments']['purge'] = false; + + if ('ids' in req.query) { + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['list_agent_ids'] = req.query.ids.split(','); + } else { + data_request['arguments']['list_agent_ids'] = req.query.ids; + } + } + + if ('older_than' in req.query) + data_request['arguments']['older_than'] = req.query.older_than; + + if ('status' in req.query) + data_request['arguments']['status'] = req.query.status; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {post} /agents Add agent + * @apiName PostAddAgentId + * @apiGroup Add + * + * @apiParam {String} name Agent name. + * @apiParam {String="IP","IP/NET", "ANY"} [ip] If this is not included, the API will get the IP automatically. If you are behind a proxy, you must set the option config.BehindProxyServer to yes at config.js. + * @apiParam {Number} [force] Remove the old agent with the same IP if disconnected since seconds. + * + * @apiDescription Add a new agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X POST -d '{"name":"NewHost","ip":"10.0.0.9"}' -H 'Content-Type:application/json' "https://127.0.0.1:55000/agents?pretty" + * + */ +router.post('/', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents"); + + // If not IP set, we will use source IP. + var ip = req.body.ip; + if ( !ip ){ + // If we hare behind a proxy server, use headers. + if (config.BehindProxyServer.toLowerCase() == "yes") + if (!req.headers.hasOwnProperty('x-forwarded-for')){ + res_h.bad_request(req, res, 800); + return; + } + else + ip = req.headers['x-forwarded-for']; + else + ip = req.connection.remoteAddress; + + // Extract IPv4 from IPv6 hybrid notation + if (ip.indexOf("::ffff:") > -1) { + var ipFiltered = ip.split(":"); + ip = ipFiltered[ipFiltered.length-1]; + logger.debug("Hybrid IPv6 IP filtered: " + ip); + } + logger.debug("Add agent with automatic IP: " + ip); + } + req.body.ip = ip; + + var data_request = {'function': 'POST/agents', 'arguments': {}}; + var filters = {'name':'names', 'ip':'ips', 'force':'numbers'}; + + if (!filter.check(req.body, filters, req, res)) // Filter with error + return; + + data_request['arguments']['ip'] = req.body.ip; + + if ('name' in req.body){ + data_request['arguments']['name'] = req.body.name; + if ('force' in req.body){ + data_request['arguments']['force'] = req.body.force; + } + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'name'"); +}) + + +/** + * @api {post} /agents/insert Insert agent + * @apiName PostInsertAgent + * @apiGroup Add + * + * @apiParam {String} name Agent name. + * @apiParam {String="IP","IP/NET", "ANY"} [ip] If this is not included, the API will get the IP automatically. If you are behind a proxy, you must set the option config.BehindProxyServer to yes at config.js. + * @apiParam {String} id Agent ID. + * @apiParam {String} key Agent key. Minimum length: 64 characters. Allowed values: ^[a-zA-Z0-9]+$ + * @apiParam {Number} [force] Remove the old agent the with same IP if disconnected since seconds. + * + * @apiDescription Insert an agent with an existing id and key. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X POST -d '{"name":"NewHost_2","ip":"10.0.10.10","id":"123","key":"1abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi64"}' -H 'Content-Type:application/json' "https://127.0.0.1:55000/agents/insert?pretty" + * + */ +router.post('/insert', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/insert"); + + // If not IP set, we will use source IP. + var ip = req.body.ip; + if ( !ip ){ + // If we hare behind a proxy server, use headers. + if (config.BehindProxyServer.toLowerCase() == "yes") + if (!req.headers.hasOwnProperty('x-forwarded-for')){ + res_h.bad_request(req, res, 800); + return; + } + else + ip = req.headers['x-forwarded-for']; + else + ip = req.connection.remoteAddress; + + // Extract IPv4 from IPv6 hybrid notation + if (ip.indexOf("::ffff:") > -1) { + var ipFiltered = ip.split(":"); + ip = ipFiltered[ipFiltered.length-1]; + logger.debug("Hybrid IPv6 IP filtered: " + ip); + } + logger.debug("Add agent with automatic IP: " + ip); + } + req.body.ip = ip; + + var data_request = {'function': 'POST/agents/insert', 'arguments': {}}; + var filters = {'name':'names', 'ip':'ips', 'id':'numbers', 'key': 'ossec_key', 'force':'numbers'}; + + if (!filter.check(req.body, filters, req, res)) // Filter with error + return; + + data_request['arguments']['id'] = req.body.id; + data_request['arguments']['name'] = req.body.name; + data_request['arguments']['ip'] = req.body.ip; + data_request['arguments']['key'] = req.body.key; + if ('force' in req.body){ + data_request['arguments']['force'] = req.body.force; + } + + if ('id' in req.body && 'name' in req.body && 'ip' in req.body && 'key' in req.body){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing fields. Mandatory fields: id, name, ip, key"); +}) + + + +/** + * @api {get} /agents/stats/distinct Get distinct fields in agents + * @apiName GetdistinctAgents + * @apiGroup Stats + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [fields] List of fields affecting the operation. + * @apiParam {String} [select] List of selected fields separated by commas. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns all the different combinations that agents have for the selected fields. It also indicates the total number of agents that have each combination. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/stats/distinct?pretty&fields=os.platform" + * + */ +router.get('/stats/distinct', cache(), function (req, res) { + query_checks = {'fields':'select_param'}; + templates.array_request('/agents/stats/distinct', req, res, "agents", {}, query_checks); +}) + +module.exports = router; \ No newline at end of file From 131d25979ba10e2c1361987ac05f04c53fe6570e Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Tue, 3 Sep 2019 16:31:55 +0200 Subject: [PATCH 04/14] improve workaround description Former-commit-id: 24da1f4d0f53887deb121df6153a2f9b6586f491 --- wazuh/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index 8787646d..d71f06b4 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -95,7 +95,7 @@ RUN chmod 755 /entrypoint.sh && \ chmod 755 /entrypoint-scripts/01-wazuh.sh # Workaround. -# Issues: +# Issues: Wazuh-api # https://github.com/wazuh/wazuh-api/issues/440 # https://github.com/wazuh/wazuh-api/issues/443 COPY --chown=root:ossec config/agents.js /var/ossec/api/controllers/agents.js From 6656fddf70e9748abe85eaecf495ea2b8d5ff5b0 Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Wed, 4 Sep 2019 08:32:56 +0200 Subject: [PATCH 05/14] Added new volume: wodles folder Former-commit-id: 36e3fa403d59ed101c1a3afa21444215e38c86a4 --- wazuh/Dockerfile | 1 + wazuh/config/permanent_data.env | 16 ++++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index 92081350..978eb162 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -83,6 +83,7 @@ VOLUME ["/var/ossec/queue"] VOLUME ["/var/ossec/var/multigroups"] VOLUME ["/var/ossec/integrations"] VOLUME ["/var/ossec/active-response/bin"] +VOLUME ["/var/ossec/wodles"] VOLUME ["/etc/filebeat"] VOLUME ["/etc/postfix"] VOLUME ["/var/lib/filebeat"] diff --git a/wazuh/config/permanent_data.env b/wazuh/config/permanent_data.env index 2ae1126c..fbff407e 100644 --- a/wazuh/config/permanent_data.env +++ b/wazuh/config/permanent_data.env @@ -36,6 +36,22 @@ PERMANENT_DATA_EXCP[((i++))]="/var/ossec/active-response/bin/pf.sh" PERMANENT_DATA_EXCP[((i++))]="/var/ossec/active-response/bin/restart-ossec.sh" PERMANENT_DATA_EXCP[((i++))]="/var/ossec/active-response/bin/restart.sh" PERMANENT_DATA_EXCP[((i++))]="/var/ossec/active-response/bin/route-null.sh" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/aws/aws-s3" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/aws/aws-s3.py" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/azure/azure-logs" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/azure/azure-logs.py" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/docker/DockerListener" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/docker/DockerListener.py" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/oscap" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/oscap.py" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/template_oval.xsl" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/template_xccdf.xsl" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/cve-debian-8-oval.xml" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/cve-debian-9-oval.xml" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/cve-ubuntu-xenial-oval.xml" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/ssg-debian-8-ds.xml" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/ssg-ubuntu-1404-ds.xml" +PERMANENT_DATA_EXCP[((i++))]="/var/ossec/wodles/oscap/content/ssg-ubuntu-1604-ds.xml" export PERMANENT_DATA_EXCP # Files mounted in a volume that should be deleted From d1eb6e7b98a274129b8862f66665af98000bf000 Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Wed, 4 Sep 2019 08:38:43 +0200 Subject: [PATCH 06/14] Removed chmod command in entrypoint Former-commit-id: 9460780adb422330b6d61cc3ec21791efc6f904e --- wazuh/config/01-wazuh.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wazuh/config/01-wazuh.sh b/wazuh/config/01-wazuh.sh index e0f005b0..56ca5fcf 100644 --- a/wazuh/config/01-wazuh.sh +++ b/wazuh/config/01-wazuh.sh @@ -258,10 +258,10 @@ main() { # Grant proper permissions # When modifiying some files using the Wazuh API (i.e. /var/ossec/etc/ossec.conf), group rw permissions are needed for changes to take place. # https://github.com/wazuh/wazuh/issues/3647 - chmod -R g+rw ${WAZUH_INSTALL_PATH} + #chmod -R g+rw ${WAZUH_INSTALL_PATH} # Files inside /var/ossec/integrations should not have write permissions for group and other. - chmod -R 750 "/var/ossec/integrations/" + #chmod -R 750 "/var/ossec/integrations/" } main From 2918502fd1d323449478f19997d2688cf36c480b Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Wed, 4 Sep 2019 11:11:59 +0200 Subject: [PATCH 07/14] save original elasticserach.yml Former-commit-id: eed444bbbb54d99fe098c2e10df4e02bf2260dd7 --- elasticsearch/config/10-config_cluster.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/elasticsearch/config/10-config_cluster.sh b/elasticsearch/config/10-config_cluster.sh index b4063825..1e200c8d 100644 --- a/elasticsearch/config/10-config_cluster.sh +++ b/elasticsearch/config/10-config_cluster.sh @@ -3,6 +3,9 @@ elastic_config_file="/usr/share/elasticsearch/config/elasticsearch.yml" +original_file="/usr/share/elasticsearch/config/original-elasticsearch.yml" + +cp $elastic_config_file $original_file # If Elasticsearch cluster is enable if [[ $ELASTIC_CLUSTER == "true" ]] From 3a06c32e62b0c2c739659e73ccde23f31334c373 Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Wed, 4 Sep 2019 11:26:06 +0200 Subject: [PATCH 08/14] add minimun_master_nodes Former-commit-id: 816549c3b6b444b36da16aee169221d04980a664 --- elasticsearch/config/10-config_cluster.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elasticsearch/config/10-config_cluster.sh b/elasticsearch/config/10-config_cluster.sh index 1e200c8d..51924331 100644 --- a/elasticsearch/config/10-config_cluster.sh +++ b/elasticsearch/config/10-config_cluster.sh @@ -13,7 +13,6 @@ then # Set the cluster.name and discovery.zen.minimun_master_nodes variables sed -i 's:cluster.name\: "docker-cluster":cluster.name\: "'$CLUSTER_NAME'":g' $elastic_config_file - sed -i 's:discovery.zen.minimum_master_nodes\: 1:discovery.zen.minimum_master_nodes\: '$CLUSTER_NUMBER_OF_MASTERS':g' $elastic_config_file # Add the cluster configuration echo " @@ -31,6 +30,7 @@ bootstrap: discovery: zen: ping.unicast.hosts: ${CLUSTER_DISCOVERY_SERVICE} + minimum_master_nodes: ${CLUSTER_NUMBER_OF_MASTERS} " >> $elastic_config_file fi From 27c37d808a4ade33f8ee9ff933ea86d5ce5c0c5e Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Wed, 4 Sep 2019 12:29:02 +0200 Subject: [PATCH 09/14] Changed versions: wazuh 3.9.4 and kibana 6.8.2 Former-commit-id: 6b13810e6a709ee6a72955081c90bee6d1a5d202 --- elasticsearch/Dockerfile | 6 +++--- kibana/Dockerfile | 4 ++-- logstash/Dockerfile | 2 +- wazuh/Dockerfile | 20 ++++++++++++-------- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/elasticsearch/Dockerfile b/elasticsearch/Dockerfile index 70f1faed..c2073891 100644 --- a/elasticsearch/Dockerfile +++ b/elasticsearch/Dockerfile @@ -1,5 +1,5 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/elasticsearch/elasticsearch:6.8.1 +FROM docker.elastic.co/elasticsearch/elasticsearch:6.8.2 ENV ALERTS_SHARDS="1" \ ALERTS_REPLICAS="0" @@ -11,7 +11,7 @@ ENV XPACK_ML="true" ENV ENABLE_CONFIGURE_S3="false" -ENV TEMPLATE_VERSION=v3.9.3 +ENV TEMPLATE_VERSION=v3.9.4 # This CA is created for testing. Please set your own CA zip containing the key and the signed certificate. @@ -61,7 +61,7 @@ COPY --chown=elasticsearch:elasticsearch ./config/load_settings.sh ./ RUN chmod +x ./load_settings.sh -RUN bin/elasticsearch-plugin install --batch https://artifacts.elastic.co/downloads/elasticsearch-plugins/repository-s3/repository-s3-6.8.1.zip +RUN bin/elasticsearch-plugin install --batch https://artifacts.elastic.co/downloads/elasticsearch-plugins/repository-s3/repository-s3-6.8.2.zip COPY config/configure_s3.sh ./config/configure_s3.sh RUN chmod 755 ./config/configure_s3.sh diff --git a/kibana/Dockerfile b/kibana/Dockerfile index 5fe761a7..0f0cccdc 100644 --- a/kibana/Dockerfile +++ b/kibana/Dockerfile @@ -1,6 +1,6 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/kibana/kibana:6.8.1 -ARG WAZUH_APP_VERSION=3.9.3_6.8.1 +FROM docker.elastic.co/kibana/kibana:6.8.2 +ARG WAZUH_APP_VERSION=3.9.4_6.8.2 USER root ADD https://packages-dev.wazuh.com/pre-release/app/kibana/wazuhapp-${WAZUH_APP_VERSION}.zip /tmp diff --git a/logstash/Dockerfile b/logstash/Dockerfile index 820d301b..f713b31e 100644 --- a/logstash/Dockerfile +++ b/logstash/Dockerfile @@ -1,5 +1,5 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/logstash/logstash:6.8.1 +FROM docker.elastic.co/logstash/logstash:6.8.2 COPY --chown=logstash:logstash config/entrypoint.sh /entrypoint.sh diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index 978eb162..470771f2 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -2,15 +2,13 @@ FROM phusion/baseimage:latest # Arguments -ARG FILEBEAT_VERSION=6.8.1 -ARG WAZUH_VERSION=3.9.3-1 +ARG FILEBEAT_VERSION=6.8.2 +ARG WAZUH_VERSION=3.9.4-1 # Environment variables ENV API_USER="foo" \ API_PASS="bar" -COPY config/wazuh-manager_3.9.3-3.9.3-2_amd64.deb /tmp/wazuh-manager_3.9.3-3.9.3-2_amd64.deb - # Install packages RUN set -x && \ echo "deb https://packages.wazuh.com/3.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list && \ @@ -25,8 +23,8 @@ RUN set -x && \ apt-get upgrade -y -o Dpkg::Options::="--force-confold" && \ apt-get --no-install-recommends --no-install-suggests -y install openssl apt-transport-https vim expect python-boto python-pip python-cryptography && \ apt-get --no-install-recommends --no-install-suggests -y install postfix bsd-mailx mailutils libsasl2-2 ca-certificates libsasl2-modules && \ - apt-get --no-install-recommends --no-install-suggests -y install /tmp/wazuh-manager_3.9.3-3.9.3-2_amd64.deb -RUN apt-get --no-install-recommends --no-install-suggests -y install nodejs wazuh-api=${WAZUH_VERSION} && \ + apt-get --no-install-recommends --no-install-suggests -y install wazuh-manager=${WAZUH_VERSION} && \ + apt-get --no-install-recommends --no-install-suggests -y install nodejs wazuh-api=${WAZUH_VERSION} && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && \ rm -f /var/ossec/logs/alerts/*/*/* && \ @@ -39,7 +37,6 @@ RUN apt-get --no-install-recommends --no-install-suggests -y install nodejs wazu curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-${FILEBEAT_VERSION}-amd64.deb && \ dpkg -i filebeat-${FILEBEAT_VERSION}-amd64.deb && rm -f filebeat-${FILEBEAT_VERSION}-amd64.deb - # Services RUN mkdir /etc/service/wazuh && \ mkdir /etc/service/wazuh-api && \ @@ -98,5 +95,12 @@ COPY config/01-wazuh.sh /entrypoint-scripts/01-wazuh.sh RUN chmod 755 /entrypoint.sh && \ chmod 755 /entrypoint-scripts/01-wazuh.sh +# Workaround. +# Issues: Wazuh-api +# https://github.com/wazuh/wazuh-api/issues/440 +# https://github.com/wazuh/wazuh-api/issues/443 +COPY --chown=root:ossec config/agents.js /var/ossec/api/controllers/agents.js +RUN chmod 770 /var/ossec/api/controllers/agents.js + # Run all services -ENTRYPOINT ["/entrypoint.sh"] +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file From f3e3abfaf0a9298d2b41330712d799325e8dd15a Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Wed, 4 Sep 2019 13:11:49 +0200 Subject: [PATCH 10/14] Add agents.js Former-commit-id: 2c5a1f7c5874f616d1d7657e215979bf12d3f190 --- wazuh/config/agents.js | 1258 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1258 insertions(+) create mode 100644 wazuh/config/agents.js diff --git a/wazuh/config/agents.js b/wazuh/config/agents.js new file mode 100644 index 00000000..e0313412 --- /dev/null +++ b/wazuh/config/agents.js @@ -0,0 +1,1258 @@ +/** + * Wazuh RESTful API + * Copyright (C) 2015-2019 Wazuh, Inc. All rights reserved. + * Wazuh.com + * + * This program is a free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public + * License (version 2) as published by the FSF - Free Software + * Foundation. + */ + + +var router = require('express').Router(); + +/** + * @api {get} /agents Get all agents + * @apiName GetAgents + * @apiGroup Info + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [select] List of selected fields separated by commas. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. Use commas to enter multiple statuses. + * @apiParam {String} [q] Query to filter results by. For example q="status=Active" + * @apiParam {String} [older_than] Filters out disconnected agents for longer than specified. Time in seconds, '[n_days]d', '[n_hours]h', '[n_minutes]m' or '[n_seconds]s'. For never connected agents, uses the register date. + * @apiParam {String} [os.platform] Filters by OS platform. + * @apiParam {String} [os.version] Filters by OS version. + * @apiParam {String} [os.name] Filters by OS name. + * @apiParam {String} [manager] Filters by manager hostname to which agents are connected. + * @apiParam {String} [version] Filters by agents version. + * @apiParam {String} [group] Filters by group of agents. + * @apiParam {String} [node_name] Filters by node name. + * @apiParam {String} [name] Filters by agent name. + * @apiParam {String} [ip] Filters by agent IP. + * + * @apiDescription Returns a list with the available agents. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents?pretty&offset=0&limit=5&sort=-ip,name" + * + */ +router.get('/', cache(), function(req, res) { + var query_checks = {'status':'alphanumeric_param', 'os.platform':'alphanumeric_param', + 'os.version':'alphanumeric_param', 'manager':'alphanumeric_param', + 'version':'alphanumeric_param', 'node_name': 'alphanumeric_param', + 'older_than':'timeframe_type', 'group':'alphanumeric_param', + 'name': 'alphanumeric_param', 'ip': 'ips', + 'os.name':'alphanumeric_param' }; + templates.array_request("/agents", req, res, "agents", {}, query_checks); +}) + +/** + * @api {get} /agents/summary Get agents summary + * @apiName GetAgentsSummary + * @apiGroup Info + * + * + * @apiDescription Returns a summary of the available agents. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/summary?pretty" + * + */ +router.get('/summary', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/summary"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/summary', 'arguments': {}}; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/summary/os Get OS summary + * @apiName GetOSSummary + * @apiGroup Info + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns a summary of the OS. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/summary/os?pretty" + * + */ +router.get('/summary/os', cache(), function(req, res) { + templates.single_field_array_request("/agents/summary/os", req, res, "agents"); +}) + +/** + * @api {get} /agents/no_group Get agents without group + * @apiName GetAgentsWithoutGroup + * @apiGroup Groups + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns a list with the available agents without group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/no_group?pretty" + * + */ +router.get('/no_group', cache(), function (req, res) { + query_checks = {'status': 'alphanumeric_param'} + templates.array_request('/agents/no_group', req, res, "agents", {}, query_checks); +}) + +/** + * @api {get} /agents/groups Get groups + * @apiName GetAgentGroups + * @apiGroup Groups + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [hash] Select algorithm to generate the sum. + * + * @apiDescription Returns the list of existing agent groups. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups?pretty" + * + */ +router.get('/groups', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers', 'sort':'sort_param', + 'search':'search_param', 'hash':'names'}; + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + if ('sort' in req.query) + data_request['arguments']['sort'] = filter.sort_param_to_json(req.query.sort); + if ('search' in req.query) + data_request['arguments']['search'] = filter.search_param_to_json(req.query.search); + if ('hash' in req.query) + data_request['arguments']['hash_algorithm'] = req.query.hash + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id Get agents in a group + * @apiName GetAgentGroupID + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [select] Select which fields to return (separated by comma). + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. + * @apiParam {String} [q] Query to filter results by. + * + * @apiDescription Returns the list of agents in a group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/dmz?pretty" + * + */ +router.get('/groups/:group_id', cache(), function(req, res) { + param_checks = {'group_id':'names'}; + query_checks = {'status': 'alphanumeric_param'} + + templates.array_request('/agents/groups/:group_id', req, res, "agents", param_checks, query_checks); +}); + + +/** + * @api {get} /agents/groups/:group_id/configuration Get group configuration + * @apiName GetAgentGroupConfiguration + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * + * @apiDescription Returns the group configuration (agent.conf). + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/dmz/configuration?pretty" + * + */ +router.get('/groups/:group_id/configuration', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/configuration"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/configuration', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers'}; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/groups/:group_id/configuration Put configuration file (agent.conf) into a group + * @apiName PostAgentGroupConfiguration + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Upload the group configuration (agent.conf). + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -X POST -H 'Content-type: application/xml' -d @agent.conf.xml "https://127.0.0.1:55000/agents/groups/dmz/configuration?pretty" -k + * + */ +router.post('/groups/:group_id/configuration', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/groups/:group_id/configuration"); + + var data_request = {'function': 'POST/agents/groups/:group_id/configuration', 'arguments': {}}; + var filters = {'group_id': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + if (!filter.check_xml(req.body, req, res)) return; + + data_request['arguments']['group_id'] = req.params.group_id; + try { + data_request['arguments']['tmp_file'] = require('../helpers/files').tmp_file_creator(req.body); + } catch(err) { + res_h.bad_request(req, res, 702, err); + return; + } + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/groups/:group_id/files/:file_name Upload file into a group + * @apiName PostAgentGroupFile + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {String} file_name File name. + * + * @apiDescription Upload a file to a group. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -X POST -H 'Content-type: application/xml' -d @agent.conf.xml "https://127.0.0.1:55000/agents/groups/dmz/files/agent.conf?pretty" -k + * + */ +router.post('/groups/:group_id/files/:file_name', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/groups/:group_id/files/:file_name"); + + var data_request = {'function': 'POST/agents/groups/:group_id/files/:file_name', 'arguments': {}}; + var filters = {'group_id': 'names', 'file_name': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + if (!filter.check_xml(req.body, req, res)) return; + + data_request['arguments']['group_id'] = req.params.group_id; + try { + data_request['arguments']['tmp_file'] = require('../helpers/files').tmp_file_creator(req.body); + } catch(err) { + res_h.bad_request(req, res, 702, err); + return; + } + data_request['arguments']['file_name'] = req.params.file_name; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id/files/:filename Get a file in group + * @apiName GetAgentGroupFile + * @apiGroup Groups + * + * @apiParam {String} [group_id] Group ID. + * @apiParam {String} [file_name] Filename + * @apiParam {String="conf","rootkit_files", "rootkit_trojans", "rcl"} [type] Type of file. + * @apiParam {String="json","xml"} [format] Optional. Output format (JSON, XML). + * + * @apiDescription Returns the specified file belonging to the group parsed to JSON. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/webserver/files/cis_debian_linux_rcl.txt?pretty" + * + */ +router.get('/groups/:group_id/files/:filename', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/files/:filename"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/files/:filename', 'arguments': {}}; + var filters = {'group_id': 'names', 'filename': 'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['filename'] = req.params.filename; + + if (!filter.check(req.query, {'type': 'names', 'format': 'format'}, req, res)) // Filter with error + return; + + if ('type' in req.query) + data_request['arguments']['type_conf'] = req.query.type; + + if ('format' in req.query) + data_request['arguments']['return_format'] = req.query.format; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/groups/:group_id/files Get group files + * @apiName GetAgentGroupFiles + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [hash] Hash algorithm to use to calculate files checksums. + * + * @apiDescription Returns the files belonging to the group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/groups/default/files?pretty" + * + */ +router.get('/groups/:group_id/files', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/groups/:group_id/files"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/groups/:group_id/files', 'arguments': {}}; + var filters = {'offset': 'numbers', 'limit': 'numbers', 'sort':'sort_param', 'search':'search_param', 'hash':'names'}; + + if (!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('offset' in req.query) + data_request['arguments']['offset'] = Number(req.query.offset); + if ('limit' in req.query) + data_request['arguments']['limit'] = Number(req.query.limit); + if ('sort' in req.query) + data_request['arguments']['sort'] = filter.sort_param_to_json(req.query.sort); + if ('search' in req.query) + data_request['arguments']['search'] = filter.search_param_to_json(req.query.search); + if ('hash' in req.query) + data_request['arguments']['hash_algorithm'] = req.query.hash; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/outdated Get outdated agents + * @apiName GetOutdatedAgents + * @apiGroup Upgrade + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns the list of outdated agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/outdated?pretty" + * + */ +router.get('/outdated', cache(), function(req, res) { + templates.array_request("/agents/outdated",req,res,"agents"); +}) + + +/** + * @api {get} /agents/name/:agent_name Get an agent by its name + * @apiName GetAgentsName + * @apiGroup Info + * + * @apiParam {String} agent_name Agent name. + * @apiParam {String} [select] List of selected fields separated by commas. + * + * @apiDescription Returns various information from an agent called :agent_name. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/name/NewHost?pretty" + * + */ +router.get('/name/:agent_name', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/name/:agent_name"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/name/:agent_name', 'arguments': {}}; + var filters = {'select':'select_param'}; + + if (!filter.check(req.params, {'agent_name':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_name'] = req.params.agent_name; + + if(!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('select' in req.query) + data_request['arguments']['select'] = + filter.select_param_to_json(req.query.select); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + +}) + +/** + * @api {get} /agents/:agent_id Get an agent + * @apiName GetAgentsID + * @apiGroup Info + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String} [select] List of selected fields separated by commas. + * + * @apiDescription Returns various information from an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/000?pretty" + * + */ +router.get('/:agent_id', cache(), function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id"); + + req.apicacheGroup = "agents"; + + var data_request = {'function': '/agents/:agent_id', 'arguments': {}}; + var filters = {'select':'select_param'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + if(!filter.check(req.query, filters, req, res)) // Filter with error + return; + + if ('select' in req.query) + data_request['arguments']['select'] = + filter.select_param_to_json(req.query.select); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + +}) + +/** + * @api {get} /agents/:agent_id/key Get agent key + * @apiName GetAgentsKey + * @apiGroup Key + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Returns the key of an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/004/key?pretty" + * + */ +router.get('/:agent_id/key', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/key"); + + var data_request = {'function': '/agents/:agent_id/key', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {get} /agents/:agent_id/upgrade_result Get upgrade result from agent + * @apiName GetUpgradeResult + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {Number} [timeout=3] Seconds to wait for the agent to respond. + * + * @apiDescription Returns the upgrade result from an agent. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/003/upgrade_result?pretty" + * + */ +router.get('/:agent_id/upgrade_result', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/upgrade_result"); + + var data_request = {'function': '/agents/:agent_id/upgrade_result', 'arguments': {}}; + + if (!filter.check(req.query, {'timeout':'numbers'}, req, res)) // Filter with error + return; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('timeout' in req.query) + data_request['arguments']['timeout'] = req.query.timeout; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {get} /agents/:agent_id/config/:component/:configuration Get active configuration + * @apiName GetConfig + * @apiGroup Config + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String="agent","agentless","analysis","auth","com","csyslog","integrator","logcollector","mail","monitor","request","syscheck","wmodules"} component Selected component. + * @apiParam {String="client","buffer","labels","internal","agentless","global","active_response","alerts","command","rules","decoders","internal","auth","active-response","internal","cluster","csyslog","integration","localfile","socket","remote","syscheck","rootcheck","wmodules"} configuration Configuration to read. + * + * @apiDescription Returns the active configuration in JSON format. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/001/config/logcollector/localfile?pretty" + * + */ + router.get('/:agent_id/config/:component/:configuration', function(req, res) { + logger.debug(req.connection.remoteAddress + " GET /agents/:agent_id/config/:component/:configuration"); + + var data_request = {'function': '/agents/:agent_id/config/:component/:configuration', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers', 'component':'names', 'configuration':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['component'] = req.params.component; + data_request['arguments']['configuration'] = req.params.configuration; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + /** + * @api {get} /agents/:agent_id/group/is_sync Get sync status of agent + * @apiName GetSync + * @apiGroup Group + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Returns the sync status in JSON format + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/001/group/is_sync?pretty" + * + */ +router.get('/:agent_id/group/is_sync', function(req, res) { + param_checks = {'agent_id': 'numbers'}; + templates.array_request('/agents/:agent_id/group/is_sync', req, res, "agents", param_checks); +}) + + +/** + * @api {put} /agents/restart Restart all agents + * @apiName PutAgentsRestart + * @apiGroup Restart + * + * @apiDescription Restarts all agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/restart?pretty" + * + */ +router.put('/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/restart"); + + var data_request = {'function': 'PUT/agents/restart', 'arguments': {}}; + + data_request['arguments']['restart_all'] = 'True'; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {post} /agents/restart Restart a list of agents + * @apiName PostAgentListRestart + * @apiGroup Restart + * + * @apiParam {String[]} ids Array of agent ID's. + * + * @apiDescription Restarts a list of agents. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X POST -H "Content-Type:application/json" -d '{"ids":["002","004"]}' "https://127.0.0.1:55000/agents/restart?pretty" + * + */ +router.post('/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/restart"); + + var data_request = {'function': 'POST/agents/restart', 'arguments': {}}; + + if (!filter.check(req.body, {'ids':'array_numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.body.ids; + + if ('ids' in req.body){ + data_request['arguments']['agent_id'] = req.body.ids; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + +/** + * @api {put} /agents/:agent_id/restart Restart an agent + * @apiName PutAgentsRestartId + * @apiGroup Restart + * + * @apiParam {Number} agent_id Agent unique ID. + * + * @apiDescription Restarts the specified agent. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/007/restart?pretty" + * + */ +router.put('/:agent_id/restart', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/restart"); + + var data_request = {'function': 'PUT/agents/:agent_id/restart', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/upgrade Upgrade agent using online repository + * @apiName PutAgentsUpgradeId + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} [wpk_repo] WPK repository. + * @apiParam {String} [version] Wazuh version. + * @apiParam {Boolean} [use_http] Use protocol HTTP. If it is false use HTTPS. By default the value is set to false. + * @apiParam {number="0","1"} [force] Force upgrade. + * + * @apiDescription Upgrade the agent using a WPK file from online repository. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/002/upgrade?pretty" + * + */ +router.put('/:agent_id/upgrade', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/upgrade"); + + var data_request = {'function': 'PUT/agents/:agent_id/upgrade', 'arguments': {}}; + var filters = { 'wpk_repo': 'paths', 'version': 'alphanumeric_param', 'force': 'numbers', 'use_http': 'boolean'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) + return; + + if (!filter.check(req.query, filters, req, res)) + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('wpk_repo' in req.query) + data_request['arguments']['wpk_repo'] = req.query.wpk_repo; + if ('version' in req.query) + data_request['arguments']['version'] = req.query.version; + if ('force' in req.query) + data_request['arguments']['force'] = req.query.force; + if ('use_http' in req.query) + data_request['arguments']['use_http'] = (req.query.use_http == true || req.query.use_http == 'true'); + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/upgrade_custom Upgrade agent using custom file + * @apiName PutAgentsUpgradeCustomId + * @apiGroup Upgrade + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} file_path Path to the WPK file. The file must be on a folder on the Wazuh's installation directory (by default, ``/var/ossec``). + * @apiParam {String} installer Installation script. + * + * @apiDescription Upgrade the agent using a custom file. + * + * @apiExample {curl} Example usage*: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/002/upgrade_custom?pretty" + * + */ +router.put('/:agent_id/upgrade_custom', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/upgrade_custom"); + + var data_request = {'function': 'PUT/agents/:agent_id/upgrade_custom', 'arguments': {}}; + var filters = {'file_path':'paths', 'installer':'alphanumeric_param'}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) + return; + + if (!filter.check(req.query, filters, req, res)) + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + if ('file_path' in req.query) + data_request['arguments']['file_path'] = req.query.file_path; + if ('installer' in req.query) + data_request['arguments']['installer'] = req.query.installer; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_name Add agent (quick method) + * @apiName PutAddAgentName + * @apiGroup Add + * + * @apiParam {String} agent_name Agent name. + * + * @apiDescription Adds a new agent with name :agent_name. This agent will use ANY as IP. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/myNewAgent?pretty" + * + */ +router.put('/:agent_name', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_name"); + + var data_request = {'function': 'PUT/agents/:agent_name', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_name':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['name'] = req.params.agent_name; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/groups/:group_id Create a group + * @apiName PutGroup + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Creates a new group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/groups/pciserver?pretty" + * + */ +router.put('/groups/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/groups/:group_id"); + + var data_request = {'function': 'PUT/agents/groups/:group_id', 'arguments': {}}; + var filters = {'group_id':'names'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {put} /agents/:agent_id/group/:group_id Add agent group + * @apiName PutGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent unique ID. + * @apiParam {String} group_id Group ID. + * @apiParam {Boolean} force_single_group Wheter to append new group to current agent's group or replace it. + * + * @apiDescription Adds an agent to the specified group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X PUT "https://127.0.0.1:55000/agents/004/group/dmz?pretty" + * + */ +router.put('/:agent_id/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " PUT /agents/:agent_id/group/:group_id"); + + var data_request = {'function': 'PUT/agents/:agent_id/group/:group_id', 'arguments': {}}; + var filters = {'agent_id':'numbers', 'group_id':'names', 'force_single_group': 'empty_boolean'}; + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['replace'] = 'force_single_group' in req.query && req.query.replace != 'false' ? true : false; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {post} /agents/group/:group_id Add a list of agents to a group + * @apiName PostGroupAgents + * @apiGroup Groups + * + * @apiParam {String[]} ids List of agents ID. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Adds a list of agents to the specified group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -X POST -H "Content-Type:application/json" -d '{"ids":["001","002"]}' "https://localhost:55000/agents/group/dmz?pretty" -k + * + */ +router.post('/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/group/:group_id"); + + var data_request = {'function': 'POST/agents/group/:group_id', 'arguments': {}}; + var filters = {'group_id': 'names', 'ids': 'array_numbers'} + + if (!filter.check(req.params, filters, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + data_request['arguments']['agent_id_list'] = req.body.ids; + + if ('ids' in req.body){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + + +/** + * @api {delete} /agents/groups Delete a list of groups + * @apiName DeleteAgentsGroups + * @apiGroup Delete + * + * @apiParam {String} ids Name of groups separated by commas. + * + * @apiDescription Removes a list of groups. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/groups?ids=webserver,database&pretty" + * + */ +router.delete('/groups', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/groups"); + + var data_request = {'function': 'DELETE/agents/groups', 'arguments': {}}; + + if (!filter.check(req.query, {'ids': 'array_names'}, req, res)) // Filter with error + return; + + if ('ids' in req.query){ + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['group_id'] = req.query.ids.split(','); + } else { + data_request['arguments']['group_id'] = req.query.ids; + } + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + + +/** + * @api {delete} /agents/:agent_id Delete an agent + * @apiName DeleteAgentId + * @apiGroup Delete + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {Boolean} purge Delete an agent from the key store. This parameter is only valid if purge is set to no in the manager's ossec.conf. + * + * @apiDescription Removes an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/008?pretty&purge" + * + */ +router.delete('/:agent_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id"); + + var data_request = {'function': 'DELETE/agents/:agent_id', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['purge'] = 'purge' in req.query && req.query.purge != 'false' ? true : false; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/:agent_id/group Remove all agent groups. + * @apiName DeleteGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent ID. + * + * @apiDescription Removes the group of the agent. The agent will automatically revert to the 'default' group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/004/group?pretty" + * + */ +router.delete('/:agent_id/group', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id/group"); + + var data_request = {'function': 'DELETE/agents/:agent_id/group', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/:agent_id/group/:group_id Remove a single group of an agent + * @apiName DeleteGroupAgent + * @apiGroup Groups + * + * @apiParam {Number} agent_id Agent ID. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Remove the group of the agent but will leave the rest of its group if it belongs to a multigroup. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/004/group/dmz?pretty" + * + */ +router.delete('/:agent_id/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/:agent_id/group/:group_id"); + + var data_request = {'function': 'DELETE/agents/:agent_id/group/:group_id', 'arguments': {}}; + + if (!filter.check(req.params, {'agent_id':'numbers', 'group_id': 'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['agent_id'] = req.params.agent_id; + data_request['arguments']['group_id'] = req.params.group_id; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents/group/:group_id Remove a single group of multiple agents + * @apiName DeleteGroupAgents + * @apiGroup Groups + * + * @apiParam {String} ids Agent IDs separated by commas. + * @apiParam {String} group_id Group ID. + * + * @apiDescription Remove a list of agents of a group + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://localhost:55000/agents/group/dmz?ids=001,002&pretty" + * + */ +router.delete('/group/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/group/:group_id"); + + var data_request = {'function': 'DELETE/agents/group/:group_id', 'arguments': {}}; + var filters_param = {'group_id': 'names'} + var filters_query = {'ids': 'array_numbers'} + + if (!filter.check(req.params, filters_param, req, res)) // Filter with error (path params) + return; + if (!filter.check(req.query, filters_query, req, res)) // Filter with error (query params) + return; + + data_request['arguments']['group_id'] = req.params.group_id; + + if ('ids' in req.query) { + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['agent_id_list'] = req.query.ids.split(','); + } else { + data_request['arguments']['agent_id_list'] = req.query.ids; + } + } + + if ('ids' in req.query){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'ids'"); +}) + +/** + * @api {delete} /agents/groups/:group_id Remove group + * @apiName DeleteGroupAgents + * @apiGroup Groups + * + * @apiParam {String} group_id Group ID. + * + * @apiDescription Removes the group. Agents that were assigned to the removed group will automatically revert to the 'default' group. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents/groups/dmz?pretty" + * + */ +router.delete('/groups/:group_id', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents/groups/:group_id"); + + var data_request = {'function': 'DELETE/agents/groups/:group_id', 'arguments': {}}; + + if (!filter.check(req.params, {'group_id':'names'}, req, res)) // Filter with error + return; + + data_request['arguments']['group_id'] = req.params.group_id; + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + +/** + * @api {delete} /agents Delete agents + * @apiName DeleteAgents + * @apiGroup Delete + * + * @apiParam {String} ids Agent IDs separated by commas. + * @apiParam {Boolean} purge Delete an agent from the key store. This parameter is only valid if purge is set to no in the manager's ossec.conf. + * @apiParam {String="active", "pending", "neverconnected", "disconnected"} [status] Filters by agent status. Use commas to enter multiple statuses. + * @apiParam {String} older_than Filters out disconnected agents for longer than specified. Time in seconds, '[n_days]d', '[n_hours]h', '[n_minutes]m' or '[n_seconds]s'. For never connected agents, uses the register date. Default value: 7d. + * + * @apiDescription Removes agents, using a list of them or a criterion based on the status or time of the last connection. The Wazuh API must be restarted after removing an agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X DELETE "https://127.0.0.1:55000/agents?older_than=10s&purge&ids=003,005&pretty" + * + */ +router.delete('/', function(req, res) { + logger.debug(req.connection.remoteAddress + " DELETE /agents"); + + var data_request = {'function': 'DELETE/agents/', 'arguments': {}}; + var filters_query = {'older_than': 'timeframe_type', 'status': 'alphanumeric_param', 'purge': 'empty_boolean', + 'ids': 'array_numbers'}; + + if (!filter.check(req.query, filters_query, req, res)) // Filter with error + return; + + if (!('ids' in req.query) && !('status' in req.query)){ + res_h.bad_request(req, res, 604, "Missing field: You have to specified 'ids' or status."); + return; + } + + if ('purge' in req.query && req.query.purge != 'false') + data_request['arguments']['purge'] = true; + else + data_request['arguments']['purge'] = false; + + if ('ids' in req.query) { + if (typeof(req.query.ids) == 'string') { + data_request['arguments']['list_agent_ids'] = req.query.ids.split(','); + } else { + data_request['arguments']['list_agent_ids'] = req.query.ids; + } + } + + if ('older_than' in req.query) + data_request['arguments']['older_than'] = req.query.older_than; + + if ('status' in req.query) + data_request['arguments']['status'] = req.query.status; + + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); +}) + + +/** + * @api {post} /agents Add agent + * @apiName PostAddAgentId + * @apiGroup Add + * + * @apiParam {String} name Agent name. + * @apiParam {String="IP","IP/NET", "ANY"} [ip] If this is not included, the API will get the IP automatically. If you are behind a proxy, you must set the option config.BehindProxyServer to yes at config.js. + * @apiParam {Number} [force] Remove the old agent with the same IP if disconnected since seconds. + * + * @apiDescription Add a new agent. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X POST -d '{"name":"NewHost","ip":"10.0.0.9"}' -H 'Content-Type:application/json' "https://127.0.0.1:55000/agents?pretty" + * + */ +router.post('/', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents"); + + // If not IP set, we will use source IP. + var ip = req.body.ip; + if ( !ip ){ + // If we hare behind a proxy server, use headers. + if (config.BehindProxyServer.toLowerCase() == "yes") + if (!req.headers.hasOwnProperty('x-forwarded-for')){ + res_h.bad_request(req, res, 800); + return; + } + else + ip = req.headers['x-forwarded-for']; + else + ip = req.connection.remoteAddress; + + // Extract IPv4 from IPv6 hybrid notation + if (ip.indexOf("::ffff:") > -1) { + var ipFiltered = ip.split(":"); + ip = ipFiltered[ipFiltered.length-1]; + logger.debug("Hybrid IPv6 IP filtered: " + ip); + } + logger.debug("Add agent with automatic IP: " + ip); + } + req.body.ip = ip; + + var data_request = {'function': 'POST/agents', 'arguments': {}}; + var filters = {'name':'names', 'ip':'ips', 'force':'numbers'}; + + if (!filter.check(req.body, filters, req, res)) // Filter with error + return; + + data_request['arguments']['ip'] = req.body.ip; + + if ('name' in req.body){ + data_request['arguments']['name'] = req.body.name; + if ('force' in req.body){ + data_request['arguments']['force'] = req.body.force; + } + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing field: 'name'"); +}) + + +/** + * @api {post} /agents/insert Insert agent + * @apiName PostInsertAgent + * @apiGroup Add + * + * @apiParam {String} name Agent name. + * @apiParam {String="IP","IP/NET", "ANY"} [ip] If this is not included, the API will get the IP automatically. If you are behind a proxy, you must set the option config.BehindProxyServer to yes at config.js. + * @apiParam {String} id Agent ID. + * @apiParam {String} key Agent key. Minimum length: 64 characters. Allowed values: ^[a-zA-Z0-9]+$ + * @apiParam {Number} [force] Remove the old agent the with same IP if disconnected since seconds. + * + * @apiDescription Insert an agent with an existing id and key. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X POST -d '{"name":"NewHost_2","ip":"10.0.10.10","id":"123","key":"1abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghi64"}' -H 'Content-Type:application/json' "https://127.0.0.1:55000/agents/insert?pretty" + * + */ +router.post('/insert', function(req, res) { + logger.debug(req.connection.remoteAddress + " POST /agents/insert"); + + // If not IP set, we will use source IP. + var ip = req.body.ip; + if ( !ip ){ + // If we hare behind a proxy server, use headers. + if (config.BehindProxyServer.toLowerCase() == "yes") + if (!req.headers.hasOwnProperty('x-forwarded-for')){ + res_h.bad_request(req, res, 800); + return; + } + else + ip = req.headers['x-forwarded-for']; + else + ip = req.connection.remoteAddress; + + // Extract IPv4 from IPv6 hybrid notation + if (ip.indexOf("::ffff:") > -1) { + var ipFiltered = ip.split(":"); + ip = ipFiltered[ipFiltered.length-1]; + logger.debug("Hybrid IPv6 IP filtered: " + ip); + } + logger.debug("Add agent with automatic IP: " + ip); + } + req.body.ip = ip; + + var data_request = {'function': 'POST/agents/insert', 'arguments': {}}; + var filters = {'name':'names', 'ip':'ips', 'id':'numbers', 'key': 'ossec_key', 'force':'numbers'}; + + if (!filter.check(req.body, filters, req, res)) // Filter with error + return; + + data_request['arguments']['id'] = req.body.id; + data_request['arguments']['name'] = req.body.name; + data_request['arguments']['ip'] = req.body.ip; + data_request['arguments']['key'] = req.body.key; + if ('force' in req.body){ + data_request['arguments']['force'] = req.body.force; + } + + if ('id' in req.body && 'name' in req.body && 'ip' in req.body && 'key' in req.body){ + execute.exec(python_bin, [wazuh_control], data_request, function (data) { res_h.send(req, res, data); }); + }else + res_h.bad_request(req, res, 604, "Missing fields. Mandatory fields: id, name, ip, key"); +}) + + + +/** + * @api {get} /agents/stats/distinct Get distinct fields in agents + * @apiName GetdistinctAgents + * @apiGroup Stats + * + * @apiParam {Number} [offset] First element to return in the collection. + * @apiParam {Number} [limit=500] Maximum number of elements to return. + * @apiParam {String} [sort] Sorts the collection by a field or fields (separated by comma). Use +/- at the beginning to list in ascending or descending order. + * @apiParam {String} [search] Looks for elements with the specified string. + * @apiParam {String} [fields] List of fields affecting the operation. + * @apiParam {String} [select] List of selected fields separated by commas. + * @apiParam {String} [q] Query to filter result. For example q="status=Active" + * + * @apiDescription Returns all the different combinations that agents have for the selected fields. It also indicates the total number of agents that have each combination. + * + * @apiExample {curl} Example usage: + * curl -u foo:bar -k -X GET "https://127.0.0.1:55000/agents/stats/distinct?pretty&fields=os.platform" + * + */ +router.get('/stats/distinct', cache(), function (req, res) { + query_checks = {'fields':'select_param'}; + templates.array_request('/agents/stats/distinct', req, res, "agents", {}, query_checks); +}) + +module.exports = router; \ No newline at end of file From 7faed76e4495e9efdc79adb3687b377481feb4d6 Mon Sep 17 00:00:00 2001 From: Josemi Hernandez <15127122+ixjosemi@users.noreply.github.com> Date: Thu, 5 Sep 2019 09:46:55 +0200 Subject: [PATCH 11/14] Added TLS version filter (#227) Former-commit-id: af007c69d4dc69335ec9a39189291fba49039e5c --- kibana/config/20-entrypoint.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kibana/config/20-entrypoint.sh b/kibana/config/20-entrypoint.sh index 771fc673..08584d1e 100644 --- a/kibana/config/20-entrypoint.sh +++ b/kibana/config/20-entrypoint.sh @@ -92,6 +92,9 @@ elasticsearch.ssl.certificateAuthorities: [\"/usr/share/kibana/config/$SECURITY_ server.ssl.enabled: true server.ssl.certificate: $SECURITY_KIBANA_SSL_CERT_PATH/kibana-access.pem server.ssl.key: $SECURITY_KIBANA_SSL_KEY_PATH/kibana-access.key +server.ssl.supportedProtocols: + - TLSv1.1 + - TLSv1.2 " >> /usr/share/kibana/config/kibana.yml echo "Create SSL directories." From 18971e3fdea98bf0d1dfd840579ea67a1061f472 Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Thu, 5 Sep 2019 10:16:07 +0200 Subject: [PATCH 12/14] Remove 6.8.2 version Former-commit-id: abbe2f20e43cd9a32c395567895c62e8173461e6 --- elasticsearch/Dockerfile | 4 ++-- kibana/Dockerfile | 4 ++-- logstash/Dockerfile | 2 +- wazuh/config/01-wazuh.sh | 7 ------- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/elasticsearch/Dockerfile b/elasticsearch/Dockerfile index c2073891..4043d11c 100644 --- a/elasticsearch/Dockerfile +++ b/elasticsearch/Dockerfile @@ -1,5 +1,5 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/elasticsearch/elasticsearch:6.8.2 +FROM docker.elastic.co/elasticsearch/elasticsearch:6.8.1 ENV ALERTS_SHARDS="1" \ ALERTS_REPLICAS="0" @@ -11,7 +11,7 @@ ENV XPACK_ML="true" ENV ENABLE_CONFIGURE_S3="false" -ENV TEMPLATE_VERSION=v3.9.4 +ENV TEMPLATE_VERSION=v3.9.3 # This CA is created for testing. Please set your own CA zip containing the key and the signed certificate. diff --git a/kibana/Dockerfile b/kibana/Dockerfile index 0f0cccdc..5fe761a7 100644 --- a/kibana/Dockerfile +++ b/kibana/Dockerfile @@ -1,6 +1,6 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/kibana/kibana:6.8.2 -ARG WAZUH_APP_VERSION=3.9.4_6.8.2 +FROM docker.elastic.co/kibana/kibana:6.8.1 +ARG WAZUH_APP_VERSION=3.9.3_6.8.1 USER root ADD https://packages-dev.wazuh.com/pre-release/app/kibana/wazuhapp-${WAZUH_APP_VERSION}.zip /tmp diff --git a/logstash/Dockerfile b/logstash/Dockerfile index f713b31e..820d301b 100644 --- a/logstash/Dockerfile +++ b/logstash/Dockerfile @@ -1,5 +1,5 @@ # Wazuh App Copyright (C) 2019 Wazuh Inc. (License GPLv2) -FROM docker.elastic.co/logstash/logstash:6.8.2 +FROM docker.elastic.co/logstash/logstash:6.8.1 COPY --chown=logstash:logstash config/entrypoint.sh /entrypoint.sh diff --git a/wazuh/config/01-wazuh.sh b/wazuh/config/01-wazuh.sh index 56ca5fcf..17ba4b9a 100644 --- a/wazuh/config/01-wazuh.sh +++ b/wazuh/config/01-wazuh.sh @@ -255,13 +255,6 @@ main() { # Delete temporary data folder rm -rf ${WAZUH_INSTALL_PATH}/data_tmp - # Grant proper permissions - # When modifiying some files using the Wazuh API (i.e. /var/ossec/etc/ossec.conf), group rw permissions are needed for changes to take place. - # https://github.com/wazuh/wazuh/issues/3647 - #chmod -R g+rw ${WAZUH_INSTALL_PATH} - - # Files inside /var/ossec/integrations should not have write permissions for group and other. - #chmod -R 750 "/var/ossec/integrations/" } main From dccb8aca54de056af7a924fdb9313512f59a6b2e Mon Sep 17 00:00:00 2001 From: Mayte Ariza Date: Thu, 5 Sep 2019 10:20:16 +0200 Subject: [PATCH 13/14] Set filebeat to 6.8.1 Former-commit-id: e22eba52b987820852357251c6fa051800ba85ab --- wazuh/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wazuh/Dockerfile b/wazuh/Dockerfile index 470771f2..a595598d 100644 --- a/wazuh/Dockerfile +++ b/wazuh/Dockerfile @@ -2,7 +2,7 @@ FROM phusion/baseimage:latest # Arguments -ARG FILEBEAT_VERSION=6.8.2 +ARG FILEBEAT_VERSION=6.8.1 ARG WAZUH_VERSION=3.9.4-1 # Environment variables From 84a06e2fbc1ddc457c87be239efd1a78e75bf5c8 Mon Sep 17 00:00:00 2001 From: AlfonsoRBJ Date: Thu, 5 Sep 2019 10:29:55 +0200 Subject: [PATCH 14/14] Wazuh 3.9.4 Elastic 6.8.1_3.9.3 Former-commit-id: e88be1d4bb514d1796cc80d842b48fd1d186b021 --- elasticsearch/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elasticsearch/Dockerfile b/elasticsearch/Dockerfile index 4043d11c..70f1faed 100644 --- a/elasticsearch/Dockerfile +++ b/elasticsearch/Dockerfile @@ -61,7 +61,7 @@ COPY --chown=elasticsearch:elasticsearch ./config/load_settings.sh ./ RUN chmod +x ./load_settings.sh -RUN bin/elasticsearch-plugin install --batch https://artifacts.elastic.co/downloads/elasticsearch-plugins/repository-s3/repository-s3-6.8.2.zip +RUN bin/elasticsearch-plugin install --batch https://artifacts.elastic.co/downloads/elasticsearch-plugins/repository-s3/repository-s3-6.8.1.zip COPY config/configure_s3.sh ./config/configure_s3.sh RUN chmod 755 ./config/configure_s3.sh