diff --git a/.github/actions/aws-ci/action.yml b/.github/actions/aws-ci/action.yml new file mode 100644 index 0000000000..5450ee9d3f --- /dev/null +++ b/.github/actions/aws-ci/action.yml @@ -0,0 +1,65 @@ +name: 'AWS CI' +description: 'AWS integration tests' +inputs: + elk-version: + description: 'ELK version' + required: true + aws-access-key-id: + description: 'AWS access key id' + required: true + aws-secret-access-key: + description: 'AWS secret access key' + required: true + aws-account-type: + description: 'AWS account type' + required: false + default: single-account + + debug: + description: 'debug' + required: false + default: 'false' +runs: + using: composite + steps: + - name: Init Integration + uses: ./.github/actions/init-integration + with: + elk-version: ${{ inputs.elk-version }} + + - name: Run cloudbeat in background + env: + ES_HOST: http://localhost:9200 + ES_USERNAME: elastic + ES_PASSWORD: changeme + AWS_ACCESS_KEY_ID: ${{ inputs.aws-access-key-id }} + AWS_SECRET_ACCESS_KEY: ${{ inputs.aws-secret-access-key }} + AWS_ACCOUNT_TYPE: ${{ inputs.aws-account-type }} + shell: bash + run: | + ./cloudbeat -c deploy/aws/cloudbeat-aws.yml -d '*' & + + - name: Wait for cloudbeat to send some events + shell: bash + run: sleep 20 + + - name: Check for findings + working-directory: ./tests + env: + USE_K8S: "false" + shell: bash + run: poetry run pytest -k "aws" --alluredir=./allure/results/ --clean-alluredir + + - name: Upload test results + if: ${{ success() || failure() }} + uses: actions/upload-artifact@v4 + with: + name: allure-results-ci-aws + path: tests/allure/results/ + + - if: ${{ (success() || failure()) && inputs.debug == 'true' }} + name: Upload cloudbeat logs + uses: actions/upload-artifact@v4 + with: + name: cloubeat-logs-ci-aws + path: logs/ diff --git a/.github/actions/azure-ci/action.yml b/.github/actions/azure-ci/action.yml new file mode 100644 index 0000000000..b3439b7f38 --- /dev/null +++ b/.github/actions/azure-ci/action.yml @@ -0,0 +1,66 @@ +name: 'Azure CI' +description: 'Azure integration tests' +inputs: + elk-version: + description: 'ELK version' + required: true + azure-client-id: + description: 'Azure client id' + required: true + azure-tenant-id: + description: 'Azure tenant id' + required: true + azure-client-secret: + description: 'Azure client secret' + required: true + + debug: + description: 'debug' + required: false + default: 'false' +runs: + using: composite + steps: + - name: Init Integration + uses: ./.github/actions/init-integration + with: + elk-version: ${{ inputs.elk-version }} + + - name: Run cloudbeat in background + env: + ES_HOST: http://localhost:9200 + ES_USERNAME: elastic + ES_PASSWORD: changeme + AZURE_ACCOUNT_TYPE: single-account + AZURE_CREDENTIALS_TYPE: service_principal_with_client_secret + AZURE_CLIENT_ID: ${{ inputs.azure-client-id }} + AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }} + AZURE_CLIENT_SECRET: ${{ inputs.azure-client-secret }} + shell: bash + run: | + ./cloudbeat -c deploy/azure/cloudbeat-azure.yml -d '*' & + + - name: Wait for cloudbeat to send some events + shell: bash + run: sleep 15 + + - name: Check for findings + working-directory: ./tests + env: + USE_K8S: "false" + shell: bash + run: poetry run pytest -k "azure" --alluredir=./allure/results/ --clean-alluredir + + - name: Upload test results + if: ${{ success() || failure() }} + uses: actions/upload-artifact@v4 + with: + name: allure-results-ci-azure + path: tests/allure/results/ + + - if: ${{ (success() || failure()) && inputs.debug == 'true' }} + name: Upload cloudbeat logs + uses: actions/upload-artifact@v4 + with: + name: cloubeat-logs-ci-azure + path: logs/ diff --git a/.github/actions/cnvm-ci/action.yml b/.github/actions/cnvm-ci/action.yml new file mode 100644 index 0000000000..4536cf9940 --- /dev/null +++ b/.github/actions/cnvm-ci/action.yml @@ -0,0 +1,68 @@ +name: 'CNVM CI' +description: 'CNVM integration tests' +inputs: + elk-version: + description: 'ELK version' + required: true + aws-access-key-id: + description: 'AWS access key id' + required: true + aws-secret-access-key: + description: 'AWS secret access key' + required: true + aws-region: + description: 'AWS region' + required: true + + debug: + description: 'debug' + required: false + default: 'false' +runs: + using: composite + steps: + - name: Init Integration + uses: ./.github/actions/init-integration + with: + elk-version: ${{ inputs.elk-version }} + + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ inputs.aws-access-key-id }} + aws-secret-access-key: ${{ inputs.aws-secret-access-key }} + aws-region: ${{ inputs.aws-region }} + + - name: Run cloudbeat in background + env: + ES_HOST: http://localhost:9200 + ES_USERNAME: elastic + ES_PASSWORD: changeme + shell: bash + run: ./cloudbeat -c deploy/vulnerability/cloudbeat-vuln-mgmt.yml -d '*' & + + - name: Wait for cloudbeat to send some events + shell: bash + run: sleep 10 + + - name: Check for findings + working-directory: ./tests + env: + USE_K8S: "false" + shell: bash + run: | + poetry run pytest -k "cnvm" --alluredir=./allure/results/ --clean-alluredir + + - name: Upload test results + if: ${{ success() || failure() }} + uses: actions/upload-artifact@v4 + with: + name: allure-results-ci-cnvm + path: tests/allure/results/ + + - if: ${{ (success() || failure()) && inputs.debug == 'true' }} + name: Upload cloudbeat logs + uses: actions/upload-artifact@v4 + with: + name: cloubeat-logs-ci-cnvm + path: logs/ diff --git a/.github/actions/docker-images/action.yml b/.github/actions/docker-images/action.yml new file mode 100644 index 0000000000..95c7b45a33 --- /dev/null +++ b/.github/actions/docker-images/action.yml @@ -0,0 +1,136 @@ +name: 'Docker Images' +description: 'Build docker images' +inputs: + build-docker-images: + description: "Build docker images" + required: false + default: 'true' + + container-image-suffix: + description: 'Container image suffix' + required: false + default: ${{ github.run_id }} + elastic-agent-docker-image: + description: 'Elastic-Agent docker image' + required: false + default: "704479110758.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent" + elastic-agent-docker-image-tag: + description: 'Elastic-Agent docker image tag' + required: false + default: "8.14.0-SNAPSHOT" + + docker-build-cache-folder: + description: 'Docker build cache folder' + required: false + default: '/tmp/.buildx-cache' + docker-images-folder: + description: 'Docker build cache folder' + required: false + default: '/tmp/.docker-images' + + goos: + description: 'GOOS environment variable' + required: false + default: 'linux' + goarch: + description: 'GOARCH environment variable' + required: false + default: 'amd64' + docker-build-platforms: + description: 'Docker build platforms' + required: false + default: 'linux/amd64' +runs: + using: composite + steps: + - name: Init directories + shell: bash + run: | + mkdir -p ${{ inputs.docker-build-cache-folder }}/{cloudbeat,agent,pytest} + mkdir -p ${{ inputs.docker-build-cache-folder }}-new/{cloudbeat,agent,pytest} + mkdir -p ${{ inputs.docker-images-folder }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Build cloudbeat binary + shell: bash + run: | + mage -v build + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Cache docker build cache + uses: actions/cache@v4 + with: + path: ${{ inputs.docker-build-cache-folder }} + key: ci-buildx-${{ runner.os }}-${{ runner.arch }}-${{ github.workflow }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Build cloudbeat-docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./deploy/Dockerfile + push: false + tags: cloudbeat:latest + cache-from: type=local,src=${{ inputs.docker-build-cache-folder }}/cloudbeat + cache-to: type=local,mode=max,dest=${{ inputs.docker-build-cache-folder }}-new/cloudbeat + outputs: type=docker,dest=${{ inputs.docker-images-folder }}/cloudbeat.tar + no-cache: false + platforms: ${{ inputs.docker-build-platforms }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Build elastic-agent + uses: docker/build-push-action@v5 + env: + GOOS: ${{ inputs.goos }} + GOARCH: ${{ inputs.goarch }} + with: + context: . + file: ./scripts/packaging/docker/elastic-agent/Dockerfile + push: false + pull: true + tags: ${{ inputs.elastic-agent-docker-image }}:${{ inputs.elastic-agent-docker-image-tag }} + cache-from: type=local,src=${{ inputs.docker-build-cache-folder }}/agent + cache-to: type=local,mode=max,dest=${{ inputs.docker-build-cache-folder }}-new/agent + outputs: type=docker,dest=${{ inputs.docker-images-folder }}/elastic-agent.tar + build-args: | + ELASTIC_AGENT_IMAGE=docker.elastic.co/beats/elastic-agent:${{ inputs.elastic-agent-docker-image-tag }} + no-cache: false + platforms: ${{ inputs.docker-build-platforms }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Build pytest-docker + uses: docker/build-push-action@v5 + with: + context: ./tests/. + push: false + tags: cloudbeat-test:latest + cache-from: type=local,src=${{ inputs.docker-build-cache-folder }}/pytest + cache-to: type=local,mode=max,dest=${{ inputs.docker-build-cache-folder }}-new/pytest + outputs: type=docker,dest=${{ inputs.docker-images-folder }}/pytest.tar + no-cache: false + platforms: ${{ inputs.docker-build-platforms }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Rotate cache + shell: bash + run: | + ls -lahR /tmp/ || true + [[ -d ${{ inputs.docker-build-cache-folder }}-new ]] && rm -rf ${{ inputs.docker-build-cache-folder }} && mv ${{ inputs.docker-build-cache-folder }}-new ${{ inputs.docker-build-cache-folder }} + + - if: ${{ inputs.build-docker-images == 'true' }} + name: Upload docker images + uses: actions/upload-artifact@v4 + with: + name: docker-images + path: ${{ inputs.docker-images-folder }} + + - if: ${{ inputs.build-docker-images == 'false' }} + name: Download docker images + uses: actions/download-artifact@v4 + with: + name: docker-images + path: ${{ inputs.docker-images-folder }} diff --git a/.github/actions/gcp-ci/action.yml b/.github/actions/gcp-ci/action.yml new file mode 100644 index 0000000000..8ed2430e3f --- /dev/null +++ b/.github/actions/gcp-ci/action.yml @@ -0,0 +1,70 @@ +name: 'GCP CI' +description: 'GCP integration tests' +inputs: + elk-version: + description: 'ELK version' + required: true + workload-identity-provider: + description: 'workload identity provider' + required: true + service-account: + description: 'workload identity provider' + required: true + gcp-project-id: + description: 'gcp project id' + required: true + gcp-account-type: + description: 'gcp account type' + required: true + + debug: + description: 'debug' + required: false + default: 'false' +runs: + using: composite + steps: + - name: Init Integration + uses: ./.github/actions/init-integration + with: + elk-version: ${{ inputs.elk-version }} + + - id: google-auth + name: Authenticate to Google Cloud + uses: google-github-actions/auth@v2 + with: + workload_identity_provider: ${{ inputs.workload-identity-provider }} + service_account: ${{ inputs.service-account }} + + - name: Run cloudbeat in background + env: + ES_HOST: http://localhost:9200 + ES_USERNAME: elastic + ES_PASSWORD: changeme + GCP_PROJECT_ID: ${{ inputs.gcp-project-id }} + GCP_ACCOUNT_TYPE: ${{ inputs.gcp-account-type }} + shell: bash + run: ./cloudbeat -c deploy/gcp/cloudbeat-gcp.yml -d '*' & + + - name: Check for findings + working-directory: ./tests + env: + USE_K8S: "false" + shell: bash + run: | + poetry install + poetry run pytest -k "cspm_gcp" --alluredir=./allure/results/ --clean-alluredir --maxfail=4 + + - name: Upload test results + if: ${{ success() || failure() }} + uses: actions/upload-artifact@v4 + with: + name: allure-results-ci-gcp + path: tests/allure/results/ + + - if: ${{ (success() || failure()) && inputs.debug == 'true' }} + name: Upload cloudbeat logs + uses: actions/upload-artifact@v4 + with: + name: cloubeat-logs-ci-gcp + path: logs/ diff --git a/.github/actions/hermit/action.yml b/.github/actions/hermit/action.yml new file mode 100644 index 0000000000..4cdaeb2cc5 --- /dev/null +++ b/.github/actions/hermit/action.yml @@ -0,0 +1,80 @@ +name: 'Hermit Environment' +description: 'Activate hermit environment' +inputs: + init-tools: + description: 'Init tools' + required: false + default: 'false' +runs: + using: composite + steps: + - id: hermit-hash + shell: bash + run: | + bin_hashes="$(find ./bin ! -type d | sort | xargs openssl sha256 | openssl sha256 -r | cut -d' ' -f1)" + poetry_security_polices="${{ hashFiles('./security-policies/poetry.lock', './security-policies/pyproject.toml') }}" + poetry_tests="${{ hashFiles('./tests/poetry.lock', './tests/pyproject.toml') }}" + pre_commit="${{ hashFiles('.pre-commit-config.yaml') }}" + action_hash="${{ hashFiles('.github/actions/hermit/action.yml') }}" + hash="$(echo "${bin_hashes} ${poetry_security_polices} ${poetry_tests} ${pre_commit} ${action_hash}" | sha256sum | cut -d' ' -f1)" + echo "hash=$hash" >> "$GITHUB_OUTPUT" + + - id: cache-tools + uses: actions/cache@v4 + with: + path: | + ~/.cache/hermit/pkg + ./.hermit + ~/.cache/pypoetry + ~/.cache/pre-commit + key: ci-hermit-env-${{ runner.os }}-${{ steps.hermit-hash.outputs.hash }} + restore-keys: | + ci-hermit-env-${{ runner.os }} + + - id: cache-go-deps + uses: actions/cache@v4 + with: + path: | + ~/go/pkg/ + key: ci-go-deps-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('**/go.mod', '**/go.sum') }} + restore-keys: | + ci-go-deps-${{ runner.os }}-${{ runner.arch }} + + - name: Initialize hermit + shell: bash + run: ./bin/hermit env --raw >> "$GITHUB_ENV" + + # in case of cache miss, an older instance of cache could be selected (with restore-keys). + # Clean hermit packages to avoid continuously size increment of folder ~/.cache/hermit/pkg. + - name: Clean hermit packages + if: steps.cache-tools.outputs.cache-hit != 'true' + shell: bash + run: hermit clean --transient + + - if: ${{ inputs.init-tools == 'true' }} + name: Install hermit packages + shell: bash + run: hermit install + - if: ${{ inputs.init-tools == 'true' }} + name: Install poetry + shell: bash + run: pip3 install poetry + - if: ${{ inputs.init-tools == 'true' }} + name: Install tests poetry dependencies + shell: bash + run: cd ./tests && poetry install --no-root + - if: ${{ inputs.init-tools == 'true' }} + name: Install security-policies poetry dependencies + shell: bash + run: cd ./security-policies && poetry install --no-root + - if: ${{ inputs.init-tools == 'true' }} + name: Install pre-commit repos + shell: bash + run: pre-commit || true + - if: ${{ inputs.init-tools == 'true' }} + name: Download go dependencies + shell: bash + run: go mod download + + - shell: bash + run: go env diff --git a/.github/actions/init-integration/action.yml b/.github/actions/init-integration/action.yml new file mode 100644 index 0000000000..c4c218bac4 --- /dev/null +++ b/.github/actions/init-integration/action.yml @@ -0,0 +1,22 @@ +name: 'Init Integration Test' +description: 'Init integration test' +inputs: + elk-version: + description: 'ELK version' + required: true +runs: + using: composite + steps: + - name: Build cloudbeat binary + shell: bash + run: mage -v build + + - name: Run elasticsearch + uses: elastic/elastic-github-actions/elasticsearch@master + with: + stack-version: ${{ inputs.elk-version }} + security-enabled: false + + - name: Elasticsearch disable dynamic mapping for findings + shell: bash + run: ./.ci/scripts/disable_dynamic_mapping.sh diff --git a/.github/actions/k8s-ci/action.yml b/.github/actions/k8s-ci/action.yml new file mode 100644 index 0000000000..4aaa8d0191 --- /dev/null +++ b/.github/actions/k8s-ci/action.yml @@ -0,0 +1,67 @@ +name: 'K8S CI' +description: 'K8s integration tests' +inputs: + kind-config: + description: 'KIND configuration' + required: true + + test-target: + description: 'Test target' + required: true + test-range: + description: 'Test range' + required: false + default: '' + values-file: + description: 'Helm values file' + required: true + + docker-images-folder: + description: 'Docker build cache folder' + required: false + default: '/tmp/.docker-images' +runs: + using: composite + steps: + - name: Prepare Kind Cluster for Process Tests + if: ${{ contains(inputs.kind-config, 'conf2') }} + shell: bash + run: | + # Workaround: Direct creation of a Kind cluster for config2 fails to start control-plane (kubelet fails) + # Creating and deleting a kind-mono cluster as a preparation for configuring Kind for process tests + just create-kind-cluster kind-mono + just delete-kind-cluster kind-mono + + - name: Create k8s Kind Cluster + shell: bash + run: just create-kind-cluster ${{ inputs.kind-config }} + + - name: Load images to kind + shell: bash + run: | + ls -lahR ${{ inputs.docker-images-folder }} + kind load image-archive ${{ inputs.docker-images-folder }}/cloudbeat.tar --name='${{ inputs.kind-config }}' + kind load image-archive ${{ inputs.docker-images-folder }}/pytest.tar --name='${{ inputs.kind-config }}' + kind load image-archive ${{ inputs.docker-images-folder }}/elastic-agent.tar --name='${{ inputs.kind-config }}' + + - name: Deploy tests Helm chart + id: deploy_helm + shell: bash + run: just deploy-tests-helm ${{ inputs.test-target }} ${{ inputs.values-file }} ${{ inputs.test-range }} + + - name: Deploy K8s Objects + if: ${{ contains(inputs.test-target, 'object_psp') }} + shell: bash + run: just apply-k8s-test-objects + + - name: Run Tests + id: run_tests + shell: bash + run: just run-tests ${{ inputs.test-target }} kind-${{ inputs.kind-config }} + + - name: Upload Test Results + if: ${{ success() || failure() }} + uses: actions/upload-artifact@v4 + with: + name: allure-results-ci-k8s-${{ inputs.test-target }}-${{ inputs.kind-config }} + path: tests/allure/results/ diff --git a/.github/workflows/aws-ci.yml b/.github/workflows/aws-ci.yml index 9b38997668..6d71e5b0f2 100644 --- a/.github/workflows/aws-ci.yml +++ b/.github/workflows/aws-ci.yml @@ -13,6 +13,7 @@ on: jobs: Run-CSPM-AWS-Tests: + if: ${{ false }} name: CIS AWS integration test runs-on: ubuntu-22.04 timeout-minutes: 60 diff --git a/.github/workflows/azure-ci.yml b/.github/workflows/azure-ci.yml index 9a0248d495..5e422b513b 100644 --- a/.github/workflows/azure-ci.yml +++ b/.github/workflows/azure-ci.yml @@ -13,6 +13,7 @@ on: jobs: Run-CSPM-AZURE-Tests: + if: ${{ false }} name: CIS AZURE integration test runs-on: ubuntu-22.04 timeout-minutes: 60 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..84c13a6c96 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,380 @@ +name: Tests + +on: + pull_request: + branches: + - main + - "[0-9]+.[0-9]+" + types: [opened, synchronize, reopened] + push: + branches: + - main + - "[0-9]+.[0-9]+" + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + init-hermit: + name: Init Hermit Tools + runs-on: ubuntu-22.04 + timeout-minutes: 60 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + - name: Hermit Environment + uses: ./.github/actions/hermit + with: + init-tools: 'true' + + lint: + needs: [ init-hermit ] + name: Lint + runs-on: ubuntu-22.04 + timeout-minutes: 60 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Pre-commit Hooks + env: + # Skipping golangci-lint as it's tested by golangci-lint + SKIP: golangci-lint + shell: bash + run: | + pre-commit run --all-files + + - name: golangci-lint + shell: bash + run: golangci-lint run --out-format github-actions + + - name: Mage Check + shell: bash + run: mage check + + - name: Mage checkLicenseHeaders + shell: bash + run: mage checkLicenseHeaders + + - name: Validate mocks + shell: bash + run: just validate-mocks + + - name: Terraform fmt + shell: bash + run: terraform fmt -check -recursive + + unit-test: + needs: [ init-hermit ] + name: Unit Test + runs-on: ubuntu-22.04 + timeout-minutes: 60 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Build opa bundle + shell: bash + run: mage buildOpaBundle + + - name: Unit-Test + shell: bash + run: | + go install gotest.tools/gotestsum + GOOS=linux TEST_DIRECTORY=./... gotestsum --format pkgname -- -race -coverpkg=./... -coverprofile=cover.out.tmp + cat cover.out.tmp | grep -v "mock_.*.go" > cover.out # remove mock files from coverage report + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: coverage-file + path: cover.out + + - name: Send coverage + env: + COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + shell: bash + run: | + go install github.com/mattn/goveralls@latest + goveralls -coverprofile=cover.out -service=github + + ci-azure: + needs: [ init-hermit ] + name: CIS Azure CI + runs-on: ubuntu-22.04 + timeout-minutes: 60 + permissions: + contents: "read" + id-token: "write" + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Run Azure integration tests + uses: ./.github/actions/azure-ci + with: + elk-version: ${{ env.ELK_VERSION }} + azure-client-id: ${{ fromJSON(secrets.AZURE_CREDENTIALS).clientId }} + azure-tenant-id: ${{ fromJSON(secrets.AZURE_CREDENTIALS).tenantId }} + azure-client-secret: ${{ fromJSON(secrets.AZURE_CREDENTIALS).clientSecret }} + + ci-aws: + needs: [ init-hermit ] + name: CIS AWS CI + runs-on: ubuntu-22.04 + timeout-minutes: 60 + permissions: + contents: "read" + id-token: "write" + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Run AWS integration tests + uses: ./.github/actions/aws-ci + with: + elk-version: ${{ env.ELK_VERSION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_TEST_ACC }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_TEST_ACC }} + aws-account-type: single-account + + ci-gcp: + needs: [ init-hermit ] + name: CIS GCP CI + runs-on: ubuntu-22.04 + timeout-minutes: 60 + permissions: + contents: 'read' + id-token: 'write' + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Run GCP integration tests + uses: ./.github/actions/gcp-ci + with: + elk-version: ${{ env.ELK_VERSION }} + workload-identity-provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} + service-account: ${{ secrets.GCP_SERVICE_ACCOUNT }} + gcp-project-id: 'elastic-security-test' + gcp-account-type: 'single-account' + + ci-cnvm: + needs: [ init-hermit ] + name: CNVM CI + runs-on: ubuntu-22.04 + timeout-minutes: 15 + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Run CNVM integration tests + uses: ./.github/actions/cnvm-ci + with: + elk-version: ${{ env.ELK_VERSION }} + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: 'us-east-2' + + docker-images: + needs: [ init-hermit ] + name: Build docker images + # Since we build the cloudbeat in the worker's OS and as non static, + # we need to keep the OS version same as elastic-agent docker image base. + # docker run --interactive --tty --rm --entrypoint bash docker.elastic.co/elastic-agent/elastic-agent-complete:8.14.0-SNAPSHOT -c 'cat /etc/os-release' + runs-on: ubuntu-20.04 + timeout-minutes: 40 + steps: + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + tool-cache: false + android: true + dotnet: true + haskell: true + large-packages: false + docker-images: true + swap-storage: true + + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Build docker images + uses: ./.github/actions/docker-images + with: + build-docker-images: 'true' + + ci-k8s: + needs: [ init-hermit, docker-images ] + name: ${{ matrix.test-target }}-${{ matrix.kind-config }} + runs-on: ubuntu-22.04 + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + include: + - test-target: pre_merge + kind-config: kind-multi + values-file: tests/test_environments/values/ci.yml + - test-target: pre_merge_agent + kind-config: kind-multi + values-file: tests/test_environments/values/ci-sa-agent.yml + - test-target: k8s_file_system_rules + kind-config: kind-test-files + values-file: tests/test_environments/values/ci-test-k8s-files.yml + - test-target: k8s_object_psp_rules + kind-config: kind-multi + values-file: tests/test_environments/values/ci-test-k8s-objects.yml + - test-target: k8s_process_rules + kind-config: kind-test-proc-conf1 + values-file: tests/test_environments/values/ci-test-k8s-proc-conf1.yml + - test-target: k8s_process_rules + kind-config: kind-test-proc-conf2 + values-file: tests/test_environments/values/ci-test-k8s-proc-conf2.yml + steps: + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + tool-cache: false + android: true + dotnet: true + haskell: true + large-packages: false + docker-images: true + swap-storage: true + + - name: Check out the repo + uses: actions/checkout@v4 + + - name: Hermit Environment + uses: ./.github/actions/hermit + + - name: Get docker images + uses: ./.github/actions/docker-images + with: + build-docker-images: 'false' + docker-images-folder: '/tmp/.docker-images' + + - name: Run k8s integration tests + uses: ./.github/actions/k8s-ci + with: + kind-config: ${{ matrix.kind-config }} + test-target: ${{ matrix.test-target }} + values-file: ${{ matrix.values-file }} + docker-images-folder: '/tmp/.docker-images' + + upload-allure-results: + needs: + - ci-azure + - ci-aws + - ci-gcp + - ci-cnvm + - ci-k8s + name: Upload integration tests results + runs-on: ubuntu-22.04 + timeout-minutes: 60 + permissions: + pull-requests: write + if: ${{ success() || failure() }} + env: + AWS_REGION: "eu-west-1" + ALLURE_S3_BUCKET: "s3://csp-allure-reports/allure_reports/cloudbeat/ci" + S3_BUCKET_ALLURE_REPORT_AP: "http://csp-allure-reports.s3.amazonaws.com/allure_reports/cloudbeat/ci" + steps: + - name: Check out the repo + uses: actions/checkout@v4 + + - uses: actions/download-artifact@v4 + if: ${{ success() || failure() }} + with: + pattern: allure-results-ci-* + path: tests/allure/results/ + merge-multiple: true + + - name: log + if: ${{ success() || failure() }} + shell: bash + run: | + ls -lahR || true + rm -f tests/allure/results/cover.out || true + + - name: Publish allure report + if: ${{ success() || failure() }} + uses: andrcuns/allure-publish-action@v2.6.0 + env: + GITHUB_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + AWS_REGION: ${{ env.AWS_REGION }} + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + with: + storageType: s3 + resultsGlob: "tests/allure/results" + updatePr: actions + collapseSummary: false + summary: suites + summaryTableType: markdown + copyLatest: true + bucket: csp-allure-reports + prefix: allure_reports/cloudbeat/ci/${{ github.event.number }} + ignoreMissingResults: true + debug: false + + - name: Allure Summary + if: ${{ success() && github.event_name == 'pull_request' }} + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + curl --fail --show-error --location '${{ env.S3_BUCKET_ALLURE_REPORT_AP }}/${{ github.event.number }}/history/history-trend.json' --output ./history-trend.json + allure_result=./history-trend.json + allure_url=${{ env.S3_BUCKET_ALLURE_REPORT_AP }}/${{ github.event.number }}/index.html + + ./.ci/scripts/allure-report-summary.sh "$allure_result" "$allure_url" + allure_summary=$(./.ci/scripts/allure-report-summary.sh "$allure_result" "$allure_url") + # posting result into job summary + echo "$allure_summary" >> $GITHUB_STEP_SUMMARY + + # saving result into env variable (with multiline handling) + echo "ALLURE_SUMMARY<> $GITHUB_ENV + echo "$allure_summary" >> $GITHUB_ENV + echo "EOF" >> $GITHUB_ENV + + - name: Comment test success result + uses: marocchino/sticky-pull-request-comment@v2 + if: ${{ success() && github.event_name == 'pull_request' }} + with: + header: CI Test Results + number: ${{ github.event.number }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + message: | + ${{ env.ALLURE_SUMMARY }} + + - if: ${{ always() }} + name: Cleanup docker image artifacts + uses: geekyeggo/delete-artifact@v5 + with: + name: docker-images + failOnError: false diff --git a/.github/workflows/cloudbeat-ci.yml b/.github/workflows/cloudbeat-ci.yml index e25cb992d5..544b338cc5 100644 --- a/.github/workflows/cloudbeat-ci.yml +++ b/.github/workflows/cloudbeat-ci.yml @@ -9,7 +9,7 @@ on: env: CONTAINER_SUFFIX: ${{ github.run_id }} - CI_ELASTIC_AGENT_DOCKER_TAG: "8.13.0-SNAPSHOT" + CI_ELASTIC_AGENT_DOCKER_TAG: "8.14.0-SNAPSHOT" CI_ELASTIC_AGENT_DOCKER_IMAGE: "704479110758.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent" concurrency: @@ -18,6 +18,7 @@ concurrency: jobs: Lint: + if: ${{ false }} # for more information see .pre-commit-config.yaml name: Pre-commit Hooks runs-on: ubuntu-latest @@ -70,6 +71,7 @@ jobs: run: just validate-mocks Build: + if: ${{ false }} name: Build runs-on: ubuntu-20.04 timeout-minutes: 20 diff --git a/.github/workflows/cnvm-ci.yml b/.github/workflows/cnvm-ci.yml index 94af1ce263..6f868f8fc3 100644 --- a/.github/workflows/cnvm-ci.yml +++ b/.github/workflows/cnvm-ci.yml @@ -9,6 +9,7 @@ on: jobs: Run-CNVM-Tests: + if: ${{ false }} name: CNVM integration test runs-on: ubuntu-22.04 timeout-minutes: 15 diff --git a/.github/workflows/eks-ci.yml b/.github/workflows/eks-ci.yml index 1d0b9326c7..fb34ea1a9c 100644 --- a/.github/workflows/eks-ci.yml +++ b/.github/workflows/eks-ci.yml @@ -24,7 +24,7 @@ env: AWS_REGION: eu-west-2 REPORTS_DIR: tests/allure/results/ KUBE_NAMESPACE: kube-system - CI_ELASTIC_AGENT_DOCKER_TAG: "8.13.0-SNAPSHOT" + CI_ELASTIC_AGENT_DOCKER_TAG: "8.14.0-SNAPSHOT" CI_ELASTIC_AGENT_DOCKER_IMAGE: "391946104644.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent" # run only a single job at a time diff --git a/.github/workflows/gcp-ci.yml b/.github/workflows/gcp-ci.yml index 47213b0e2f..e5baf60843 100644 --- a/.github/workflows/gcp-ci.yml +++ b/.github/workflows/gcp-ci.yml @@ -9,6 +9,7 @@ on: jobs: Run-CSPM-GCP-Tests: + if: ${{ false }} name: CIS GCP integration test runs-on: ubuntu-22.04 timeout-minutes: 60 diff --git a/.github/workflows/k8s-ci.yml b/.github/workflows/k8s-ci.yml index 4c8ceaab18..148fe65d70 100644 --- a/.github/workflows/k8s-ci.yml +++ b/.github/workflows/k8s-ci.yml @@ -14,7 +14,7 @@ on: env: CONTAINER_SUFFIX: ${{ github.run_id }} - CI_ELASTIC_AGENT_DOCKER_TAG: "8.13.0-SNAPSHOT" + CI_ELASTIC_AGENT_DOCKER_TAG: "8.14.0-SNAPSHOT" CI_ELASTIC_AGENT_DOCKER_IMAGE: "704479110758.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent" concurrency: @@ -106,7 +106,8 @@ jobs: k8s_functional_tests: # Run only selected tests on PRs - if: github.event_name == 'pull_request' + # if: github.event_name == 'pull_request' + if: ${{ false }} name: ${{ matrix.test-target }}-${{ matrix.kind-config }} needs: [ Build ] runs-on: ubuntu-22.04 diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 3111859b79..23b68fc898 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -19,6 +19,7 @@ concurrency: jobs: unit_tests: + if: ${{ false }} name: Unit Tests runs-on: ubuntu-20.04 timeout-minutes: 40 @@ -49,6 +50,7 @@ jobs: path: cover.out coverage: + if: ${{ false }} name: Coverage report needs: unit_tests runs-on: ubuntu-20.04 @@ -96,6 +98,7 @@ jobs: kubeval --strict -d ${{ env.K8S_MANIFEST_DIR }} --ignore-missing-schemas --ignored-filename-patterns kustomization,kind,patch,cloudbeat,cloudformation,deployment-manager --skip-kinds ClusterConfig golangci: + if: ${{ false }} name: golangci-lint runs-on: ubuntu-20.04 timeout-minutes: 15 @@ -120,6 +123,7 @@ jobs: run: golangci-lint run --whole-files --out-format github-actions terraform-linter: + if: ${{ false }} name: terraform-lint runs-on: ubuntu-20.04 steps: diff --git a/bin/hermit.hcl b/bin/hermit.hcl index 67ffcd34d4..ebdfd3c5c4 100644 --- a/bin/hermit.hcl +++ b/bin/hermit.hcl @@ -1,4 +1,4 @@ env = { - "CLOUDBEAT_VERSION": "8.13.0", + "CLOUDBEAT_VERSION": "8.14.0", "ELK_VERSION": "${CLOUDBEAT_VERSION}-SNAPSHOT", } diff --git a/scripts/packaging/docker/elastic-agent/Dockerfile b/scripts/packaging/docker/elastic-agent/Dockerfile index 3ebd5ad855..700312bc38 100644 --- a/scripts/packaging/docker/elastic-agent/Dockerfile +++ b/scripts/packaging/docker/elastic-agent/Dockerfile @@ -1,23 +1,10 @@ -ARG ELASTIC_AGENT_IMAGE # e.g. docker.elastic.co/cloud-release/elastic-agent-cloud:8.5.0-7dbc10f8-SNAPSHOT +ARG ELASTIC_AGENT_IMAGE=docker.elastic.co/beats/elastic-agent:8.14.0-SNAPSHOT -FROM --platform=linux/amd64 ${ELASTIC_AGENT_IMAGE} as elastic_agent_amd64 -ARG STACK_VERSION # e.g. 8.5.0-SNAPSHOT -ARG VCS_REF_SHORT # e.g. abc123 -ONBUILD COPY --chown=elastic-agent cloudbeat \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/cloudbeat -ONBUILD COPY --chown=elastic-agent bundle.tar.gz \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/bundle.tar.gz -ONBUILD COPY --chown=elastic-agent cloudbeat.yml \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/cloudbeat.yml +FROM ${ELASTIC_AGENT_IMAGE} as elastic_agent_cloudbeat +COPY --chown=elastic-agent:elastic-agent --chmod=755 cloudbeat /tmp/components/cloudbeat +COPY --chown=elastic-agent:elastic-agent --chmod=666 bundle.tar.gz /tmp/components/bundle.tar.gz +COPY --chown=elastic-agent:elastic-agent --chmod=644 cloudbeat.yml /tmp/components/cloudbeat.yml -FROM --platform=linux/arm64 ${ELASTIC_AGENT_IMAGE} as elastic_agent_arm64 -ARG STACK_VERSION # e.g. 8.5.0-SNAPSHOT -ARG VCS_REF_SHORT # e.g. abc123 -ONBUILD COPY --chown=elastic-agent cloudbeat \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/cloudbeat -ONBUILD COPY --chown=elastic-agent bundle.tar.gz \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/bundle.tar.gz -ONBUILD COPY --chown=elastic-agent cloudbeat.yml \ - ./data/elastic-agent-${VCS_REF_SHORT}/components/cloudbeat.yml +RUN mv /tmp/components/* "$(dirname "$(realpath "$(which elastic-agent)")")"/components/ -FROM elastic_agent_${TARGETARCH} +FROM elastic_agent_cloudbeat diff --git a/scripts/packaging/docker/elastic-agent/env.sh b/scripts/packaging/docker/elastic-agent/env.sh new file mode 100755 index 0000000000..9c24270373 --- /dev/null +++ b/scripts/packaging/docker/elastic-agent/env.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -eu + +VERSION=$(grep defaultBeatVersion version/version.go | cut -f2 -d "\"") +DEFAULT_IMAGE_TAG="${DEFAULT_IMAGE_TAG:-${VERSION}-SNAPSHOT}" +BASE_IMAGE="${BASE_IMAGE:-docker.elastic.co/beats/elastic-agent:$DEFAULT_IMAGE_TAG}" + +echo "BASE_IMAGE=${BASE_IMAGE}" diff --git a/tests/test_environments/k8s-cloudbeat-tests/templates/standalone-agent.yml b/tests/test_environments/k8s-cloudbeat-tests/templates/standalone-agent.yml index 1fa0931086..d887679f0a 100644 --- a/tests/test_environments/k8s-cloudbeat-tests/templates/standalone-agent.yml +++ b/tests/test_environments/k8s-cloudbeat-tests/templates/standalone-agent.yml @@ -487,7 +487,7 @@ spec: dnsPolicy: ClusterFirstWithHostNet containers: - name: elastic-agent - image: docker.elastic.co/beats/elastic-agent:8.4.0-SNAPSHOT + image: docker.elastic.co/beats/elastic-agent:8.14.0-SNAPSHOT args: [ "-c", "/etc/agent.yml", "-e", diff --git a/tests/test_environments/sa-agent-pytest.yml b/tests/test_environments/sa-agent-pytest.yml index d274404059..f5f26393e0 100644 --- a/tests/test_environments/sa-agent-pytest.yml +++ b/tests/test_environments/sa-agent-pytest.yml @@ -404,7 +404,7 @@ spec: dnsPolicy: ClusterFirstWithHostNet containers: - name: elastic-agent - image: 704479110758.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent:8.13.0-SNAPSHOT + image: 704479110758.dkr.ecr.eu-west-2.amazonaws.com/elastic-agent:8.14.0-SNAPSHOT imagePullPolicy: IfNotPresent args: ["-c", "/etc/agent.yml", "-e"] env: