diff --git a/kibana/Dockerfile b/kibana/Dockerfile new file mode 100644 index 00000000..20245926 --- /dev/null +++ b/kibana/Dockerfile @@ -0,0 +1,65 @@ +# Wazuh Docker Copyright (C) 2020 Wazuh Inc. (License GPLv2) +ARG KIBANA_IMAGE=docker.elastic.co/kibana/kibana:7.9.3 +FROM ${KIBANA_IMAGE} +USER kibana +ARG ELASTIC_VERSION=7.9.3 +ARG WAZUH_VERSION=4.0.3 +ARG WAZUH_APP_VERSION="${WAZUH_VERSION}_${ELASTIC_VERSION}" + +WORKDIR /usr/share/kibana +RUN ./bin/kibana-plugin install https://packages.wazuh.com/4.x/ui/kibana/wazuh_kibana-${WAZUH_APP_VERSION}-1.zip + +ENV PATTERN="" \ + CHECKS_PATTERN="" \ + CHECKS_TEMPLATE="" \ + CHECKS_API="" \ + CHECKS_SETUP="" \ + EXTENSIONS_PCI="" \ + EXTENSIONS_GDPR="" \ + EXTENSIONS_HIPAA="" \ + EXTENSIONS_NIST="" \ + EXTENSIONS_TSC="" \ + EXTENSIONS_AUDIT="" \ + EXTENSIONS_OSCAP="" \ + EXTENSIONS_CISCAT="" \ + EXTENSIONS_AWS="" \ + EXTENSIONS_GCP="" \ + EXTENSIONS_VIRUSTOTAL="" \ + EXTENSIONS_OSQUERY="" \ + EXTENSIONS_DOCKER="" \ + APP_TIMEOUT="" \ + API_SELECTOR="" \ + IP_SELECTOR="" \ + IP_IGNORE="" \ + WAZUH_MONITORING_ENABLED="" \ + WAZUH_MONITORING_FREQUENCY="" \ + WAZUH_MONITORING_SHARDS="" \ + WAZUH_MONITORING_REPLICAS="" \ + ADMIN_PRIVILEGES="" \ + XPACK_CANVAS="true" \ + XPACK_LOGS="true" \ + XPACK_INFRA="true" \ + XPACK_ML="true" \ + XPACK_DEVTOOLS="true" \ + XPACK_MONITORING="true" \ + XPACK_APM="true" + +WORKDIR / +USER kibana +RUN NODE_OPTIONS="--max-old-space-size=2048" /usr/local/bin/kibana-docker --optimize + +COPY --chown=kibana:kibana config/entrypoint.sh ./entrypoint.sh +RUN chmod 755 ./entrypoint.sh + +COPY --chown=kibana:kibana ./config/wazuh.yml /usr/share/kibana/optimize/wazuh/config/wazuh.yml +COPY --chown=kibana:kibana ./config/wazuh_app_config.sh ./ +RUN chmod +x ./wazuh_app_config.sh + +COPY --chown=kibana:kibana ./config/kibana_settings.sh ./ +RUN chmod +x ./kibana_settings.sh + +COPY --chown=kibana:kibana ./config/xpack_config.sh ./ +RUN chmod +x ./xpack_config.sh +RUN ./xpack_config.sh + +ENTRYPOINT ./entrypoint.sh diff --git a/kibana/config/entrypoint.sh b/kibana/config/entrypoint.sh new file mode 100644 index 00000000..885fb7d6 --- /dev/null +++ b/kibana/config/entrypoint.sh @@ -0,0 +1,60 @@ +#!/bin/bash +# Wazuh Docker Copyright (C) 2020 Wazuh Inc. (License GPLv2) + +set -e + +############################################################################## +# Waiting for elasticsearch +############################################################################## + +if [ "x${ELASTICSEARCH_URL}" = "x" ]; then + export el_url="http://elasticsearch:9200" +else + export el_url="${ELASTICSEARCH_URL}" +fi + +if [[ ${ENABLED_XPACK} != "true" || "x${ELASTICSEARCH_USERNAME}" = "x" || "x${ELASTICSEARCH_PASSWORD}" = "x" ]]; then + auth="" +else + auth="--user ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD}" +fi + +until curl -XGET $el_url ${auth}; do + >&2 echo "Elastic is unavailable - sleeping" + sleep 5 +done + +sleep 2 + +>&2 echo "Elasticsearch is up." + + +############################################################################## +# Waiting for wazuh alerts template +############################################################################## + +strlen=0 + +while [[ $strlen -eq 0 ]] +do + template=$(curl ${auth} $el_url/_cat/templates/wazuh -s) + strlen=${#template} + >&2 echo "Wazuh alerts template not loaded - sleeping." + sleep 2 +done + +sleep 2 + +>&2 echo "Wazuh alerts template is loaded." + +./xpack_config.sh + +./wazuh_app_config.sh + +sleep 5 + +./kibana_settings.sh & + +sleep 2 + +/usr/local/bin/kibana-docker diff --git a/kibana/config/kibana_settings.sh b/kibana/config/kibana_settings.sh new file mode 100644 index 00000000..137d5d47 --- /dev/null +++ b/kibana/config/kibana_settings.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# Wazuh Docker Copyright (C) 2020 Wazuh Inc. (License GPLv2) + +WAZUH_MAJOR=4 + +############################################################################## +# Wait for the Kibana API to start. It is necessary to do it in this container +# because the others are running Elastic Stack and we can not interrupt them. +# +# The following actions are performed: +# +# Add the wazuh alerts index as default. +# Set the Discover time interval to 24 hours instead of 15 minutes. +# Do not ask user to help providing usage statistics to Elastic. +############################################################################## + +############################################################################## +# Customize elasticsearch ip +############################################################################## +sed -i "s|elasticsearch.hosts:.*|elasticsearch.hosts: $el_url|g" /usr/share/kibana/config/kibana.yml + +# If KIBANA_INDEX was set, then change the default index in kibana.yml configuration file. If there was an index, then delete it and recreate. +if [ "$KIBANA_INDEX" != "" ]; then + if grep -q 'kibana.index' /usr/share/kibana/config/kibana.yml; then + sed -i '/kibana.index/d' /usr/share/kibana/config/kibana.yml + fi + echo "kibana.index: $KIBANA_INDEX" >> /usr/share/kibana/config/kibana.yml +fi + +if [ "$XPACK_SECURITY_ENABLED" != "" ]; then + if grep -q 'xpack.security.enabled' /usr/share/kibana/config/kibana.yml; then + sed -i '/xpack.security.enabled/d' /usr/share/kibana/config/kibana.yml + fi + echo "xpack.security.enabled: $XPACK_SECURITY_ENABLED" >> /usr/share/kibana/config/kibana.yml +fi + +if [ "$KIBANA_IP" != "" ]; then + kibana_ip="$KIBANA_IP" +else + kibana_ip="kibana" +fi + +# Add auth headers if required +if [ "$ELASTICSEARCH_USERNAME" != "" ] && [ "$ELASTICSEARCH_PASSWORD" != "" ]; then + curl_auth="-u $ELASTICSEARCH_USERNAME:$ELASTICSEARCH_PASSWORD" +fi + +while [[ "$(curl $curl_auth -XGET -I -s -o /dev/null -w ''%{http_code}'' kibana:5601/status)" != "200" ]]; do + echo "Waiting for Kibana API. Sleeping 5 seconds" + sleep 5 +done + + + +# Prepare index selection. +echo "Kibana API is running" + +default_index="/tmp/default_index.json" + +cat > ${default_index} << EOF +{ + "changes": { + "defaultIndex": "wazuh-alerts-${WAZUH_MAJOR}.x-*" + } +} +EOF + +sleep 5 +# Add the wazuh alerts index as default. +curl ${auth} -POST -k https://127.0.0.1:5601/api/kibana/settings -H "Content-Type: application/json" -H "kbn-xsrf: true" -d@${default_index} +rm -f ${default_index} + +sleep 5 +# Configuring Kibana TimePicker. +curl ${auth} -POST -k "https://127.0.0.1:5601/api/kibana/settings" -H "Content-Type: application/json" -H "kbn-xsrf: true" -d \ +'{"changes":{"timepicker:timeDefaults":"{\n \"from\": \"now-12h\",\n \"to\": \"now\",\n \"mode\": \"quick\"}"}}' + +sleep 5 +# Do not ask user to help providing usage statistics to Elastic +curl -POST "http://$kibana_ip:5601/api/telemetry/v2/optIn" -H "Content-Type: application/json" -H "kbn-xsrf: true" -d '{"enabled":false}' + +echo "End settings" diff --git a/kibana/config/wazuh.yml b/kibana/config/wazuh.yml new file mode 100644 index 00000000..6c52d526 --- /dev/null +++ b/kibana/config/wazuh.yml @@ -0,0 +1,162 @@ +--- +# +# Wazuh app - App configuration file +# Copyright (C) 2015-2020 Wazuh, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# Find more information about this on the LICENSE file. +# +# ======================== Wazuh app configuration file ======================== +# +# Please check the documentation for more information on configuration options: +# https://documentation.wazuh.com/current/installation-guide/index.html +# +# Also, you can check our repository: +# https://github.com/wazuh/wazuh-kibana-app +# +# ------------------------------- Index patterns ------------------------------- +# +# Default index pattern to use. +#pattern: wazuh-alerts-* +# +# ----------------------------------- Checks ----------------------------------- +# +# Defines which checks must to be consider by the healthcheck +# step once the Wazuh app starts. Values must to be true or false. +#checks.pattern : true +#checks.template: true +#checks.api : true +#checks.setup : true +#checks.metaFields: true +# +# --------------------------------- Extensions --------------------------------- +# +# Defines which extensions should be activated when you add a new API entry. +# You can change them after Wazuh app starts. +# Values must to be true or false. +#extensions.pci : true +#extensions.gdpr : true +#extensions.hipaa : true +#extensions.nist : true +#extensions.tsc : true +#extensions.audit : true +#extensions.oscap : false +#extensions.ciscat : false +#extensions.aws : false +#extensions.gcp : false +#extensions.virustotal: false +#extensions.osquery : false +#extensions.docker : false +# +# ---------------------------------- Time out ---------------------------------- +# +# Defines maximum timeout to be used on the Wazuh app requests. +# It will be ignored if it is bellow 1500. +# It means milliseconds before we consider a request as failed. +# Default: 20000 +#timeout: 20000 +# +# -------------------------------- API selector -------------------------------- +# +# Defines if the user is allowed to change the selected +# API directly from the Wazuh app top menu. +# Default: true +#api.selector: true +# +# --------------------------- Index pattern selector --------------------------- +# +# Defines if the user is allowed to change the selected +# index pattern directly from the Wazuh app top menu. +# Default: true +#ip.selector: true +# +# List of index patterns to be ignored +#ip.ignore: [] +# +# -------------------------------- X-Pack RBAC --------------------------------- +# +# Custom setting to enable/disable built-in X-Pack RBAC security capabilities. +# Default: enabled +#xpack.rbac.enabled: true +# +# ------------------------------ wazuh-monitoring ------------------------------ +# +# Custom setting to enable/disable wazuh-monitoring indices. +# Values: true, false, worker +# If worker is given as value, the app will show the Agents status +# visualization but won't insert data on wazuh-monitoring indices. +# Default: true +#wazuh.monitoring.enabled: true +# +# Custom setting to set the frequency for wazuh-monitoring indices cron task. +# Default: 900 (s) +#wazuh.monitoring.frequency: 900 +# +# Configure wazuh-monitoring-* indices shards and replicas. +#wazuh.monitoring.shards: 2 +#wazuh.monitoring.replicas: 0 +# +# Configure wazuh-monitoring-* indices custom creation interval. +# Values: h (hourly), d (daily), w (weekly), m (monthly) +# Default: d +#wazuh.monitoring.creation: d +# +# Default index pattern to use for Wazuh monitoring +#wazuh.monitoring.pattern: wazuh-monitoring-* +# +# --------------------------------- wazuh-cron ---------------------------------- +# +# Customize the index prefix of predefined jobs +# This change is not retroactive, if you change it new indexes will be created +# cron.prefix: test +# +# ------------------------------ wazuh-statistics ------------------------------- +# +# Custom setting to enable/disable statistics tasks. +#cron.statistics.status: true +# +# Enter the ID of the APIs you want to save data from, leave this empty to run +# the task on all configured APIs +#cron.statistics.apis: [] +# +# Define the frequency of task execution using cron schedule expressions +#cron.statistics.interval: 0 0 * * * * +# +# Define the name of the index in which the documents are to be saved. +#cron.statistics.index.name: statistics +# +# Define the interval in which the index will be created +#cron.statistics.index.creation: w +# +# ------------------------------- App privileges -------------------------------- +#admin: true +# +# ---------------------------- Hide manager alerts ------------------------------ +# Hide the alerts of the manager in all dashboards and discover +#hideManagerAlerts: false +# +# ------------------------------- App logging level ----------------------------- +# Set the logging level for the Wazuh App log files. +# Default value: info +# Allowed values: info, debug +#logs.level: info +# +# -------------------------------- Enrollment DNS ------------------------------- +# Set the variable WAZUH_REGISTRATION_SERVER in agents deployment. +# Default value: '' +#enrollment.dns: '' +# +#-------------------------------- API entries ----------------------------------- +#The following configuration is the default structure to define an API entry. +# +#hosts: +# - : +# url: http(s):// +# port: +# username: +# password: + diff --git a/kibana/config/wazuh_app_config.sh b/kibana/config/wazuh_app_config.sh new file mode 100644 index 00000000..7ff90337 --- /dev/null +++ b/kibana/config/wazuh_app_config.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Wazuh Docker Copyright (C) 2020 Wazuh Inc. (License GPLv2) + +wazuh_url="${WAZUH_API_URL:-https://wazuh}" +wazuh_port="${API_PORT:-55000}" +api_username="${API_USERNAME:-wazuh-wui}" +api_password="${API_PASSWORD:-wazuh-wui}" + +kibana_config_file="/usr/share/kibana/optimize/wazuh/config/wazuh.yml" + +declare -A CONFIG_MAP=( + [pattern]=$PATTERN + [checks.pattern]=$CHECKS_PATTERN + [checks.template]=$CHECKS_TEMPLATE + [checks.api]=$CHECKS_API + [checks.setup]=$CHECKS_SETUP + [extensions.pci]=$EXTENSIONS_PCI + [extensions.gdpr]=$EXTENSIONS_GDPR + [extensions.hipaa]=$EXTENSIONS_HIPAA + [extensions.nist]=$EXTENSIONS_NIST + [extensions.tsc]=$EXTENSIONS_TSC + [extensions.audit]=$EXTENSIONS_AUDIT + [extensions.oscap]=$EXTENSIONS_OSCAP + [extensions.ciscat]=$EXTENSIONS_CISCAT + [extensions.aws]=$EXTENSIONS_AWS + [extensions.gcp]=$EXTENSIONS_GCP + [extensions.virustotal]=$EXTENSIONS_VIRUSTOTAL + [extensions.osquery]=$EXTENSIONS_OSQUERY + [extensions.docker]=$EXTENSIONS_DOCKER + [timeout]=$APP_TIMEOUT + [api.selector]=$API_SELECTOR + [ip.selector]=$IP_SELECTOR + [ip.ignore]=$IP_IGNORE + [wazuh.monitoring.enabled]=$WAZUH_MONITORING_ENABLED + [wazuh.monitoring.frequency]=$WAZUH_MONITORING_FREQUENCY + [wazuh.monitoring.shards]=$WAZUH_MONITORING_SHARDS + [wazuh.monitoring.replicas]=$WAZUH_MONITORING_REPLICAS + [admin]=$ADMIN_PRIVILEGES +) + +for i in "${!CONFIG_MAP[@]}" +do + if [ "${CONFIG_MAP[$i]}" != "" ]; then + sed -i 's/.*#'"$i"'.*/'"$i"': '"${CONFIG_MAP[$i]}"'/' $kibana_config_file + fi +done + +CONFIG_CODE=$(curl ${auth} -s -o /dev/null -w "%{http_code}" -XGET $el_url/.wazuh/_doc/1513629884013) + +grep -q 1513629884013 $kibana_config_file +_config_exists=$? + +if [[ "x$CONFIG_CODE" != "x200" && $_config_exists -ne 0 ]]; then +cat << EOF >> $kibana_config_file +hosts: + - 1513629884013: + url: $wazuh_url + port: $wazuh_port + username: $api_username + password: $api_password +EOF +else + echo "Wazuh APP already configured" +fi diff --git a/kibana/config/xpack_config.sh b/kibana/config/xpack_config.sh new file mode 100644 index 00000000..fedfad4e --- /dev/null +++ b/kibana/config/xpack_config.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# Wazuh Docker Copyright (C) 2020 Wazuh Inc. (License GPLv2) + +kibana_config_file="/usr/share/kibana/config/kibana.yml" +if grep -Fq "#xpack features" "$kibana_config_file"; +then + declare -A CONFIG_MAP=( + [xpack.apm.ui.enabled]=$XPACK_APM + [xpack.grokdebugger.enabled]=$XPACK_DEVTOOLS + [xpack.searchprofiler.enabled]=$XPACK_DEVTOOLS + [xpack.ml.enabled]=$XPACK_ML + [xpack.canvas.enabled]=$XPACK_CANVAS + [xpack.infra.enabled]=$XPACK_INFRA + [xpack.monitoring.enabled]=$XPACK_MONITORING + [console.enabled]=$XPACK_DEVTOOLS + ) + for i in "${!CONFIG_MAP[@]}" + do + if [ "${CONFIG_MAP[$i]}" != "" ]; then + sed -i 's/.'"$i"'.*/'"$i"': '"${CONFIG_MAP[$i]}"'/' $kibana_config_file + fi + done +else + echo " +#xpack features +xpack.apm.ui.enabled: $XPACK_APM +xpack.grokdebugger.enabled: $XPACK_DEVTOOLS +xpack.searchprofiler.enabled: $XPACK_DEVTOOLS +xpack.ml.enabled: $XPACK_ML +xpack.canvas.enabled: $XPACK_CANVAS +xpack.infra.enabled: $XPACK_INFRA +xpack.monitoring.enabled: $XPACK_MONITORING +console.enabled: $XPACK_DEVTOOLS +" >> $kibana_config_file +fi