diff --git a/.github/actions/offline-installation/common.sh b/.github/actions/offline-installation/common.sh new file mode 100644 index 0000000..1adc952 --- /dev/null +++ b/.github/actions/offline-installation/common.sh @@ -0,0 +1,317 @@ +#!/bin/bash + +function check_package() { + + if [ "${sys_type}" == "deb" ]; then + if ! apt list --installed 2>/dev/null | grep -q "${1}"; then + echo "INFO: The package "${1}" is not installed." + return 1 + fi + elif [ "${sys_type}" == "rpm" ]; then + if ! yum list installed 2>/dev/null | grep -q "${1}"; then + echo "INFO: The package "${1}" is not installed." + return 1 + fi + fi + return 0 + +} + +function check_system() { + + if [ -n "$(command -v yum)" ]; then + sys_type="rpm" + echo "INFO: RPM system detected." + elif [ -n "$(command -v apt-get)" ]; then + sys_type="deb" + echo "INFO: DEB system detected." + else + echo "ERROR: could not detect the system." + exit 1 + fi + +} + +function check_file() { + + if [ ! -f "${1}" ]; then + echo "ERROR: The ${1} file could not be downloaded." + exit 1 + fi + +} + +function check_shards() { + + retries=0 + until [ "$(curl -s -k -u admin:admin "https://127.0.0.1:9200/_template/wazuh?pretty&filter_path=wazuh.settings.index.number_of_shards" | grep "number_of_shards")" ] || [ "${retries}" -eq 5 ]; do + sleep 5 + retries=$((retries+1)) + done + + if [ ${retries} -eq 5 ]; then + echo "ERROR: Could not get the number of shards." + exit 1 + fi + curl -s -k -u admin:admin "https://127.0.0.1:9200/_template/wazuh?pretty&filter_path=wazuh.settings.index.number_of_shards" + echo "INFO: Number of shards detected." + +} + +function dashboard_installation() { + + install_package "wazuh-dashboard" + check_package "wazuh-dashboard" + + echo "INFO: Generating certificates of the Wazuh dashboard..." + NODE_NAME=dashboard + mkdir /etc/wazuh-dashboard/certs + mv -n wazuh-certificates/$NODE_NAME.pem /etc/wazuh-dashboard/certs/dashboard.pem + mv -n wazuh-certificates/$NODE_NAME-key.pem /etc/wazuh-dashboard/certs/dashboard-key.pem + cp wazuh-certificates/root-ca.pem /etc/wazuh-dashboard/certs/ + chmod 500 /etc/wazuh-dashboard/certs + chmod 400 /etc/wazuh-dashboard/certs/* + chown -R wazuh-dashboard:wazuh-dashboard /etc/wazuh-dashboard/certs + + if [ "${sys_type}" == "deb" ]; then + enable_start_service "wazuh-dashboard" + elif [ "${sys_type}" == "rpm" ]; then + /usr/share/wazuh-dashboard/bin/opensearch-dashboards "-c /etc/wazuh-dashboard/opensearch_dashboards.yml" --allow-root > /dev/null 2>&1 & + fi + + retries=0 + # In this context, 302 HTTP code refers to SSL certificates warning: success. + until [ "$(curl -k -s -I -w "%{http_code}" https://127.0.0.1 -o /dev/null --fail)" -ne "302" ] || [ "${retries}" -eq 5 ]; do + echo "INFO: Sleeping 10 seconds." + sleep 10 + retries=$((retries+1)) + done + if [ ${retries} -eq 5 ]; then + echo "ERROR: The Wazuh dashboard installation has failed." + exit 1 + else + echo "INFO: The Wazuh dashboard is ready." + fi + +} + +function download_resources() { + + check_file "${ABSOLUTE_PATH}"/wazuh-install.sh + bash "${ABSOLUTE_PATH}"/wazuh-install.sh -dw "${sys_type}" + echo "INFO: Downloading the resources..." + + curl -sO https://packages.wazuh.com/4.10/config.yml + check_file "config.yml" + + sed -i -e '0,// s//127.0.0.1/' config.yml + sed -i -e '0,// s//127.0.0.1/' config.yml + sed -i -e '0,// s//127.0.0.1/' config.yml + + curl -sO https://packages.wazuh.com/4.10/wazuh-certs-tool.sh + check_file "wazuh-certs-tool.sh" + chmod 744 wazuh-certs-tool.sh + ./wazuh-certs-tool.sh --all + + tar xf wazuh-offline.tar.gz + echo "INFO: Download finished." + + if [ ! -d ./wazuh-offline ]; then + echo "ERROR: Could not download the resources." + exit 1 + fi + +} + +function enable_start_service() { + + systemctl daemon-reload + systemctl enable "${1}" + systemctl start "${1}" + + retries=0 + until [ "$(systemctl status "${1}" | grep "active")" ] || [ "${retries}" -eq 3 ]; do + sleep 2 + retries=$((retries+1)) + systemctl start "${1}" + done + + if [ ${retries} -eq 3 ]; then + echo "ERROR: The "${1}" service could not be started." + exit 1 + fi + +} + +function filebeat_installation() { + + install_package "filebeat" + check_package "filebeat" + + cp ./wazuh-offline/wazuh-files/filebeat.yml /etc/filebeat/ &&\ + cp ./wazuh-offline/wazuh-files/wazuh-template.json /etc/filebeat/ &&\ + chmod go+r /etc/filebeat/wazuh-template.json + + sed -i 's|\("index.number_of_shards": \)".*"|\1 "1"|' /etc/filebeat/wazuh-template.json + filebeat keystore create + echo admin | filebeat keystore add username --stdin --force + echo admin | filebeat keystore add password --stdin --force + tar -xzf ./wazuh-offline/wazuh-files/wazuh-filebeat-0.4.tar.gz -C /usr/share/filebeat/module + + echo "INFO: Generating certificates of Filebeat..." + NODE_NAME=wazuh-1 + mkdir /etc/filebeat/certs + mv -n wazuh-certificates/$NODE_NAME.pem /etc/filebeat/certs/filebeat.pem + mv -n wazuh-certificates/$NODE_NAME-key.pem /etc/filebeat/certs/filebeat-key.pem + cp wazuh-certificates/root-ca.pem /etc/filebeat/certs/ + chmod 500 /etc/filebeat/certs + chmod 400 /etc/filebeat/certs/* + chown -R root:root /etc/filebeat/certs + + if [ "${sys_type}" == "deb" ]; then + enable_start_service "filebeat" + elif [ "${sys_type}" == "rpm" ]; then + /usr/share/filebeat/bin/filebeat --environment systemd -c /etc/filebeat/filebeat.yml --path.home /usr/share/filebeat --path.config /etc/filebeat --path.data /var/lib/filebeat --path.logs /var/log/filebeat & + fi + + sleep 10 + check_shards + eval "filebeat test output" + if [ "${PIPESTATUS[0]}" != 0 ]; then + echo "ERROR: The Filebeat installation has failed." + exit 1 + fi + +} + +function indexer_initialize() { + + retries=0 + until [ "$(cat /var/log/wazuh-indexer/wazuh-cluster.log | grep "Node started")" ] || [ "${retries}" -eq 5 ]; do + sleep 5 + retries=$((retries+1)) + done + + if [ ${retries} -eq 5 ]; then + echo "ERROR: The indexer node is not started." + exit 1 + fi + /usr/share/wazuh-indexer/bin/indexer-security-init.sh + +} + +function indexer_installation() { + + if [ "${sys_type}" == "rpm" ]; then + rpm --import ./wazuh-offline/wazuh-files/GPG-KEY-WAZUH + fi + + install_package "wazuh-indexer" + check_package "wazuh-indexer" + + echo "INFO: Generating certificates of the Wazuh indexer..." + NODE_NAME=node-1 + mkdir /etc/wazuh-indexer/certs + mv -n wazuh-certificates/$NODE_NAME.pem /etc/wazuh-indexer/certs/indexer.pem + mv -n wazuh-certificates/$NODE_NAME-key.pem /etc/wazuh-indexer/certs/indexer-key.pem + mv wazuh-certificates/admin-key.pem /etc/wazuh-indexer/certs/ + mv wazuh-certificates/admin.pem /etc/wazuh-indexer/certs/ + cp wazuh-certificates/root-ca.pem /etc/wazuh-indexer/certs/ + chmod 500 /etc/wazuh-indexer/certs + chmod 400 /etc/wazuh-indexer/certs/* + chown -R wazuh-indexer:wazuh-indexer /etc/wazuh-indexer/certs + + sed -i 's|\(network.host: \)"0.0.0.0"|\1"127.0.0.1"|' /etc/wazuh-indexer/opensearch.yml + + if [ "${sys_type}" == "rpm" ]; then + runuser "wazuh-indexer" --shell="/bin/bash" --command="OPENSEARCH_PATH_CONF=/etc/wazuh-indexer /usr/share/wazuh-indexer/bin/opensearch" > /dev/null 2>&1 & + sleep 5 + elif [ "${sys_type}" == "deb" ]; then + enable_start_service "wazuh-indexer" + fi + + indexer_initialize + sleep 10 + eval "curl -s -XGET https://127.0.0.1:9200 -u admin:admin -k --fail" + if [ "${PIPESTATUS[0]}" != 0 ]; then + echo "ERROR: The Wazuh indexer installation has failed." + exit 1 + fi + +} + +function install_dependencies() { + + if [ "${sys_type}" == "rpm" ]; then + dependencies=( util-linux initscripts openssl ) + not_installed=() + for dep in "${dependencies[@]}"; do + if [ "${dep}" == "openssl" ]; then + if ! yum list installed 2>/dev/null | grep -q "${dep}\.";then + not_installed+=("${dep}") + fi + elif ! yum list installed 2>/dev/null | grep -q "${dep}";then + not_installed+=("${dep}") + fi + done + + if [ "${#not_installed[@]}" -gt 0 ]; then + echo "--- Dependencies ---" + for dep in "${not_installed[@]}"; do + echo "Installing $dep." + eval "yum install ${dep} -y" + if [ "${PIPESTATUS[0]}" != 0 ]; then + echo "ERROR: Cannot install dependency: ${dep}." + exit 1 + fi + done + fi + + elif [ "${sys_type}" == "deb" ]; then + eval "apt-get update -q > /dev/null" + dependencies=( openssl ) + not_installed=() + + for dep in "${dependencies[@]}"; do + if ! apt list --installed 2>/dev/null | grep -q "${dep}"; then + not_installed+=("${dep}") + fi + done + + if [ "${#not_installed[@]}" -gt 0 ]; then + echo "--- Dependencies ----" + for dep in "${not_installed[@]}"; do + echo "Installing $dep." + apt-get install -y "${dep}" + if [ "${install_result}" != 0 ]; then + echo "ERROR: Cannot install dependency: ${dep}." + exit 1 + fi + done + fi + fi + +} + +function install_package() { + + if [ "${sys_type}" == "deb" ]; then + dpkg -i ./wazuh-offline/wazuh-packages/"${1}"*.deb + elif [ "${sys_type}" == "rpm" ]; then + rpm -ivh ./wazuh-offline/wazuh-packages/"${1}"*.rpm + fi + +} + +function manager_installation() { + + install_package "wazuh-manager" + check_package "wazuh-manager" + + if [ "${sys_type}" == "deb" ]; then + enable_start_service "wazuh-manager" + elif [ "${sys_type}" == "rpm" ]; then + /var/ossec/bin/wazuh-control start + fi + +} diff --git a/.github/actions/offline-installation/offline-installation.sh b/.github/actions/offline-installation/offline-installation.sh new file mode 100644 index 0000000..787b20b --- /dev/null +++ b/.github/actions/offline-installation/offline-installation.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Gets the absolute path of the script, used to load the common.sh file +ABSOLUTE_PATH="$( cd $(dirname ${0}) ; pwd -P )" +. ${ABSOLUTE_PATH}/common.sh + +check_system +install_dependencies +download_resources + +indexer_installation +echo "INFO: Wazuh indexer installation completed." + +manager_installation +echo "INFO: Wazuh manager installation completed." + +filebeat_installation +echo "INFO: Filebeat installation completed." + +dashboard_installation +echo "INFO: Wazuh dashboard installation completed." diff --git a/.github/actions/passwords-tool/tests-stack-failure.sh b/.github/actions/passwords-tool/tests-stack-failure.sh new file mode 100644 index 0000000..223f989 --- /dev/null +++ b/.github/actions/passwords-tool/tests-stack-failure.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +apiPass="$(cat wazuh-install-files/wazuh-passwords.txt | awk "/username: 'wazuh'/{getline;print;}" | awk '{ print $2 }' | tr -d \' )" +adminPass="$(cat wazuh-install-files/wazuh-passwords.txt | awk "/username: 'admin'/{getline;print;}" | awk '{ print $2 }' | tr -d \')" + +if ! bash wazuh-passwords-tool.sh -u wazuuuh | grep "ERROR"; then + exit 1 +elif ! sudo bash wazuh-passwords-tool.sh -u admin -p password | grep "ERROR"; then + exit 1 +elif ! sudo bash wazuh-passwords-tool.sh -au wazuh -ap "${adminPass}" -u wazuh -p password -A | grep "ERROR"; then + exit 1 +elif ! curl -s -u wazuh:wazuh -k -X POST "https://127.0.0.1:55000/security/user/authenticate" | grep "Invalid credentials"; then + exit 1 +elif ! curl -s -u wazuuh:"${apiPass}" -k -X POST "https://127.0.0.1:55000/security/user/authenticate" | grep "Invalid credentials"; then + exit 1 +elif ! curl -s -XGET https://127.0.0.1:9200/ -u admin:admin -k | grep "Unauthorized"; then + exit 1 +elif ! curl -s -XGET https://127.0.0.1:9200/ -u adminnnn:"${adminPass}" -k | grep "Unauthorized"; then + exit 1 +fi diff --git a/.github/actions/passwords-tool/tests-stack-success.sh b/.github/actions/passwords-tool/tests-stack-success.sh new file mode 100644 index 0000000..0782439 --- /dev/null +++ b/.github/actions/passwords-tool/tests-stack-success.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +users=( admin kibanaserver kibanaro logstash readall snapshotrestore ) +api_users=( wazuh wazuh-wui ) + +echo '::group:: Change indexer password, password providing it.' + +bash wazuh-passwords-tool.sh -u admin -p LN*X1v.VNtCZ5sESEtLfijPAd39LXGAI +if curl -s -XGET https://127.0.0.1:9200/ -u admin:LN*X1v.VNtCZ5sESEtLfijPAd39LXGAI -k -w %{http_code} | grep "401"; then + exit 1 +fi +echo '::endgroup::' + +echo '::group:: Change indexer password without providing it.' + +indx_pass="$(bash wazuh-passwords-tool.sh -u admin | awk '/admin/{ print $NF }' | tr -d \' )" +if curl -s -XGET https://127.0.0.1:9200/ -u admin:"${indx_pass}" -k -w %{http_code} | grep "401"; then + exit 1 +fi + +echo '::endgroup::' + +echo '::group:: Change all passwords except Wazuh API ones.' + +mapfile -t pass < <(bash wazuh-passwords-tool.sh -a | grep 'The password for' | awk '{ print $NF }') +for i in "${!users[@]}"; do + if curl -s -XGET https://127.0.0.1:9200/ -u "${users[i]}":"${pass[i]}" -k -w %{http_code} | grep "401"; then + exit 1 + fi +done + +echo '::endgroup::' + +echo '::group:: Change all passwords.' + +wazuh_pass="$(cat wazuh-install-files/wazuh-passwords.txt | awk "/username: 'wazuh'/{getline;print;}" | awk '{ print $2 }' | tr -d \' )" + +mapfile -t passall < <(bash wazuh-passwords-tool.sh -a -au wazuh -ap "${wazuh_pass}" | grep 'The password for' | awk '{ print $NF }' ) +passindexer=("${passall[@]:0:6}") +passapi=("${passall[@]:(-2)}") + +for i in "${!users[@]}"; do + if curl -s -XGET https://127.0.0.1:9200/ -u "${users[i]}":"${passindexer[i]}" -k -w %{http_code} | grep "401"; then + exit 1 + fi +done + +for i in "${!api_users[@]}"; do + if curl -s -u "${api_users[i]}":"${passapi[i]}" -w "%{http_code}" -k -X POST "https://127.0.0.1:55000/security/user/authenticate" | grep "401"; then + exit 1 + fi +done + +echo '::endgroup::' + +echo '::group:: Change single Wazuh API user.' + +bash wazuh-passwords-tool.sh -au wazuh -ap "${passapi[0]}" -u wazuh -p BkJt92r*ndzN.CkCYWn?d7i5Z7EaUt63 -A + if curl -s -w "%{http_code}" -u wazuh:BkJt92r*ndzN.CkCYWn?d7i5Z7EaUt63 -k -X POST "https://127.0.0.1:55000/security/user/authenticate" | grep "401"; then + exit 1 + fi +echo '::endgroup::' + +echo '::group:: Change all passwords except Wazuh API ones using a file.' + +mapfile -t passfile < <(bash wazuh-passwords-tool.sh -f wazuh-install-files/wazuh-passwords.txt | grep 'The password for' | awk '{ print $NF }' ) +for i in "${!users[@]}"; do + if curl -s -XGET https://127.0.0.1:9200/ -u "${users[i]}":"${passfile[i]}" -k -w %{http_code} | grep "401"; then + exit 1 + fi +done +echo '::endgroup::' + +echo '::group:: Change all passwords from a file.' +mapfile -t passallf < <(bash wazuh-passwords-tool.sh -f wazuh-install-files/wazuh-passwords.txt -au wazuh -ap BkJt92r*ndzN.CkCYWn?d7i5Z7EaUt63 | grep 'The password for' | awk '{ print $NF }' ) +passindexerf=("${passallf[@]:0:6}") +passapif=("${passallf[@]:(-2)}") + +for i in "${!users[@]}"; do + if curl -s -XGET https://127.0.0.1:9200/ -u "${users[i]}":"${passindexerf[i]}" -k -w %{http_code} | grep "401"; then + exit 1 + fi +done + +for i in "${!api_users[@]}"; do + if curl -s -u "${api_users[i]}":"${passapif[i]}" -w "%{http_code}" -k -X POST "https://127.0.0.1:55000/security/user/authenticate" | grep "401"; then + exit 1 + fi +done + +echo '::endgroup::' diff --git a/.github/workflows/offline-installation.yml b/.github/workflows/offline-installation.yml new file mode 100644 index 0000000..1d31ec4 --- /dev/null +++ b/.github/workflows/offline-installation.yml @@ -0,0 +1,61 @@ +name: Offline installation test +on: + pull_request: + paths: + - 'install_functions/wazuh-offline-download.sh' + - 'install_functions/wazuh-offline-installation.sh' + workflow_dispatch: + +jobs: + Build-wazuh-install-script: + runs-on: ubuntu-latest + steps: + - name: Cancel previous runs + uses: fkirc/skip-duplicate-actions@master + with: + cancel_others: 'true' + github_token: ${{ secrets.GITHUB_TOKEN }} + skip_after_successful_duplicate: 'false' + + - uses: actions/checkout@v4 + + - name: Build wazuh-install script and use staging packages + run: bash builder.sh -i -d staging + + - uses: actions/upload-artifact@v3 + with: + name: script + path: ./wazuh-install.sh + if-no-files-found: error + + Test-offline-installation-debian: + runs-on: ubuntu-latest + needs: Build-wazuh-install-script + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v3 + with: + name: script + + - name: Move installation assistant script + run: cp $GITHUB_WORKSPACE/wazuh-install.sh $GITHUB_WORKSPACE/.github/actions/offline-installation/wazuh-install.sh + + - name: Run script + run: sudo bash $GITHUB_WORKSPACE/.github/actions/offline-installation/offline-installation.sh + + Test-offline-installation-rpm: + runs-on: ubuntu-latest + needs: Build-wazuh-install-script + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v3 + with: + name: script + + - name: Move installation assistant script + run: cp $GITHUB_WORKSPACE/wazuh-install.sh $GITHUB_WORKSPACE/.github/actions/offline-installation/wazuh-install.sh + + - name: Launch docker and run script + run: sudo docker run -v $GITHUB_WORKSPACE/.github/actions/offline-installation/:/tests centos:centos7 bash /tests/offline-installation.sh diff --git a/.github/workflows/password-tool.yml b/.github/workflows/password-tool.yml new file mode 100644 index 0000000..9584fc0 --- /dev/null +++ b/.github/workflows/password-tool.yml @@ -0,0 +1,54 @@ +on: + pull_request: + paths: + - 'passwords_tool/**' + +jobs: + Build-password-tool-and-wazuh-install-scripts: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build password-tool and wazuh-install scripts + run: | + bash builder.sh -p + bash builder.sh -i -d staging + shell: bash + - uses: actions/upload-artifact@v3 + with: + name: scripts + path: | + ./wazuh-install.sh + ./wazuh-passwords-tool.sh + if-no-files-found: error + + test-password-tool-success: + runs-on: ubuntu-latest + needs: Build-password-tool-and-wazuh-install-scripts + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v3 + with: + name: scripts + - name: Install wazuh + run: | + sudo bash wazuh-install.sh -a -v + - name: Uncompress wazuh install files + run: sudo tar -xvf wazuh-install-files.tar + - name: Run script + run: sudo bash .github/actions/passwords-tool/tests-stack-success.sh + + test-password-tool-failure: + runs-on: ubuntu-latest + needs: Build-password-tool-and-wazuh-install-scripts + steps: + - uses: actions/checkout@v4 + - uses: actions/download-artifact@v3 + with: + name: scripts + - name: Install wazuh + run: | + sudo bash wazuh-install.sh -a -v + - name: Uncompress wazuh install files + run: sudo tar -xvf wazuh-install-files.tar + - name: Run script + run: sudo bash .github/actions/passwords-tool/tests-stack-failure.sh