diff --git a/.github/actions/comment-test-coverage/README.md b/.github/actions/comment-test-coverage/README.md index e86b5f2238..b20a220ab1 100644 --- a/.github/actions/comment-test-coverage/README.md +++ b/.github/actions/comment-test-coverage/README.md @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout Code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Run Jasmine tests run: npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0b144db595..d6623591c4 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -9,11 +9,11 @@ # the `language` matrix defined below to confirm you have the correct set of # supported CodeQL languages. # -name: "CodeQL" +name: 'CodeQL' on: schedule: - - cron: '0 8 * * *' + - cron: '0 8 * * *' workflow_dispatch: jobs: @@ -28,45 +28,44 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'javascript' ] + language: ['javascript'] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Use only 'java' to analyze code written in Java, Kotlin or both # Use only 'javascript' to analyze code written in JavaScript, TypeScript or both # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v4 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 - # Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 + # ℹī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - # ℹī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 - with: - category: "/language:${{matrix.language}}" + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: '/language:${{matrix.language}}' diff --git a/.github/workflows/cypress-basic.yml b/.github/workflows/cypress-basic.yml index e0465d7e2c..d8c6725c5e 100644 --- a/.github/workflows/cypress-basic.yml +++ b/.github/workflows/cypress-basic.yml @@ -12,18 +12,18 @@ on: description: 'Wazuh Version' default: 'v4.3.4' required: true - elastic-version: + elastic-version: description: 'Elastic Version' default: '7.16.3' required: true - ubuntu-cypress-version: + ubuntu-cypress-version: description: 'Ubuntu Cypress Version' default: '3.0.0' required: true url-package: description: 'Package Download Url' - required: false - default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' + required: false + default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -31,83 +31,85 @@ jobs: name: Run setup environment wazuh kibana app runs-on: ubuntu-latest steps: - - name: Step 01 - Set up environment variables - run: | - echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_basic-wz_cluster-agent/" >> $GITHUB_ENV + - name: Step 01 - Set up environment variables + run: | + echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_basic-wz_cluster-agent/" >> $GITHUB_ENV - echo "Information about the workflow (basic): - wazuh-version: ${{ github.event.inputs.wazuh-version }} - elastic-version: ${{ github.event.inputs.elastic-version }} - ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} - url-package: ${{ github.event.inputs.url-package }}" - - - name: Step 02 - Download Project wazuh-app-environments - uses: actions/checkout@v2 - with: - repository: matiasmoreno876/wazuh-app-environments - ref: 'master' - path: wazuh-app-environments - token: ${{ secrets.FE_SECRET_TOKEN }} - - name: Step 03 - Configuring templates docker environment - run: | - cd $GITHUB_WORKSPACE/wazuh-app-environments/ - mkdir packages - cd ${{ env.PATH_TEMPLATE }} - sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env - sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env - sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env - cat .env - - name: Step 04 - Starting containers - run: | - cd ${{ env.PATH_TEMPLATE }} - docker-compose up -d - echo CONTINUES AFTER 15 SECONDS ... - sleep 15s - - name: Step 05 - Installing package from url - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} - docker-compose restart kibana - echo CONTINUES AFTER 60 SECONDS ... - sleep 60s - docker-compose ps - - name: Step 06 - Configuring ip container into wazuh.yml - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml - docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml - - name: Step 07 - Run Cypress tests - id: run-cypress-test - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:basic" | tee cypress.log - continue-on-error: true - - name: Step 08 - Run Cypress reports - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" - - name: Step 09 - Archive reports - uses: actions/upload-artifact@v2 - with: - name: cypress-reports_BASIC_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.elastic-version }} - path: ${{ env.PATH_TEMPLATE }}/report/* - - name: Step 10 - Log parsing - run: | - cd ${{ env.PATH_TEMPLATE }} - echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV - echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV - echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV - echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV - echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV - echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV - - name: Step 11 - Post to a Slack channel - id: slack - uses: slackapi/slack-github-action@v1.19.0 - with: + echo "Information about the workflow (basic): + wazuh-version: ${{ github.event.inputs.wazuh-version }} + elastic-version: ${{ github.event.inputs.elastic-version }} + ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} + url-package: ${{ github.event.inputs.url-package }}" + + - name: Step 02 - Download Project wazuh-app-environments + uses: actions/checkout@v4 + with: + repository: matiasmoreno876/wazuh-app-environments + ref: 'master' + path: wazuh-app-environments + token: ${{ secrets.FE_SECRET_TOKEN }} + - name: Step 03 - Configuring templates docker environment + run: | + cd $GITHUB_WORKSPACE/wazuh-app-environments/ + mkdir packages + cd ${{ env.PATH_TEMPLATE }} + sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env + sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env + sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env + cat .env + - name: Step 04 - Starting containers + run: | + cd ${{ env.PATH_TEMPLATE }} + docker-compose up -d + echo CONTINUES AFTER 15 SECONDS ... + sleep 15s + - name: Step 05 - Installing package from url + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} + docker-compose restart kibana + echo CONTINUES AFTER 60 SECONDS ... + sleep 60s + docker-compose ps + - name: Step 06 - Configuring ip container into wazuh.yml + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml + docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml + - name: Step 07 - Run Cypress tests + id: run-cypress-test + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:basic" | tee cypress.log + continue-on-error: true + - name: Step 08 - Run Cypress reports + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" + - name: Step 09 - Archive reports + uses: actions/upload-artifact@v4 + with: + name: cypress-reports_BASIC_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.elastic-version }} + path: ${{ env.PATH_TEMPLATE }}/report/* + overwrite: true + - name: Step 10 - Log parsing + run: | + cd ${{ env.PATH_TEMPLATE }} + echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV + echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV + echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV + echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV + echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV + echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV + - name: Step 11 - Post to a Slack channel + id: slack + uses: slackapi/slack-github-action@v1.19.0 + with: # Slack channel id, channel name, or user id to post message. # See also: https://api.slack.com/methods/chat.postMessage#channels - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - # For posting a simple plain text message - slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} \ No newline at end of file + channel-id: + ${{ secrets.SLACK_CHANNEL_ID }} + # For posting a simple plain text message + slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + env: + SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} diff --git a/.github/workflows/cypress-odfe.yml b/.github/workflows/cypress-odfe.yml index e95263a91a..241c8e9cd1 100644 --- a/.github/workflows/cypress-odfe.yml +++ b/.github/workflows/cypress-odfe.yml @@ -12,22 +12,22 @@ on: description: 'Wazuh Version' default: 'v4.3.4' required: true - elastic-version: + elastic-version: description: 'Elastic Version' default: '7.10.2' required: true - odfe-version: + odfe-version: description: 'ODFE Version' default: '1.13.2' required: true - ubuntu-cypress-version: + ubuntu-cypress-version: description: 'Ubuntu Cypress Version' default: '3.0.0' required: true url-package: description: 'Package Download Url' - required: false - default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' + required: false + default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -35,85 +35,87 @@ jobs: name: Run setup environment wazuh kibana app runs-on: ubuntu-latest steps: - - name: Step 01 - Set up environment variables - run: | - echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_odfe-wz_cluster-agent/" >> $GITHUB_ENV + - name: Step 01 - Set up environment variables + run: | + echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_odfe-wz_cluster-agent/" >> $GITHUB_ENV - echo "Information about the workflow (odfe): - wazuh-version: ${{ github.event.inputs.wazuh-version }} - elastic-version: ${{ github.event.inputs.elastic-version }} - odfe-version: ${{ github.event.inputs.odfe-version }} - ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} - url-package: ${{ github.event.inputs.url-package }}" - - - name: Step 02 - Download Project wazuh-app-environments - uses: actions/checkout@v2 - with: - repository: matiasmoreno876/wazuh-app-environments - ref: 'master' - path: wazuh-app-environments - token: ${{ secrets.FE_SECRET_TOKEN }} - - name: Step 03 - Configuring templates docker environment - run: | - cd $GITHUB_WORKSPACE/wazuh-app-environments/ - mkdir packages - cd ${{ env.PATH_TEMPLATE }} - sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env - sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env - sed -i -e 's|ODFE_VERSION=.*|ODFE_VERSION=${{ github.event.inputs.odfe-version }}|g' ./.env - sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env - cat .env - - name: Step 04 - Starting containers - run: | - cd ${{ env.PATH_TEMPLATE }} - docker-compose up -d - echo CONTINUES AFTER 15 SECONDS ... - sleep 15s - - name: Step 05 - Installing package from url - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} - docker-compose restart kibana - echo CONTINUES AFTER 60 SECONDS ... - sleep 60s - docker-compose ps - - name: Step 06 - Configuring ip container into wazuh.yml - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml - docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml - - name: Step 07 - Run Cypress tests - id: run-cypress-test - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:odfe" | tee cypress.log - continue-on-error: true - - name: Step 08 - Run Cypress reports - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" - - name: Step 09 - Archive reports - uses: actions/upload-artifact@v2 - with: - name: cypress-reports_ODFE_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.odfe-version }}-${{ github.event.inputs.elastic-version }} - path: ${{ env.PATH_TEMPLATE }}/report/* - - name: Step 10 - Log parsing - run: | - cd ${{ env.PATH_TEMPLATE }} - echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV - echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV - echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV - echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV - echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV - echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV - - name: Step 11 - Post to a Slack channel - id: slack - uses: slackapi/slack-github-action@v1.19.0 - with: + echo "Information about the workflow (odfe): + wazuh-version: ${{ github.event.inputs.wazuh-version }} + elastic-version: ${{ github.event.inputs.elastic-version }} + odfe-version: ${{ github.event.inputs.odfe-version }} + ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} + url-package: ${{ github.event.inputs.url-package }}" + + - name: Step 02 - Download Project wazuh-app-environments + uses: actions/checkout@v4 + with: + repository: matiasmoreno876/wazuh-app-environments + ref: 'master' + path: wazuh-app-environments + token: ${{ secrets.FE_SECRET_TOKEN }} + - name: Step 03 - Configuring templates docker environment + run: | + cd $GITHUB_WORKSPACE/wazuh-app-environments/ + mkdir packages + cd ${{ env.PATH_TEMPLATE }} + sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env + sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env + sed -i -e 's|ODFE_VERSION=.*|ODFE_VERSION=${{ github.event.inputs.odfe-version }}|g' ./.env + sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env + cat .env + - name: Step 04 - Starting containers + run: | + cd ${{ env.PATH_TEMPLATE }} + docker-compose up -d + echo CONTINUES AFTER 15 SECONDS ... + sleep 15s + - name: Step 05 - Installing package from url + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} + docker-compose restart kibana + echo CONTINUES AFTER 60 SECONDS ... + sleep 60s + docker-compose ps + - name: Step 06 - Configuring ip container into wazuh.yml + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml + docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml + - name: Step 07 - Run Cypress tests + id: run-cypress-test + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:odfe" | tee cypress.log + continue-on-error: true + - name: Step 08 - Run Cypress reports + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" + - name: Step 09 - Archive reports + uses: actions/upload-artifact@v4 + with: + name: cypress-reports_ODFE_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.odfe-version }}-${{ github.event.inputs.elastic-version }} + path: ${{ env.PATH_TEMPLATE }}/report/* + overwrite: true + - name: Step 10 - Log parsing + run: | + cd ${{ env.PATH_TEMPLATE }} + echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV + echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV + echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV + echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV + echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV + echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV + - name: Step 11 - Post to a Slack channel + id: slack + uses: slackapi/slack-github-action@v1.19.0 + with: # Slack channel id, channel name, or user id to post message. # See also: https://api.slack.com/methods/chat.postMessage#channels - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - # For posting a simple plain text message - slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nODFE version: ${{ github.event.inputs.odfe-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} \ No newline at end of file + channel-id: + ${{ secrets.SLACK_CHANNEL_ID }} + # For posting a simple plain text message + slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nODFE version: ${{ github.event.inputs.odfe-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + env: + SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} diff --git a/.github/workflows/cypress-wzd.yml b/.github/workflows/cypress-wzd.yml index 8e0b051142..b4abd30034 100644 --- a/.github/workflows/cypress-wzd.yml +++ b/.github/workflows/cypress-wzd.yml @@ -12,14 +12,14 @@ on: description: 'Wazuh Stack Version' default: '4.3.4' required: true - ubuntu-cypress-version: + ubuntu-cypress-version: description: 'Ubuntu Cypress Version' default: '3.0.0' required: true url-package: description: 'Package Download Url' - required: false - default: 'https://packages-dev.wazuh.com/pre-release/ui/dashboard/wazuh-4.3.4-1.zip' + required: false + default: 'https://packages-dev.wazuh.com/pre-release/ui/dashboard/wazuh-4.3.4-1.zip' # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -27,84 +27,86 @@ jobs: name: Run setup environment wazuh dashboard app runs-on: ubuntu-latest steps: - - name: Step 01 - Set up environment variables - run: | - echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_wazuh_prod/" >> $GITHUB_ENV + - name: Step 01 - Set up environment variables + run: | + echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_wazuh_prod/" >> $GITHUB_ENV - echo "Information about the workflow (wzd): - wazuh-stack-version: ${{ github.event.inputs.wazuh-stack-version }} - ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} - url-package: ${{ github.event.inputs.url-package }}" - - - name: Step 02 - Download Project wazuh-app-environments - uses: actions/checkout@v2 - with: - repository: matiasmoreno876/wazuh-app-environments - ref: 'master' - path: wazuh-app-environments - token: ${{ secrets.FE_SECRET_TOKEN }} - - name: Step 03 - Configuring templates docker environment - run: | - cd $GITHUB_WORKSPACE/wazuh-app-environments/ - mkdir packages - cd ${{ env.PATH_TEMPLATE }} - sed -i -e 's|WAZUH_STACK_VERSION=.*|WAZUH_STACK_VERSION=${{ github.event.inputs.wazuh-stack-version }}|g' ./.env - sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env - cat .env - - name: Step 04 - Starting containers - run: | - cd ${{ env.PATH_TEMPLATE }} - docker-compose up -d - echo CONTINUES AFTER 30 SECONDS ... - sleep 30s - - name: Step 05 - Remove Wazuh - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q wazuh.dashboard) bin/opensearch-dashboards-plugin remove wazuh - docker-compose restart wazuh.dashboard - echo CONTINUES AFTER 30 SECONDS ... - sleep 30s - docker-compose ps - - name: Step 06 - Installing package from url - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q wazuh.dashboard) bin/opensearch-dashboards-plugin install ${{ github.event.inputs.url-package }} - docker-compose restart wazuh.dashboard - echo CONTINUES AFTER 60 SECONDS ... - sleep 60s - docker-compose ps - - name: Step 07 - Run Cypress tests - id: run-cypress-test - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:wzd" | tee cypress.log - continue-on-error: true - - name: Step 08 - Run Cypress reports - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" - - name: Step 09 - Archive reports - uses: actions/upload-artifact@v2 - with: - name: cypress-reports_WZD_${{ github.event.inputs.wazuh-stack-version }} - path: ${{ env.PATH_TEMPLATE }}/report/* - - name: Step 10 - Log parsing - run: | - cd ${{ env.PATH_TEMPLATE }} - echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV - echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV - echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV - echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV - echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV - echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV - - name: Step 11 - Post to a Slack channel - id: slack - uses: slackapi/slack-github-action@v1.19.0 - with: + echo "Information about the workflow (wzd): + wazuh-stack-version: ${{ github.event.inputs.wazuh-stack-version }} + ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} + url-package: ${{ github.event.inputs.url-package }}" + + - name: Step 02 - Download Project wazuh-app-environments + uses: actions/checkout@v4 + with: + repository: matiasmoreno876/wazuh-app-environments + ref: 'master' + path: wazuh-app-environments + token: ${{ secrets.FE_SECRET_TOKEN }} + - name: Step 03 - Configuring templates docker environment + run: | + cd $GITHUB_WORKSPACE/wazuh-app-environments/ + mkdir packages + cd ${{ env.PATH_TEMPLATE }} + sed -i -e 's|WAZUH_STACK_VERSION=.*|WAZUH_STACK_VERSION=${{ github.event.inputs.wazuh-stack-version }}|g' ./.env + sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env + cat .env + - name: Step 04 - Starting containers + run: | + cd ${{ env.PATH_TEMPLATE }} + docker-compose up -d + echo CONTINUES AFTER 30 SECONDS ... + sleep 30s + - name: Step 05 - Remove Wazuh + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q wazuh.dashboard) bin/opensearch-dashboards-plugin remove wazuh + docker-compose restart wazuh.dashboard + echo CONTINUES AFTER 30 SECONDS ... + sleep 30s + docker-compose ps + - name: Step 06 - Installing package from url + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q wazuh.dashboard) bin/opensearch-dashboards-plugin install ${{ github.event.inputs.url-package }} + docker-compose restart wazuh.dashboard + echo CONTINUES AFTER 60 SECONDS ... + sleep 60s + docker-compose ps + - name: Step 07 - Run Cypress tests + id: run-cypress-test + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:wzd" | tee cypress.log + continue-on-error: true + - name: Step 08 - Run Cypress reports + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" + - name: Step 09 - Archive reports + uses: actions/upload-artifact@v4 + with: + name: cypress-reports_WZD_${{ github.event.inputs.wazuh-stack-version }} + path: ${{ env.PATH_TEMPLATE }}/report/* + overwrite: true + - name: Step 10 - Log parsing + run: | + cd ${{ env.PATH_TEMPLATE }} + echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV + echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV + echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV + echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV + echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV + echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV + - name: Step 11 - Post to a Slack channel + id: slack + uses: slackapi/slack-github-action@v1.19.0 + with: # Slack channel id, channel name, or user id to post message. # See also: https://api.slack.com/methods/chat.postMessage#channels - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - # For posting a simple plain text message - slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh stack version: ${{ github.event.inputs.wazuh-stack-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} \ No newline at end of file + channel-id: + ${{ secrets.SLACK_CHANNEL_ID }} + # For posting a simple plain text message + slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh stack version: ${{ github.event.inputs.wazuh-stack-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + env: + SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} diff --git a/.github/workflows/cypress-xpack.yml b/.github/workflows/cypress-xpack.yml index a16f888eff..aa4a46be3a 100644 --- a/.github/workflows/cypress-xpack.yml +++ b/.github/workflows/cypress-xpack.yml @@ -12,18 +12,18 @@ on: description: 'Wazuh Version' default: 'v4.3.4' required: true - elastic-version: + elastic-version: description: 'Elastic Version' default: '7.16.3' required: true - ubuntu-cypress-version: + ubuntu-cypress-version: description: 'Ubuntu Cypress Version' default: '3.0.0' required: true url-package: description: 'Package Download Url' - required: false - default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' + required: false + default: 'https://packages-dev.wazuh.com/pre-release/ui/kibana/wazuh_kibana-4.3.4_7.16.3-1.zip' # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -31,84 +31,86 @@ jobs: name: Run setup environment wazuh kibana app runs-on: ubuntu-latest steps: - - name: Step 01 - Set up environment variables - run: | - echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_xpack-wz_cluster-agent/" >> $GITHUB_ENV + - name: Step 01 - Set up environment variables + run: | + echo "PATH_TEMPLATE=$GITHUB_WORKSPACE/wazuh-app-environments/templates_elastic_prod/es_xpack-wz_cluster-agent/" >> $GITHUB_ENV - echo "Information about the workflow (xpack): - wazuh-version: ${{ github.event.inputs.wazuh-version }} - elastic-version: ${{ github.event.inputs.elastic-version }} - ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} - url-package: ${{ github.event.inputs.url-package }}" - - - name: Step 02 - Download Project wazuh-app-environments - uses: actions/checkout@v2 - with: - repository: matiasmoreno876/wazuh-app-environments - ref: 'master' - path: wazuh-app-environments - token: ${{ secrets.FE_SECRET_TOKEN }} - - name: Step 03 - Configuring templates docker environment - run: | - cd $GITHUB_WORKSPACE/wazuh-app-environments/ - mkdir packages - cd ${{ env.PATH_TEMPLATE }} - sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env - sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env - sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env - cat .env - - name: Step 04 - Starting containers - run: | - cd ${{ env.PATH_TEMPLATE }} - sed -i -e 's|docker-compose exec elasticsearch|docker exec $(docker-compose ps -q elasticsearch)|g' ./setup.sh - sudo sh setup.sh - echo CONTINUES AFTER 15 SECONDS ... - sleep 15s - - name: Step 05 - Installing package from url - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} - docker-compose restart kibana - echo CONTINUES AFTER 60 SECONDS ... - sleep 60s - docker-compose ps - - name: Step 06 - Configuring ip container into wazuh.yml - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml - docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml - - name: Step 07 - Run Cypress tests - id: run-cypress-test - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:xpack" | tee cypress.log - continue-on-error: true - - name: Step 08 - Run Cypress reports - run: | - cd ${{ env.PATH_TEMPLATE }} - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" - - name: Step 09 - Archive reports - uses: actions/upload-artifact@v2 - with: - name: cypress-reports_XPACK_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.elastic-version }} - path: ${{ env.PATH_TEMPLATE }}/report/* - - name: Step 10 - Log parsing - run: | - cd ${{ env.PATH_TEMPLATE }} - echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV - echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV - echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV - echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV - echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV - echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV - - name: Step 11 - Post to a Slack channel - id: slack - uses: slackapi/slack-github-action@v1.19.0 - with: + echo "Information about the workflow (xpack): + wazuh-version: ${{ github.event.inputs.wazuh-version }} + elastic-version: ${{ github.event.inputs.elastic-version }} + ubuntu-cypress-version: ${{ github.event.inputs.ubuntu-cypress-version }} + url-package: ${{ github.event.inputs.url-package }}" + + - name: Step 02 - Download Project wazuh-app-environments + uses: actions/checkout@v4 + with: + repository: matiasmoreno876/wazuh-app-environments + ref: 'master' + path: wazuh-app-environments + token: ${{ secrets.FE_SECRET_TOKEN }} + - name: Step 03 - Configuring templates docker environment + run: | + cd $GITHUB_WORKSPACE/wazuh-app-environments/ + mkdir packages + cd ${{ env.PATH_TEMPLATE }} + sed -i -e 's|WAZUH_VERSION=.*|WAZUH_VERSION=${{ github.event.inputs.wazuh-version }}|g' ./.env + sed -i -e 's|ELASTIC_VERSION=.*|ELASTIC_VERSION=${{ github.event.inputs.elastic-version }}|g' ./.env + sed -i -e 's|UBUNTU_CYPRESS_VERSION=.*|UBUNTU_CYPRESS_VERSION=${{ github.event.inputs.ubuntu-cypress-version }}|g' ./.env + cat .env + - name: Step 04 - Starting containers + run: | + cd ${{ env.PATH_TEMPLATE }} + sed -i -e 's|docker-compose exec elasticsearch|docker exec $(docker-compose ps -q elasticsearch)|g' ./setup.sh + sudo sh setup.sh + echo CONTINUES AFTER 15 SECONDS ... + sleep 15s + - name: Step 05 - Installing package from url + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) bin/kibana-plugin install ${{ github.event.inputs.url-package }} + docker-compose restart kibana + echo CONTINUES AFTER 60 SECONDS ... + sleep 60s + docker-compose ps + - name: Step 06 - Configuring ip container into wazuh.yml + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q kibana) sed -i -e "s/url: https:\/\/localhost/url: https:\/\/wazuh-manager-master/g" /usr/share/kibana/data/wazuh/config/wazuh.yml + docker exec $(docker-compose ps -q kibana) cat /usr/share/kibana/data/wazuh/config/wazuh.yml + - name: Step 07 - Run Cypress tests + id: run-cypress-test + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:xpack" | tee cypress.log + continue-on-error: true + - name: Step 08 - Run Cypress reports + run: | + cd ${{ env.PATH_TEMPLATE }} + docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:report" + - name: Step 09 - Archive reports + uses: actions/upload-artifact@v4 + with: + name: cypress-reports_XPACK_${{ github.event.inputs.wazuh-version }}-${{ github.event.inputs.elastic-version }} + path: ${{ env.PATH_TEMPLATE }}/report/* + overwrite: true + - name: Step 10 - Log parsing + run: | + cd ${{ env.PATH_TEMPLATE }} + echo "TEST_SKIPPED=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF)}')" >> $GITHUB_ENV + echo "TEST_PENDING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-1)}')" >> $GITHUB_ENV + echo "TEST_FAILING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-2)}')" >> $GITHUB_ENV + echo "TEST_PASSING=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-3)}')" >> $GITHUB_ENV + echo "TEST_TOTAL=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-4)}')" >> $GITHUB_ENV + echo "TEST_TIME=$(grep -E "failed \(|passed" cypress.log | awk ' { print $(NF-5)}')" >> $GITHUB_ENV + - name: Step 11 - Post to a Slack channel + id: slack + uses: slackapi/slack-github-action@v1.19.0 + with: # Slack channel id, channel name, or user id to post message. # See also: https://api.slack.com/methods/chat.postMessage#channels - channel-id: ${{ secrets.SLACK_CHANNEL_ID }} - # For posting a simple plain text message - slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - env: - SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} \ No newline at end of file + channel-id: + ${{ secrets.SLACK_CHANNEL_ID }} + # For posting a simple plain text message + slack-message: "The following workflow was executed: ${{ github.workflow }}\nWazuh version: ${{ github.event.inputs.wazuh-version }}\nElastic version: ${{ github.event.inputs.elastic-version }}\nUbuntu Cypress version: ${{ github.event.inputs.ubuntu-cypress-version }}\nPackage used: ${{ github.event.inputs.url-package }}\n\nTest summary:\n\tTotal Test: ${{ env.TEST_TOTAL }}\n\tPassing: ${{ env.TEST_PASSING }}\n\tFailing: ${{ env.TEST_FAILING }}\n\tPending: ${{ env.TEST_PENDING }}\n\tSkipped: ${{ env.TEST_SKIPPED }}\n\tTotal Time: ${{ env.TEST_TIME }}\n\nFor more information visit: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" + env: + SLACK_BOT_TOKEN: ${{ secrets.ACTIONS_SLACK_TOKEN }} diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index fe461b4243..0d4a01360d 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,6 +15,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: 'Dependency Review' - uses: actions/dependency-review-action@v2 + uses: actions/dependency-review-action@v4 diff --git a/.github/workflows/dev-environment.yml b/.github/workflows/dev-environment.yml index 1fd2f9c080..93e6162f1c 100644 --- a/.github/workflows/dev-environment.yml +++ b/.github/workflows/dev-environment.yml @@ -68,7 +68,7 @@ jobs: steps: - name: Step 01 - Download the plugin's source code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: wazuh/wazuh-dashboard-plugins ref: ${{ inputs.reference }} @@ -108,18 +108,20 @@ jobs: cd /home/node/kbn/plugins/${{ matrix.plugins.container_path }} && yarn && ${{ inputs.command }}; ' - - name: Get the plugin version + - name: Get the plugin version and format reference name run: | + echo "githubReference=$(echo ${{ inputs.reference }} | sed 's/\//-/g')" >> $GITHUB_ENV echo "version=$(jq -r '.version' $(pwd)/wazuh/plugins/main/package.json)" >> $GITHUB_ENV echo "revision=$(jq -r '.revision' $(pwd)/wazuh/plugins/main/package.json)" >> $GITHUB_ENV - name: Step 04 - Upload artifact to GitHub if: ${{ inputs.artifact_name && inputs.artifact_path }} - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: ${{ inputs.artifact_name }}_${{ env.version }}-${{ env.revision }}_${{ inputs.reference }}.zip + name: ${{ inputs.artifact_name }}_${{ matrix.plugins.container_path }}_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip path: ${{ matrix.plugins.path }}/${{ inputs.artifact_path }} if-no-files-found: 'error' + overwrite: true - name: Step 05 - Upload coverage results to GitHub if: ${{ inputs.notify_jest_coverage_summary && github.event_name == 'pull_request' }} diff --git a/.github/workflows/eslint.yml b/.github/workflows/eslint.yml index 38954d9028..c162ff14a7 100644 --- a/.github/workflows/eslint.yml +++ b/.github/workflows/eslint.yml @@ -11,6 +11,10 @@ name: ESLint on: pull_request: + branches-ignore: + - 2.* + - 3.* + - 4.* jobs: linter: @@ -19,11 +23,11 @@ jobs: steps: # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 # - https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#node-version-file - name: Install NodeJS - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' @@ -39,12 +43,11 @@ jobs: echo "Listing branches" git branch -a echo "Getting diff files ignoring deleted and getting the changed or renamed files" - CHANGED_FILES=$(git diff --name-status --diff-filter d ${REMOTE_NAME}/${GITHUB_BASE_REF}..${REMOTE_NAME}/${GITHUB_HEAD_REF} | awk '{print $2}') + CHANGED_FILES=$(git diff --name-status --diff-filter d ${REMOTE_NAME}/${GITHUB_BASE_REF}..${REMOTE_NAME}/${GITHUB_HEAD_REF} | awk '{print $NF}' | grep -E '.*\.[jt]sx?$') echo "Changed files:" echo "${CHANGED_FILES}" git checkout $GITHUB_HEAD_REF - plugin_package_json=$(ls -d plugins/* | head -n1) - echo "Installing dependencies from plugin: ${plugin_package_json}" - yarn --cwd "${plugin_package_json}" --modules-folder ../../node_modules + echo "Installing dependencies" + yarn echo "Running eslint on the changed files" npx eslint ${CHANGED_FILES} diff --git a/.github/workflows/manual-build.yml b/.github/workflows/manual-build.yml index 4452e637dd..e8c03183da 100644 --- a/.github/workflows/manual-build.yml +++ b/.github/workflows/manual-build.yml @@ -39,27 +39,43 @@ jobs: steps: - name: Step 01 - Download the plugin's source code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: repository: wazuh/wazuh-dashboard-plugins ref: ${{ inputs.reference }} path: wazuh - - name: Step 02 - Get version and revision + - name: Step 02 - Set variables run: | + echo "githubReference=$(echo ${{ inputs.reference }} | sed 's/\//-/g')" >> $GITHUB_ENV echo "currentDir=$(pwd -P)" >> $GITHUB_ENV echo "version=$(jq -r '.version' $(pwd)/wazuh/plugins/main/package.json)" >> $GITHUB_ENV echo "revision=$(jq -r '.revision' $(pwd)/wazuh/plugins/main/package.json)" >> $GITHUB_ENV echo "versionPlatform=$(jq -r '.pluginPlatform.version' $(pwd)/wazuh/plugins/main/package.json)" >> $GITHUB_ENV - - name: Step 03 - Download the plugin's source code - uses: actions/download-artifact@v3 + - name: Step 03 - Download the main plugin's artifact + uses: actions/download-artifact@v4 with: - name: wazuh-dashboard-plugins_${{ env.version }}-${{ env.revision }}_${{ inputs.reference }}.zip - path: ${{ env.currentDir }}/wazuh/scripts/test-packages/wazuh-dashboard-plugins_${{ env.version }}-${{ env.revision }}_${{ inputs.reference }}.zip + name: wazuh-dashboard-plugins_wazuh_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + path: ${{ env.currentDir }}/wazuh/scripts/test-packages/plugins/wazuh-dashboard-plugins_wazuh_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + overwrite: true - - name: Step 04 - Build the Docker image + - name: Step 04 - Download the core plugin's artifact + uses: actions/download-artifact@v4 + with: + name: wazuh-dashboard-plugins_wazuh-core_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + path: ${{ env.currentDir }}/wazuh/scripts/test-packages/plugins/wazuh-dashboard-plugins_wazuh-core_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + overwrite: true + + - name: Step 05 - Download the check-updates plugin's artifact + uses: actions/download-artifact@v4 + with: + name: wazuh-dashboard-plugins_wazuh-check-updates_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + path: ${{ env.currentDir }}/wazuh/scripts/test-packages/plugins/wazuh-dashboard-plugins_wazuh-check-updates_${{ env.version }}-${{ env.revision }}_${{ env.githubReference }}.zip + overwrite: true + + - name: Step 06 - Build the Docker image run: | echo "current=${{ env.currentDir }}" cd ./wazuh/scripts/test-packages - docker build --build-arg OSD_VERSION=${{ env.versionPlatform }} --build-arg PACKAGE_NAME=wazuh-dashboard-plugins_${{ env.version }}-${{ env.revision }}_${{ inputs.reference }}.zip -f osd-test-packages.Dockerfile ./ + docker build --build-arg OSD_VERSION=${{ env.versionPlatform }} -f osd-test-packages.Dockerfile ./ diff --git a/.github/workflows/prettier.yml b/.github/workflows/prettier.yml index 23de4aa1e6..4e62af22ed 100644 --- a/.github/workflows/prettier.yml +++ b/.github/workflows/prettier.yml @@ -10,11 +10,11 @@ jobs: steps: # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 # - https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#node-version-file - name: Install NodeJS - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' diff --git a/.github/workflows/wazuh-build-push-docker-action.yml b/.github/workflows/wazuh-build-push-docker-action.yml index 74be8e29e1..e6cbcd66e2 100644 --- a/.github/workflows/wazuh-build-push-docker-action.yml +++ b/.github/workflows/wazuh-build-push-docker-action.yml @@ -56,7 +56,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Step 01 - Download wazuh-kibana-app - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: wazuh-kibana-app - name: Step 02 - Login to quay.io @@ -80,7 +80,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Step 01 - Download wazuh-kibana-app - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: wazuh-kibana-app - name: Step 02 - Login to quay.io @@ -101,7 +101,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Step 01 - Download wazuh-kibana-app - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: wazuh-kibana-app - name: Step 02 - Login to quay.io diff --git a/CHANGELOG.md b/CHANGELOG.md index 51dfa62e0e..7ad0073c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,12 @@ All notable changes to the Wazuh app project will be documented in this file. - Support for Wazuh 4.10.1 -## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 03 +### Changed + +- Refined the layout of the agent details view [#7193](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7193) +- Changed the width of the command column, relocate argvs column and change the width of the rest of the columns in the table processes. [#7195](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7195) + +## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 06 ### Added @@ -35,6 +40,8 @@ All notable changes to the Wazuh app project will be documented in this file. - Added ability to filter from File Integrity Monitoring registry inventory [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119) - Added new field columns and ability to select the visible fields in the File Integrity Monitoring Files and Registry tables [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119) - Added filter by value to document details fields [#7081](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7081) +- Added pinned agent mechanic to inventory data, stats, and configuration for consistent functionality [#7135](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7135) +- Added ability to edit the `wazuh.updates.disabled` configuration setting from UI [#7156](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7156) ### Changed @@ -49,6 +56,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Changed feature container margins to ensure consistent separation and uniform design. [#7034](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7034) - Changed the initial width to the default columns on each selected field [#7059](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7059) - Changed inventory, stats and configuration page to use tabs [#7089](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7089) +- Changed styles in the register agent view for consistency of styles in the views. [#7149](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7149) ### Fixed @@ -63,7 +71,13 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed filter management to prevent hiding when adding multiple filters [#7077](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7077) - Fixed the Mitre ATT&CK exception in the agent view, the redirections of ID, Tactics, Dashboard Icon and Event Icon in the drop-down menu and the card not displaying information when the flyout was opened [#7116](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7116) - Fixed the filter are displayed cropped on screens of 575px to 767px in vulnerability detection module [#7047](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7047) -- Fixed ability to filter from files inventory details flyout of File Integrity Monitoring [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119) +- Fixed ability to filter from files inventory details flyout of File Integrity Monitoring [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119) [#7163](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7163) +- Fixed endpoint group module name and indexer management order [#7150](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7150) +- Fixed Invalid date filter applied on FIM details flyout [#7160](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7160) +- Fixed the check updates UI was displayed despite it could be configured as disabled [#7156](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7156) +- Fixed filter by value in document details in safari [#7151](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7151) +- Fixed error message to prevent pass no strings to the wazuh logger [#7167](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7167) +- Fixed the rendering of the `data.vunerability.reference` in the table and flyout [#7177](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7177) ### Removed diff --git a/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap b/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap index 281620631e..6e7375e505 100644 --- a/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap +++ b/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap @@ -44,7 +44,7 @@ exports[`AgentStatus component Renders status indicator with the its color and t active (this.indexPattern = idxPtn)); } - details() { - return [ - { - field: 'date', - name: 'Last analysis', - grow: 2, - icon: 'clock', - link: true, - transformValue: formatUIDate, - }, - { - field: 'mtime', - name: 'Last modified', - grow: 2, - icon: 'clock', - link: true, - transformValue: formatUIDate, - }, - { - field: 'uname', - name: 'User', - icon: 'user', - link: true, - }, - { - field: 'uid', - name: 'User ID', - icon: 'user', - link: true, - }, - { - field: 'gname', - name: 'Group', - icon: 'usersRolesApp', - onlyLinux: true, - link: true, - }, - { - field: 'gid', - name: 'Group ID', - onlyLinux: true, - icon: 'usersRolesApp', - link: true, - }, - { - field: 'size', - name: 'Size', - icon: 'nested', - link: true, - transformValue: value => this.renderFileDetailsSize(value), - }, - { - field: 'inode', - name: 'Inode', - icon: 'link', - onlyLinux: true, - link: true, - }, - { - field: 'md5', - name: 'MD5', - checksum: true, - icon: 'check', - link: true, - }, - { - field: 'sha1', - name: 'SHA1', - checksum: true, - icon: 'check', - link: true, - }, - { - field: 'sha256', - name: 'SHA256', - checksum: true, - icon: 'check', - link: true, - }, - { - field: 'perm', - name: 'Permissions', - icon: 'lock', - link: false, - transformValue: value => this.renderFileDetailsPermissions(value), - }, - ]; - } - registryDetails() { return [ { @@ -309,15 +219,20 @@ export class FileDetails extends Component { this.props.closeFlyout(); } + getFilterValue(fieldType, value, rawValue) { + return fieldType === 'date' || fieldType === 'mtime' ? rawValue : value; + } + getDetails() { const { view } = this.props; const columns = this.props.type === 'registry_key' || this.props.currentFile.type === 'registry_key' ? this.registryDetails() - : this.details(); + : getProperties(this.props.agent?.os?.platform, 'details'); const generalDetails = columns.map((item, idx) => { let value = this.props.currentFile[item.field] || '-'; + let rawValue = value; if (item.transformValue) { value = item.transformValue(value, this.props); } @@ -357,7 +272,10 @@ export class FileDetails extends Component { > { - this.addFilter(item.field, value); + this.addFilter( + item.field, + this.getFilterValue(item.field, value, rawValue), + ); }} iconType='magnifyWithPlus' aria-label='Next' @@ -403,61 +321,6 @@ export class FileDetails extends Component { ); } - renderFileDetailsPermissions(value) { - if ( - ((this.props.agent || {}).os || {}).platform === 'windows' && - value && - value !== '-' - ) { - return ( - -

