diff --git a/.github/workflows/bats-sqlite-coverage.yml b/.github/workflows/bats-sqlite-coverage.yml index 93dadf105..72a931a81 100644 --- a/.github/workflows/bats-sqlite-coverage.yml +++ b/.github/workflows/bats-sqlite-coverage.yml @@ -8,8 +8,11 @@ env: TEST_COVERAGE: true jobs: - build: + strategy: + matrix: + go-version: ["1.20.1"] + name: "Build + tests" runs-on: ubuntu-latest timeout-minutes: 20 @@ -21,10 +24,10 @@ jobs: sudo chmod +w /etc/machine-id echo githubciXXXXXXXXXXXXXXXXXXXXXXXX | sudo tee /etc/machine-id - - name: "Set up Go 1.20" + - name: "Set up Go ${{ matrix.go-version }}" uses: actions/setup-go@v3 with: - go-version: 1.20.1 + go-version: ${{ matrix.go-version }} id: go - name: "Check out CrowdSec repository" @@ -33,6 +36,18 @@ jobs: fetch-depth: 0 submodules: true + - name: Cache Go modules + uses: actions/cache@v3 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + ~/Library/Caches/go-build + %LocalAppData%\go-build + key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-${{ matrix.go-version }}-go- + - name: "Install bats dependencies" env: GOBIN: /usr/local/bin diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 5ec9b849f..6adc690f2 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -26,6 +26,8 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + with: + config: .github/buildkit.toml - name: "Build flavor: full" uses: docker/build-push-action@v4 diff --git a/.github/workflows/publish_docker-image_on_master.yml b/.github/workflows/publish_docker-image_on_master.yml index 4d1fab719..ad92ffb24 100644 --- a/.github/workflows/publish_docker-image_on_master.yml +++ b/.github/workflows/publish_docker-image_on_master.yml @@ -38,6 +38,8 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + with: + config: .github/buildkit.toml - name: Login to DockerHub uses: docker/login-action@v2 diff --git a/.github/workflows/release_publish_docker-image-debian.yml b/.github/workflows/release_publish_docker-image-debian.yml index 90db69880..98d394a40 100644 --- a/.github/workflows/release_publish_docker-image-debian.yml +++ b/.github/workflows/release_publish_docker-image-debian.yml @@ -39,6 +39,9 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + with: + config: .github/buildkit.toml + - name: Login to DockerHub uses: docker/login-action@v2 with: diff --git a/.github/workflows/release_publish_docker-image.yml b/.github/workflows/release_publish_docker-image.yml index 029c57e69..db344f549 100644 --- a/.github/workflows/release_publish_docker-image.yml +++ b/.github/workflows/release_publish_docker-image.yml @@ -42,6 +42,9 @@ jobs: uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 + with: + config: .github/buildkit.toml + - name: Login to DockerHub uses: docker/login-action@v2 with: diff --git a/tests/bats/01_crowdsec.bats b/tests/bats/01_crowdsec.bats index 756dd8eac..00b641b9e 100644 --- a/tests/bats/01_crowdsec.bats +++ b/tests/bats/01_crowdsec.bats @@ -24,51 +24,51 @@ teardown() { #---------- @test "crowdsec (usage)" { - run -0 --separate-stderr timeout 2s "${CROWDSEC}" -h + rune -0 timeout 2s "${CROWDSEC}" -h assert_stderr_line --regexp "Usage of .*:" - run -0 --separate-stderr timeout 2s "${CROWDSEC}" --help + rune -0 timeout 2s "${CROWDSEC}" --help assert_stderr_line --regexp "Usage of .*:" } @test "crowdsec (unknown flag)" { - run -2 --separate-stderr timeout 2s "${CROWDSEC}" --foobar + rune -2 timeout 2s "${CROWDSEC}" --foobar assert_stderr_line "flag provided but not defined: -foobar" assert_stderr_line --regexp "Usage of .*" } @test "crowdsec (unknown argument)" { - run -2 --separate-stderr timeout 2s "${CROWDSEC}" trololo + rune -2 timeout 2s "${CROWDSEC}" trololo assert_stderr_line "argument provided but not defined: trololo" assert_stderr_line --regexp "Usage of .*" } @test "crowdsec (no api and no agent)" { - run -1 --separate-stderr timeout 2s "${CROWDSEC}" -no-api -no-cs + rune -1 timeout 2s "${CROWDSEC}" -no-api -no-cs assert_stderr_line --partial "You must run at least the API Server or crowdsec" } @test "crowdsec - print error on exit" { # errors that cause program termination are printed to stderr, not only logs config_set '.db_config.type="meh"' - run -1 --separate-stderr "${CROWDSEC}" + rune -1 "${CROWDSEC}" assert_stderr --partial "unable to create database client: unknown database type 'meh'" } @test "crowdsec - bad configuration (empty/missing common section)" { config_set '.common={}' - run -1 --separate-stderr "${CROWDSEC}" + rune -1 "${CROWDSEC}" refute_output assert_stderr --partial "unable to load configuration: common section is empty" config_set 'del(.common)' - run -1 --separate-stderr "${CROWDSEC}" + rune -1 "${CROWDSEC}" refute_output assert_stderr --partial "unable to load configuration: common section is empty" } @test "CS_LAPI_SECRET not strong enough" { - CS_LAPI_SECRET=foo run -1 --separate-stderr timeout 2s "${CROWDSEC}" + CS_LAPI_SECRET=foo rune -1 timeout 2s "${CROWDSEC}" assert_stderr --partial "api server init: unable to run local API: controller init: CS_LAPI_SECRET not strong enough" } @@ -77,7 +77,7 @@ teardown() { log_old="${logdir1}/crowdsec.log" config_set ".common.log_dir=\"${logdir1}\"" - run -0 ./instance-crowdsec start + rune -0 ./instance-crowdsec start # PID="$output" assert_file_exist "$log_old" assert_file_contains "$log_old" "Starting processing data" @@ -91,14 +91,14 @@ teardown() { sleep 5 # this won't work as crowdsec-wrapper does not relay the signal - # run -0 kill -HUP "$PID" + # rune -0 kill -HUP "$PID" # During functional tests, crowdsec is often run from a wrapper script, # which captures its output (for coverage reports) and cannot relay signals # at the same time. So instead of sending a SIGHUP to the wrapper, we send # it to the crowdsec process by name - with or without coverage. - run pkill -HUP -f "$BIN_DIR/crowdsec.cover" - run pkill -HUP -f "$BIN_DIR/crowdsec" + rune pkill -HUP -f "$BIN_DIR/crowdsec.cover" + rune pkill -HUP -f "$BIN_DIR/crowdsec" for ((i=0; i<10; i++)); do sleep 1 @@ -139,14 +139,14 @@ teardown() { assert_file_contains "$log_new" "CrowdSec Local API listening on 127.0.0.1:8080" assert_file_contains "$log_new" "Reload is finished" - run -0 ./instance-crowdsec stop + rune -0 ./instance-crowdsec stop } @test "crowdsec (error if the acquisition_path file is defined but missing)" { ACQUIS_YAML=$(config_get '.crowdsec_service.acquisition_path') rm -f "$ACQUIS_YAML" - run -1 --separate-stderr timeout 2s "${CROWDSEC}" + rune -1 timeout 2s "${CROWDSEC}" assert_stderr_line --partial "acquis.yaml: no such file or directory" } @@ -159,7 +159,7 @@ teardown() { rm -f "$ACQUIS_DIR" config_set '.common.log_media="stdout"' - run -124 --separate-stderr timeout 2s "${CROWDSEC}" + rune -124 timeout 2s "${CROWDSEC}" # check warning assert_stderr_line --partial "no acquisition file found" } @@ -174,7 +174,7 @@ teardown() { config_set '.crowdsec_service.acquisition_dir=""' config_set '.common.log_media="stdout"' - run -124 --separate-stderr timeout 2s "${CROWDSEC}" + rune -124 timeout 2s "${CROWDSEC}" # check warning assert_stderr_line --partial "no acquisition_path or acquisition_dir specified" } @@ -188,5 +188,5 @@ teardown() { mkdir -p "$ACQUIS_DIR" touch "$ACQUIS_DIR"/foo.yaml - run -124 --separate-stderr timeout 2s "${CROWDSEC}" + rune -124 timeout 2s "${CROWDSEC}" } diff --git a/tests/bats/01_base.bats b/tests/bats/01_cscli.bats similarity index 76% rename from tests/bats/01_base.bats rename to tests/bats/01_cscli.bats index 50af7cd99..8959f425d 100644 --- a/tests/bats/01_base.bats +++ b/tests/bats/01_cscli.bats @@ -23,63 +23,58 @@ teardown() { ./instance-crowdsec stop } -# to silence shellcheck -declare stderr - #---------- @test "cscli - usage" { - run -0 cscli + rune -0 cscli assert_output --partial "Usage:" assert_output --partial "cscli [command]" assert_output --partial "Available Commands:" # no "usage" output after every error - run -1 --separate-stderr cscli blahblah + rune -1 cscli blahblah # error is displayed as log entry, not with print assert_stderr --partial 'level=fatal msg="unknown command \"blahblah\" for \"cscli\""' refute_stderr --partial 'unknown command "blahblah" for "cscli"' } @test "cscli version" { - run -0 cscli version - assert_output --partial "version:" - assert_output --partial "Codename:" - assert_output --partial "BuildDate:" - assert_output --partial "GoVersion:" - assert_output --partial "Platform:" - assert_output --partial "Constraint_parser:" - assert_output --partial "Constraint_scenario:" - assert_output --partial "Constraint_api:" - assert_output --partial "Constraint_acquis:" + rune -0 cscli version + assert_stderr --partial "version:" + assert_stderr --partial "Codename:" + assert_stderr --partial "BuildDate:" + assert_stderr --partial "GoVersion:" + assert_stderr --partial "Platform:" + assert_stderr --partial "Constraint_parser:" + assert_stderr --partial "Constraint_scenario:" + assert_stderr --partial "Constraint_api:" + assert_stderr --partial "Constraint_acquis:" # should work without configuration file rm "${CONFIG_YAML}" - run -0 cscli version - assert_output --partial "version:" + rune -0 cscli version + assert_stderr --partial "version:" } @test "cscli help" { - run -0 cscli help + rune -0 cscli help assert_line "Available Commands:" assert_line --regexp ".* help .* Help about any command" # should work without configuration file rm "${CONFIG_YAML}" - run -0 cscli help + rune -0 cscli help assert_line "Available Commands:" } -@test "cscli config show -o human" { - run -0 cscli config show -o human +@test "cscli config show" { + rune -0 cscli config show -o human assert_output --partial "Global:" assert_output --partial "Crowdsec:" assert_output --partial "cscli:" assert_output --partial "Local API Server:" -} -@test "cscli config show -o json" { - run -0 cscli config show -o json + rune -0 cscli config show -o json assert_output --partial '"API":' assert_output --partial '"Common":' assert_output --partial '"ConfigPaths":' @@ -89,10 +84,8 @@ declare stderr assert_output --partial '"Hub":' assert_output --partial '"PluginConfig":' assert_output --partial '"Prometheus":' -} -@test "cscli config show -o raw" { - run -0 cscli config show -o raw + rune -0 cscli config show -o raw assert_line "api:" assert_line "common:" assert_line "config_paths:" @@ -101,31 +94,29 @@ declare stderr assert_line "db_config:" assert_line "plugin_config:" assert_line "prometheus:" -} -@test "cscli config show --key" { - run -0 --separate-stderr cscli config show --key Config.API.Server.ListenURI + rune -0 cscli config show --key Config.API.Server.ListenURI assert_output "127.0.0.1:8080" } @test "cscli config backup / restore" { # test that we need a valid path # disabled because in CI, the empty string is not passed as a parameter - #run -1 --separate-stderr cscli config backup "" + #rune -1 cscli config backup "" #assert_stderr --partial "failed to backup config: directory path can't be empty" - run -1 --separate-stderr cscli config backup "/dev/null/blah" + rune -1 cscli config backup "/dev/null/blah" assert_stderr --partial "failed to backup config: while creating /dev/null/blah: mkdir /dev/null/blah: not a directory" # pick a dirpath backupdir=$(TMPDIR="${BATS_TEST_TMPDIR}" mktemp -u) # succeed the first time - run -0 cscli config backup "${backupdir}" - assert_output --partial "Starting configuration backup" + rune -0 cscli config backup "${backupdir}" + assert_stderr --partial "Starting configuration backup" # don't overwrite an existing backup - run -1 --separate-stderr cscli config backup "${backupdir}" + rune -1 cscli config backup "${backupdir}" assert_stderr --partial "failed to backup config" assert_stderr --partial "file exists" @@ -133,7 +124,7 @@ declare stderr # restore rm "${SIMULATION_YAML}" - run -0 cscli config restore "${backupdir}" + rune -0 cscli config restore "${backupdir}" assert_file_exist "${SIMULATION_YAML}" # cleanup @@ -141,56 +132,55 @@ declare stderr # backup: detect missing files rm "${SIMULATION_YAML}" - run -1 --separate-stderr cscli config backup "${backupdir}" + rune -1 cscli config backup "${backupdir}" assert_stderr --regexp "failed to backup config: failed copy .* to .*: stat .*: no such file or directory" rm -rf -- "${backupdir:?}" } @test "cscli lapi status" { - run -0 --separate-stderr cscli lapi status + rune -0 cscli lapi status - run -0 echo "${stderr}" - assert_output --partial "Loaded credentials from" - assert_output --partial "Trying to authenticate with username" - assert_output --partial " on http://127.0.0.1:8080/" - assert_output --partial "You can successfully interact with Local API (LAPI)" + assert_stderr --partial "Loaded credentials from" + assert_stderr --partial "Trying to authenticate with username" + assert_stderr --partial " on http://127.0.0.1:8080/" + assert_stderr --partial "You can successfully interact with Local API (LAPI)" } @test "cscli - missing LAPI credentials file" { LOCAL_API_CREDENTIALS=$(config_get '.api.client.credentials_path') rm -f "${LOCAL_API_CREDENTIALS}" - run -1 --separate-stderr cscli lapi status + rune -1 cscli lapi status assert_stderr --partial "loading api client: while reading yaml file: open ${LOCAL_API_CREDENTIALS}: no such file or directory" - run -1 --separate-stderr cscli alerts list + rune -1 cscli alerts list assert_stderr --partial "loading api client: while reading yaml file: open ${LOCAL_API_CREDENTIALS}: no such file or directory" - run -1 --separate-stderr cscli decisions list + rune -1 cscli decisions list assert_stderr --partial "loading api client: while reading yaml file: open ${LOCAL_API_CREDENTIALS}: no such file or directory" } @test "cscli - empty LAPI credentials file" { LOCAL_API_CREDENTIALS=$(config_get '.api.client.credentials_path') truncate -s 0 "${LOCAL_API_CREDENTIALS}" - run -1 --separate-stderr cscli lapi status + rune -1 cscli lapi status assert_stderr --partial "no credentials or URL found in api client configuration '${LOCAL_API_CREDENTIALS}'" - run -1 --separate-stderr cscli alerts list + rune -1 cscli alerts list assert_stderr --partial "no credentials or URL found in api client configuration '${LOCAL_API_CREDENTIALS}'" - run -1 --separate-stderr cscli decisions list + rune -1 cscli decisions list assert_stderr --partial "no credentials or URL found in api client configuration '${LOCAL_API_CREDENTIALS}'" } @test "cscli - missing LAPI client settings" { config_set 'del(.api.client)' - run -1 --separate-stderr cscli lapi status + rune -1 cscli lapi status assert_stderr --partial "loading api client: no API client section in configuration" - run -1 --separate-stderr cscli alerts list + rune -1 cscli alerts list assert_stderr --partial "loading api client: no API client section in configuration" - run -1 --separate-stderr cscli decisions list + rune -1 cscli decisions list assert_stderr --partial "loading api client: no API client section in configuration" } @@ -198,22 +188,22 @@ declare stderr LOCAL_API_CREDENTIALS=$(config_get '.api.client.credentials_path') config_set "${LOCAL_API_CREDENTIALS}" '.url="https://127.0.0.1:-80"' - run -1 --separate-stderr cscli lapi status + rune -1 cscli lapi status assert_stderr --partial 'parsing api url' assert_stderr --partial 'invalid port \":-80\" after host' - run -1 --separate-stderr cscli alerts list + rune -1 cscli alerts list assert_stderr --partial 'parsing api url' assert_stderr --partial 'invalid port \":-80\" after host' - run -1 --separate-stderr cscli decisions list + rune -1 cscli decisions list assert_stderr --partial 'parsing api url' assert_stderr --partial 'invalid port \":-80\" after host' } @test "cscli metrics" { - run -0 cscli lapi status - run -0 --separate-stderr cscli metrics + rune -0 cscli lapi status + rune -0 cscli metrics assert_output --partial "Route" assert_output --partial '/v1/watchers/login' assert_output --partial "Local Api Metrics:" @@ -221,17 +211,17 @@ declare stderr } @test "'cscli completion' with or without configuration file" { - run -0 cscli completion bash + rune -0 cscli completion bash assert_output --partial "# bash completion for cscli" - run -0 cscli completion zsh + rune -0 cscli completion zsh assert_output --partial "# zsh completion for cscli" - run -0 cscli completion powershell + rune -0 cscli completion powershell assert_output --partial "# powershell completion for cscli" - run -0 cscli completion fish + rune -0 cscli completion fish assert_output --partial "# fish completion for cscli" rm "${CONFIG_YAML}" - run -0 cscli completion bash + rune -0 cscli completion bash assert_output --partial "# bash completion for cscli" } @@ -239,7 +229,7 @@ declare stderr # we check for the presence of some objects. There may be others when we # use $PACKAGE_TESTING, so the order is not important. - run -0 --separate-stderr cscli hub list -o human + rune -0 cscli hub list -o human assert_line --regexp '^ crowdsecurity/linux' assert_line --regexp '^ crowdsecurity/sshd' assert_line --regexp '^ crowdsecurity/dateparse-enrich' @@ -249,7 +239,7 @@ declare stderr assert_line --regexp '^ crowdsecurity/ssh-bf' assert_line --regexp '^ crowdsecurity/ssh-slow-bf' - run -0 --separate-stderr cscli hub list -o raw + rune -0 cscli hub list -o raw assert_line --regexp '^crowdsecurity/linux,enabled,[0-9]+\.[0-9]+,core linux support : syslog\+geoip\+ssh,collections$' assert_line --regexp '^crowdsecurity/sshd,enabled,[0-9]+\.[0-9]+,sshd support : parser and brute-force detection,collections$' assert_line --regexp '^crowdsecurity/dateparse-enrich,enabled,[0-9]+\.[0-9]+,,parsers$' @@ -259,8 +249,8 @@ declare stderr assert_line --regexp '^crowdsecurity/ssh-bf,enabled,[0-9]+\.[0-9]+,Detect ssh bruteforce,scenarios$' assert_line --regexp '^crowdsecurity/ssh-slow-bf,enabled,[0-9]+\.[0-9]+,Detect slow ssh bruteforce,scenarios$' - run -0 --separate-stderr cscli hub list -o json - run jq -r '.collections[].name, .parsers[].name, .scenarios[].name' <(output) + rune -0 cscli hub list -o json + rune -0 jq -r '.collections[].name, .parsers[].name, .scenarios[].name' <(output) assert_line 'crowdsecurity/linux' assert_line 'crowdsecurity/sshd' assert_line 'crowdsecurity/dateparse-enrich' @@ -272,7 +262,7 @@ declare stderr } @test "cscli support dump (smoke test)" { - run -0 cscli support dump -f "$BATS_TEST_TMPDIR"/dump.zip + rune -0 cscli support dump -f "$BATS_TEST_TMPDIR"/dump.zip assert_file_exist "$BATS_TEST_TMPDIR"/dump.zip } diff --git a/tests/lib/bats-core b/tests/lib/bats-core index 410dd229a..6636e2c2e 160000 --- a/tests/lib/bats-core +++ b/tests/lib/bats-core @@ -1 +1 @@ -Subproject commit 410dd229a5ed005c68167cc90ed0712ad2a1c909 +Subproject commit 6636e2c2ef5ffe361535cb45fc61682c5ef46b71