- Permissions - - - - - -

- - } - > - - {JSON.stringify(value, null, 2)} - -
- ); - } - return value; - } - - renderFileDetailsSize(value) { - if (isNaN(value)) { - return 0; - } - const b = 2; - if (0 === value) { - return '0 Bytes'; - } - const c = 0 > b ? 0 : b, - d = Math.floor(Math.log(value) / Math.log(1024)); - return ( - parseFloat((value / Math.pow(1024, d)).toFixed(c)) + - ' ' + - ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][d] - ); - } - getDiscoverColumns() { const agentId = this.props.agent?.id; return agentId diff --git a/plugins/main/public/components/agents/fim/inventory/fim-data.tsx b/plugins/main/public/components/agents/fim/inventory/fim-data.tsx new file mode 100644 index 0000000000..b423407258 --- /dev/null +++ b/plugins/main/public/components/agents/fim/inventory/fim-data.tsx @@ -0,0 +1,400 @@ +import React from 'react'; +import { formatUIDate } from '../../../../react-services/time-service'; +import { + EuiIconTip, + EuiAccordion, + EuiTitle, + EuiToolTip, + EuiIcon, + EuiCodeBlock, +} from '@elastic/eui'; + +function renderFileDetailsPermissions(value) { + // Permisions in string form will get rendered in a EuiAccordion + if (typeof value === 'object') { + return ( + +

+ Permissions + + + + + +

+ + } + > + + {JSON.stringify(value, null, 2)} + +
+ ); + } + return value; +} + +function renderFileDetailsSize(value) { + if (isNaN(value)) { + return 0; + } + const b = 2; + if (0 === value) { + return '0 Bytes'; + } + const c = 0 > b ? 0 : b, + d = Math.floor(Math.log(value) / Math.log(1024)); + return ( + parseFloat((value / Math.pow(1024, d)).toFixed(c)) + + ' ' + + ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'][d] + ); +} + +// dataFIM defines a configuration list for fields used in a File Integrity Monitoring (FIM) system. +// Include: +// - field: The identifier for the data field. +// - columns: Defines how the field appears into file table +// - details: Describes how the field is shown in detailed view +// - suggestions: Defines the helps to searchbar +// - registry: Defines how the field appears into windows registry table + +const dataFIM = [ + { + field: 'file', + columns: { + name: 'File', + sortable: true, + width: '250px', + searchable: true, + show: true, + }, + details: null, + suggestion: { description: 'filter by file' }, + registry: { + width: '250px', + name: 'Registry', + sortable: true, + searchable: true, + show: true, + }, + }, + { + field: 'date', + columns: { + name: ( + + Last analysis{' '} + + + ), + sortable: true, + width: '130px', + render: formatUIDate, + searchable: false, + }, + details: { + name: 'Last analysis', + grow: 2, + icon: 'clock', + link: true, + transformValue: formatUIDate, + }, + suggestion: { description: 'filter by analysis time' }, + registry: { + name: ( + + Last analysis{' '} + + + ), + sortable: true, + width: '100px', + render: formatUIDate, + searchable: false, + }, + }, + { + field: 'mtime', + columns: { + name: ( + + Last modified{' '} + + + ), + sortable: true, + width: '130px', + render: formatUIDate, + searchable: false, + show: true, + }, + details: { + name: 'Last modified', + grow: 2, + icon: 'clock', + link: true, + transformValue: formatUIDate, + }, + suggestion: { + description: 'filter by modification time', + }, + registry: { + name: ( + + Last modified{' '} + + + ), + sortable: true, + width: '250px', + className: 'wz-white-space-nowrap', + render: formatUIDate, + searchable: false, + show: true, + }, + }, + { + field: 'uname', + columns: { + name: 'User', + sortable: true, + truncateText: true, + width: '60px', + searchable: true, + show: true, + }, + details: { name: 'User', icon: 'user', link: true }, + suggestion: { description: 'filter by user name' }, + }, + { + field: 'uid', + columns: { + name: 'User ID', + sortable: true, + truncateText: true, + width: '60px', + searchable: true, + show: true, + }, + details: { name: 'User ID', icon: 'user', link: true }, + suggestion: { description: 'filter by user name' }, + }, + { + field: 'gname', + columns: { + name: 'Group', + sortable: true, + truncateText: true, + width: '60px', + searchable: true, + show: true, + }, + details: { + name: 'Group', + icon: 'usersRolesApp', + link: true, + }, + onlyLinux: true, + suggestion: { description: 'filter by group name' }, + }, + { + field: 'gid', + columns: { + name: 'Group ID', + sortable: true, + truncateText: true, + width: '60px', + searchable: true, + show: true, + }, + details: { + name: 'Group ID', + icon: 'usersRolesApp', + link: true, + }, + onlyLinux: true, + suggestion: { description: 'filter by group id' }, + }, + { + field: 'size', + columns: { + name: 'Size', + sortable: true, + width: '60px', + searchable: true, + show: true, + }, + details: { + name: 'Size', + icon: 'nested', + link: true, + transformValue: value => renderFileDetailsSize(value), + }, + suggestion: { description: 'filter by size' }, + }, + { + field: 'inode', + columns: { + name: 'Inode', + width: '60px', + searchable: true, + sortable: true, + }, + details: { + name: 'Inode', + icon: 'link', + link: true, + }, + onlyLinux: true, + suggestion: { description: 'filter by Inode checksum' }, + }, + { + field: 'md5', + columns: { + name: 'MD5', + searchable: true, + sortable: true, + }, + details: { + name: 'MD5', + checksum: true, + icon: 'check', + link: true, + }, + suggestion: { description: 'filter by MD5 checksum' }, + }, + { + field: 'sha1', + columns: { + name: 'SHA1', + searchable: true, + sortable: true, + }, + details: { + name: 'SHA1', + checksum: true, + icon: 'check', + link: true, + }, + suggestion: { description: 'filter by SHA1 checksum' }, + }, + { + field: 'sha256', + columns: { + name: 'SHA256', + searchable: true, + sortable: true, + }, + details: { + name: 'SHA256', + checksum: true, + icon: 'check', + link: true, + }, + suggestion: { description: 'filter by SHA256 checksum' }, + }, + { + field: 'perm', + columns: null, + details: { + name: 'Permissions', + icon: 'lock', + link: false, + transformValue: value => renderFileDetailsPermissions(value), + }, + suggestion: null, + }, +]; + +// Checks that OS is not windows +function filterByOS(items, agentInfo: string) { + return items.filter(item => item.onlyLinux !== (agentInfo === 'windows')); +} + +function getPropertiesColumnsType(items) { + // Avoid columns that are not rendered from getting into view + return items + .filter(({ columns }) => columns) + .map(({ field, columns }) => ({ + field, + ...columns, + })); +} + +function getPropertiesRegistryType(items) { + return items + .filter(item => item.registry) + .map(({ field, registry }) => ({ field, ...registry })); +} + +function getPropertiesSuggestionsType(items) { + return items + .filter(({ suggestion }) => suggestion) + .map(({ field, suggestion }) => ({ + label: field, + ...suggestion, + })) + .sort((a, b) => a.label.localeCompare(b.label)); +} + +function getPropertiesDetailsType(items) { + // Avoid details that are not rendered from getting into view + return items + .filter(({ details }) => details) + .map(({ field, name, details }) => ({ + field, + name, + ...details, + })); +} + +const mappersType = { + columns: getPropertiesColumnsType, + suggestions: getPropertiesSuggestionsType, + details: getPropertiesDetailsType, + registry: getPropertiesRegistryType, +}; + +export function getProperties( + agentInfo: string, + type: 'columns' | 'suggestions' | 'details' | 'registry', +) { + // Filter + const filteredFields = filterByOS(dataFIM, agentInfo); + + // Get mapper by type + const mapperByType = mappersType[type]; + + return mapperByType(filteredFields); +} diff --git a/plugins/main/public/components/agents/fim/inventory/registry-table.tsx b/plugins/main/public/components/agents/fim/inventory/registry-table.tsx index 6dfb410c46..45777d4ea2 100644 --- a/plugins/main/public/components/agents/fim/inventory/registry-table.tsx +++ b/plugins/main/public/components/agents/fim/inventory/registry-table.tsx @@ -14,12 +14,12 @@ import React, { Component } from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; import { WzRequest } from '../../../../react-services/wz-request'; import { FlyoutDetail } from './flyout'; -import { formatUIDate } from '../../../../react-services/time-service'; import { TableWzAPI } from '../../../common/tables'; import { SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT } from '../../../../../common/constants'; import { withRouterSearch } from '../../../common/hocs'; import { Route, Switch } from '../../../router-search'; import NavigationService from '../../../../react-services/navigation-service'; +import { getProperties } from './fim-data'; export const RegistryTable = withRouterSearch( class RegistryTable extends Component { @@ -58,56 +58,6 @@ export const RegistryTable = withRouterSearch( }); }; - columns() { - return [ - { - field: 'file', - name: 'Registry', - sortable: true, - searchable: true, - show: true, - }, - { - field: 'mtime', - name: ( - - Last modified{' '} - - - ), - sortable: true, - width: '250px', - className: 'wz-white-space-nowrap', - render: formatUIDate, - searchable: false, - show: true, - }, - { - field: 'date', - name: ( - - Last analysis{' '} - - - ), - sortable: true, - width: '100px', - render: formatUIDate, - searchable: false, - }, - ]; - } - onFiltersChange = filters => { this.setState({ filters, @@ -127,8 +77,7 @@ export const RegistryTable = withRouterSearch( }; }; - const columns = this.columns(); - + const columns = getProperties(this.props.agent?.os?.platform, 'registry'); const APIendpoint = `/syscheck/${this.props.agent.id}?type=registry_key`; return ( diff --git a/plugins/main/public/components/agents/fim/inventory/table.tsx b/plugins/main/public/components/agents/fim/inventory/table.tsx index 80157ce30c..dbca1b8edf 100644 --- a/plugins/main/public/components/agents/fim/inventory/table.tsx +++ b/plugins/main/public/components/agents/fim/inventory/table.tsx @@ -11,15 +11,15 @@ */ import React, { Component } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiIconTip } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { WzRequest } from '../../../../react-services/wz-request'; import { FlyoutDetail } from './flyout'; -import { formatUIDate } from '../../../../react-services/time-service'; import { TableWzAPI } from '../../../common/tables'; import { SEARCH_BAR_WQL_VALUE_SUGGESTIONS_COUNT } from '../../../../../common/constants'; import { withRouterSearch } from '../../../common/hocs'; import { Route, Switch } from '../../../router-search'; import NavigationService from '../../../../react-services/navigation-service'; +import { getProperties } from './fim-data'; export const InventoryTable = withRouterSearch( class InventoryTable extends Component { @@ -58,122 +58,6 @@ export const InventoryTable = withRouterSearch( }); }; - columns() { - let width; - (((this.props.agent || {}).os || {}).platform || false) === 'windows' - ? (width = '60px') - : (width = '80px'); - return [ - { - field: 'file', - name: 'File', - sortable: true, - width: '250px', - searchable: true, - show: true, - }, - { - field: 'mtime', - name: ( - - Last modified{' '} - - - ), - sortable: true, - width: '100px', - render: formatUIDate, - searchable: false, - show: true, - }, - { - field: 'uname', - name: 'User', - sortable: true, - truncateText: true, - width: `${width}`, - searchable: true, - show: true, - }, - { - field: 'uid', - name: 'User ID', - sortable: true, - truncateText: true, - width: `${width}`, - searchable: true, - show: true, - }, - { - field: 'gname', - name: 'Group', - sortable: true, - truncateText: true, - width: `${width}`, - searchable: true, - show: true, - }, - { - field: 'gid', - name: 'Group ID', - sortable: true, - truncateText: true, - width: `${width}`, - searchable: true, - show: true, - }, - { - field: 'size', - name: 'Size', - sortable: true, - width: `${width}`, - searchable: true, - show: true, - }, - { - field: 'date', - name: ( - - Last analysis{' '} - - - ), - sortable: true, - width: '100px', - render: formatUIDate, - searchable: false, - }, - { - field: 'md5', - name: 'MD5', - searchable: true, - sortable: true, - }, - { - field: 'sha1', - name: 'SHA1', - searchable: true, - sortable: true, - }, - { - field: 'sha256', - name: 'SHA256', - searchable: true, - sortable: true, - }, - ]; - } - onFiltersChange = filters => { this.setState({ filters, @@ -192,7 +76,7 @@ export const InventoryTable = withRouterSearch( }, }; }; - const columns = this.columns(); + const columns = getProperties(this.props.agent?.os?.platform, 'columns'); const APIendpoint = `/syscheck/${this.props.agent.id}?type=file`; @@ -206,25 +90,11 @@ export const InventoryTable = withRouterSearch( endpoint={APIendpoint} searchBarWQL={{ suggestions: { - field: currentValue => [ - { label: 'date', description: 'filter by analysis time' }, - { label: 'file', description: 'filter by file' }, - { label: 'gid', description: 'filter by group id' }, - { label: 'gname', description: 'filter by group name' }, - { label: 'md5', description: 'filter by MD5 checksum' }, - { - label: 'mtime', - description: 'filter by modification time', - }, - { label: 'sha1', description: 'filter by SHA1 checksum' }, - { - label: 'sha256', - description: 'filter by SHA256 checksum', - }, - { label: 'size', description: 'filter by size' }, - { label: 'uname', description: 'filter by user name' }, - { label: 'uid', description: 'filter by user id' }, - ], + field: currentValue => + getProperties( + this.props.agent?.os?.platform, + 'suggestions', + ), value: async (currentValue, { field }) => { try { const response = await WzRequest.apiReq( diff --git a/plugins/main/public/components/agents/stats/agent-stats.test.tsx b/plugins/main/public/components/agents/stats/agent-stats.test.tsx index 84f8e2a648..c0b7ef3399 100644 --- a/plugins/main/public/components/agents/stats/agent-stats.test.tsx +++ b/plugins/main/public/components/agents/stats/agent-stats.test.tsx @@ -1,8 +1,16 @@ import React from 'react'; -import { render, act } from '@testing-library/react'; +import { render, act, RenderResult } from '@testing-library/react'; import { AgentStats } from './agent-stats'; import { queryDataTestAttr } from '../../../../test/public/query-attr'; import { CSS } from '../../../../test/utils/CSS'; +import { WzRequest } from '../../../react-services'; +import { AgentStatTable } from './table'; + +const agent000 = '000'; +const agent001 = '001'; + +const apiReqMock = WzRequest.apiReq as jest.Mock; +const AgentStatTableMock = AgentStatTable as jest.Mock; jest.mock('../../../react-services', () => ({ WzRequest: { @@ -10,6 +18,43 @@ jest.mock('../../../react-services', () => ({ }, })); +jest.mock('redux', () => ({ + compose: () => (Component: React.JSX.Element) => Component, + __esModule: true, +})); + +jest.mock('../../common/hocs', () => ({ + withGlobalBreadcrumb: () => () => <>, + withGuard: () => () => <>, + withUserAuthorizationPrompt: () => () => <>, + withErrorBoundary: () => () => <>, + __esModule: true, +})); + +jest.mock('../prompts', () => ({ + PromptNoActiveAgentWithoutSelect: () => <>, + PromptAgentFeatureVersion: () => <>, + __esModule: true, +})); + +jest.mock('../../../utils/applications', () => ({ + endpointsSummary: { + id: 'endpoints-summary', + breadcrumbLabel: 'Endpoints', + }, +})); + +jest.mock('../../../react-services/navigation-service', () => ({ + getInstance: () => ({ + getUrlForApp: jest.fn().mockReturnValue('http://url'), + __esModule: true, + }), +})); + +jest.mock('./table', () => ({ + AgentStatTable: jest.fn(() => <>), +})); + describe('AgentStats', () => { it('should not render agent info ribbon', async () => { await act(async () => { @@ -65,4 +110,152 @@ describe('AgentStats', () => { ).toHaveLength(7); }); }); + + it('should call api with correct agent ids and endpoints when changing agent', async () => { + apiReqMock.mockClear(); + + let rerender: RenderResult['rerender']; + + await act(async () => { + ({ rerender } = render()); + }); + + expect(apiReqMock).toHaveBeenCalledTimes(2); + expect(apiReqMock.mock.calls[0]).toEqual([ + 'GET', + `/agents/${agent000}/stats/logcollector`, + {}, + ]); + expect(apiReqMock.mock.calls[1]).toEqual([ + 'GET', + `/agents/${agent000}/stats/agent`, + {}, + ]); + + apiReqMock.mockClear(); + + await act(async () => { + rerender(); + }); + + expect(apiReqMock).toHaveBeenCalledTimes(2); + expect(apiReqMock.mock.calls[0]).toEqual([ + 'GET', + `/agents/${agent001}/stats/logcollector`, + {}, + ]); + expect(apiReqMock.mock.calls[1]).toEqual([ + 'GET', + `/agents/${agent001}/stats/agent`, + {}, + ]); + }); + + it('should maintain column structure across multiple renders, either when changing agent or not', async () => { + AgentStatTableMock.mockClear(); + + const mockColumns = [ + { + field: 'location', + name: 'Location', + sortable: true, + }, + { + field: 'events', + name: 'Events', + sortable: true, + }, + { + field: 'bytes', + name: 'Bytes', + sortable: true, + }, + ]; + + let rerender: RenderResult['rerender']; + + await act(async () => { + ({ rerender } = render()); + }); + + expect(AgentStatTableMock.mock.calls[0][0].columns).toEqual(mockColumns); + expect(AgentStatTableMock.mock.calls[1][0].columns).toEqual(mockColumns); + + AgentStatTableMock.mockClear(); + + await act(async () => { + rerender(); + }); + + expect(AgentStatTableMock.mock.calls[0][0].columns).toEqual(mockColumns); + expect(AgentStatTableMock.mock.calls[1][0].columns).toEqual(mockColumns); + }); + + it('should apply correct titles after render and rerender, either when changing agent or not', async () => { + AgentStatTableMock.mockClear(); + + const mockDataStatLogcollectorTitle = 'Global'; + const mockDataStatAgentTitle = 'Interval'; + + let rerender: RenderResult['rerender']; + + await act(async () => { + ({ rerender } = render()); + }); + + expect(AgentStatTableMock.mock.calls[0][0].title).toEqual( + mockDataStatLogcollectorTitle, + ); + expect(AgentStatTableMock.mock.calls[1][0].title).toEqual( + mockDataStatAgentTitle, + ); + + AgentStatTableMock.mockClear(); + + await act(async () => { + rerender(); + }); + + expect(AgentStatTableMock.mock.calls[0][0].title).toEqual( + mockDataStatLogcollectorTitle, + ); + expect(AgentStatTableMock.mock.calls[1][0].title).toEqual( + mockDataStatAgentTitle, + ); + }); + + it('should update export csv filename correctly when changing agent', async () => { + AgentStatTableMock.mockClear(); + + const mockExportCSVFilename = ( + agent000: string, + suffix: 'global' | 'interval', + ) => `agent-stats-${agent000}-logcollector-${suffix}`; + + let rerender: RenderResult['rerender']; + + await act(async () => { + ({ rerender } = render()); + }); + + expect(AgentStatTableMock.mock.calls[0][0].exportCSVFilename).toEqual( + mockExportCSVFilename(agent000, 'global'), + ); + expect(AgentStatTableMock.mock.calls[1][0].exportCSVFilename).toEqual( + mockExportCSVFilename(agent000, 'interval'), + ); + + AgentStatTableMock.mockClear(); + + await act(async () => { + rerender(); + }); + + expect(AgentStatTableMock.mock.calls[0][0].exportCSVFilename).toEqual( + mockExportCSVFilename(agent001, 'global'), + ); + expect(AgentStatTableMock.mock.calls[1][0].exportCSVFilename).toEqual( + mockExportCSVFilename(agent001, 'interval'), + ); + }); }); diff --git a/plugins/main/public/components/agents/stats/agent-stats.tsx b/plugins/main/public/components/agents/stats/agent-stats.tsx index 98f966281c..86269a7fae 100644 --- a/plugins/main/public/components/agents/stats/agent-stats.tsx +++ b/plugins/main/public/components/agents/stats/agent-stats.tsx @@ -13,14 +13,10 @@ import React, { useState, useEffect } from 'react'; import { EuiFlexGroup, EuiFlexItem, - EuiLoadingSpinner, - EuiPanel, EuiPage, EuiPageBody, EuiSpacer, - EuiText, } from '@elastic/eui'; - import { withGlobalBreadcrumb, withGuard, @@ -48,6 +44,8 @@ import { getErrorOrchestrator } from '../../../react-services/common-services'; import { endpointSummary } from '../../../utils/applications'; import NavigationService from '../../../react-services/navigation-service'; import WzRibbon from '../../common/ribbon/ribbon'; +import { Agent } from '../../endpoints-summary/types'; +import { SECTIONS } from '../../../sections'; const tableColumns = [ { @@ -67,40 +65,43 @@ const tableColumns = [ }, ]; -const statsAgents: { title: string; field: string; render?: (value) => any }[] = - [ - { - title: 'Status', - field: 'status', - }, - { - title: 'Buffer', - field: 'buffer_enabled', - render: value => (value ? 'enabled' : 'disabled'), - }, - { - title: 'Message buffer', - field: 'msg_buffer', - }, - { - title: 'Messages count', - field: 'msg_count', - }, - { - title: 'Messages sent', - field: 'msg_sent', - }, - { - title: 'Last ack', - field: 'last_ack', - render: formatUIDate, - }, - { - title: 'Last keep alive', - field: 'last_keepalive', - render: formatUIDate, - }, - ]; +const statsAgents: { + title: string; + field: string; + render?: (value: any) => any; +}[] = [ + { + title: 'Status', + field: 'status', + }, + { + title: 'Buffer', + field: 'buffer_enabled', + render: value => (value ? 'enabled' : 'disabled'), + }, + { + title: 'Message buffer', + field: 'msg_buffer', + }, + { + title: 'Messages count', + field: 'msg_count', + }, + { + title: 'Messages sent', + field: 'msg_sent', + }, + { + title: 'Last ack', + field: 'last_ack', + render: formatUIDate, + }, + { + title: 'Last keep alive', + field: 'last_keepalive', + render: formatUIDate, + }, +]; export const MainAgentStats = compose( withErrorBoundary, @@ -108,7 +109,7 @@ export const MainAgentStats = compose( { text: endpointSummary.breadcrumbLabel, href: NavigationService.getInstance().getUrlForApp(endpointSummary.id, { - path: `#/agents-preview`, + path: `#/${SECTIONS.AGENTS_PREVIEW}`, }), }, { agent }, @@ -143,9 +144,13 @@ export const MainAgentStats = compose( ), )(AgentStats); -export function AgentStats(props) { +interface AgentStatsProps { + agent: Agent; +} + +export function AgentStats(props: AgentStatsProps) { const { agent } = props; - const [loading, setLoading] = useState(); + const [loading, setLoading] = useState(false); const [dataStatLogcollector, setDataStatLogcollector] = useState({}); const [dataStatAgent, setDataStatAgent] = useState(); useEffect(() => { @@ -175,8 +180,8 @@ export function AgentStats(props) { severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity, error: { error: error, - message: error.message || error, - title: error.name || error, + message: (error as Error).message || (error as string), + title: (error as Error).name || (error as string), }, }; getErrorOrchestrator().handleError(options); @@ -184,7 +189,7 @@ export function AgentStats(props) { setLoading(false); } })(); - }, []); + }, [agent.id]); return ( diff --git a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap index 21933a7df0..13c4b57394 100644 --- a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap +++ b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap @@ -17,9 +17,12 @@ exports[`Inventory data Network Network interfaces table A Apple agent should re style="responsive:" >
+
+
+
+
+
+
+
+
+
+
@@ -14628,10 +14670,10 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_argvs_6" + data-test-subj="tableHeaderCell_size_6" role="columnheader" scope="col" - style="width:15%" + style="width:7%" > @@ -14653,9 +14695,10 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_vm_size_7" + data-test-subj="tableHeaderCell_session_7" role="columnheader" scope="col" + style="width:7%" > @@ -14677,9 +14720,10 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_size_8" + data-test-subj="tableHeaderCell_nice_8" role="columnheader" scope="col" + style="width:7%" > @@ -14701,9 +14745,10 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_session_9" + data-test-subj="tableHeaderCell_state_9" role="columnheader" scope="col" + style="width:7%" > @@ -14725,9 +14770,10 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_nice_10" + data-test-subj="tableHeaderCell_cmd_10" role="columnheader" scope="col" + style="width:15%" > @@ -14749,7 +14795,7 @@ exports[`Inventory data Processes A Linux agent should render processes table wi aria-live="polite" aria-sort="none" class="euiTableHeaderCell" - data-test-subj="tableHeaderCell_state_11" + data-test-subj="tableHeaderCell_argvs_11" role="columnheader" scope="col" style="width:15%" @@ -14765,7 +14811,7 @@ exports[`Inventory data Processes A Linux agent should render processes table wi - State + Argvs @@ -14821,9 +14867,12 @@ exports[`Inventory data Processes A Windows agent should render processes table style="responsive:" >
+