diff --git a/.gitignore b/.gitignore index 904f75874..163232a37 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,9 @@ plugins/notifications/dummy/notification-dummy #test binaries pkg/csplugin/tests/cs_plugin_test* +#test cache (downloaded files) +.cache + #release stuff crowdsec-v* pkg/cwhub/hubdir/.index.json diff --git a/config/config.yaml b/config/config.yaml index db7bcdbaf..47a6cfff5 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -22,6 +22,7 @@ crowdsec_service: parser_routines: 1 cscli: output: human + color: auto db_config: log_level: info type: sqlite diff --git a/pkg/csplugin/broker.go b/pkg/csplugin/broker.go index 90afa5ffb..944d84202 100644 --- a/pkg/csplugin/broker.go +++ b/pkg/csplugin/broker.go @@ -119,7 +119,7 @@ loop: }() case <-pluginTomb.Dying(): - log.Infof("plugingTomb dying") + log.Infof("pluginTomb dying") pb.watcher.tomb.Kill(errors.New("Terminating")) for { select { diff --git a/tests/ansible/provision_dependencies.yml b/tests/ansible/provision_dependencies.yml index 8f6a97cb1..891bcc16e 100644 --- a/tests/ansible/provision_dependencies.yml +++ b/tests/ansible/provision_dependencies.yml @@ -21,7 +21,8 @@ vars_files: - vars/postgres.yml tasks: - - ansible.builtin.include_role: + - name: role "geerlingguy.postgresql" + ansible.builtin.include_role: name: geerlingguy.postgresql ## enable this for debugging # vars: @@ -35,7 +36,8 @@ vars_files: - vars/mysql.yml tasks: - - ansible.builtin.include_role: + - name: role "geerlingguy.mysql" + ansible.builtin.include_role: name: geerlingguy.mysql when: - lookup('ansible.builtin.env', 'DB_BACKEND') == 'mysql' diff --git a/tests/bats/01_crowdsec.bats b/tests/bats/01_crowdsec.bats index dce5805c3..a60b576dd 100644 --- a/tests/bats/01_crowdsec.bats +++ b/tests/bats/01_crowdsec.bats @@ -82,12 +82,16 @@ teardown() { # this won't work as crowdsec-wrapper does not relay the signal # run -0 kill -HUP "$PID" - run killall -HUP "$BIN_DIR/crowdsec.cover" - run killall -HUP "$BIN_DIR/crowdsec" + # 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" - for ((i=0; i<20; i++)); do + for ((i=0; i<10; i++)); do sleep 1 - grep -q "killing all plugins" <"$log_old" && break + grep -q "serve: shutting down api server" <"$log_old" && break done echo "waited $i seconds" @@ -103,14 +107,12 @@ teardown() { assert_file_contains "$log_old" "Killing parser routines" assert_file_contains "$log_old" "Bucket routine exiting" assert_file_contains "$log_old" "serve: shutting down api server" - assert_file_contains "$log_old" "plugingTomb dying" - assert_file_contains "$log_old" "killing all plugins" sleep 5 assert_file_exist "$log_new" - for ((i=0; i<20; i++)); do + for ((i=0; i<10; i++)); do sleep 1 grep -q "Reload is finished" <"$log_old" && break done diff --git a/tests/bats/04_capi.bats b/tests/bats/04_capi.bats index e7e1f9866..6564d1f6a 100644 --- a/tests/bats/04_capi.bats +++ b/tests/bats/04_capi.bats @@ -39,14 +39,14 @@ setup() { run cscli alerts list -a -o json if [[ "${status}" -ne 0 ]]; then - run cscli alerts list -o json + run --separate-stderr cscli alerts list -o json fi run -0 jq -r '. | length' <(output) refute_output 0 } @test "we have exactly one machine, localhost" { - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq -c '[. | length, .[0].machineId[0:32], .[0].isValidated, .[0].ipAddress]' <(output) assert_output '[1,"githubciXXXXXXXXXXXXXXXXXXXXXXXX",true,"127.0.0.1"]' } diff --git a/tests/bats/10_bouncers.bats b/tests/bats/10_bouncers.bats index 6d573a3e0..832fea019 100644 --- a/tests/bats/10_bouncers.bats +++ b/tests/bats/10_bouncers.bats @@ -24,7 +24,7 @@ teardown() { #---------- @test "there are 0 bouncers" { - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output "[]" } @@ -32,7 +32,7 @@ teardown() { run -0 cscli bouncers add ciTestBouncer assert_output --partial "Api key for 'ciTestBouncer':" run -0 cscli bouncers delete ciTestBouncer - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output '[]' } diff --git a/tests/bats/11_bouncers_tls.bats b/tests/bats/11_bouncers_tls.bats index 119ef10cd..dcb1ff450 100644 --- a/tests/bats/11_bouncers_tls.bats +++ b/tests/bats/11_bouncers_tls.bats @@ -61,17 +61,17 @@ teardown() { #---------- @test "there are 0 bouncers" { - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output "[]" } @test "simulate one bouncer request with a valid cert" { run -0 curl -s --cert "${tmpdir}/bouncer.pem" --key "${tmpdir}/bouncer-key.pem" --cacert "${tmpdir}/bundle.pem" https://localhost:8080/v1/decisions\?ip=42.42.42.42 assert_output "null" - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json run -0 jq '. | length' <(output) assert_output '1' - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json run -0 jq -r '.[] | .name' <(output) assert_output "localhost@127.0.0.1" run cscli bouncers delete localhost@127.0.0.1 @@ -79,19 +79,19 @@ teardown() { @test "simulate one bouncer request with an invalid cert" { run curl -s --cert "${tmpdir}/bouncer_invalid.pem" --key "${tmpdir}/bouncer_invalid-key.pem" --cacert "${tmpdir}/ca-key.pem" https://localhost:8080/v1/decisions\?ip=42.42.42.42 - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output "[]" } @test "simulate one bouncer request with an invalid OU" { run curl -s --cert "${tmpdir}/bouncer_bad_ou.pem" --key "${tmpdir}/bouncer_bad_ou-key.pem" --cacert "${tmpdir}/bundle.pem" https://localhost:8080/v1/decisions\?ip=42.42.42.42 - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output "[]" } @test "simulate one bouncer request with a revoked certificate" { run -0 curl -i -s --cert "${tmpdir}/bouncer_revoked.pem" --key "${tmpdir}/bouncer_revoked-key.pem" --cacert "${tmpdir}/bundle.pem" https://localhost:8080/v1/decisions\?ip=42.42.42.42 assert_output --partial "access forbidden" - run -0 cscli bouncers list -o json + run -0 --separate-stderr cscli bouncers list -o json assert_output "[]" } diff --git a/tests/bats/20_collections.bats b/tests/bats/20_collections.bats index f33f0384f..c63d4c3bd 100644 --- a/tests/bats/20_collections.bats +++ b/tests/bats/20_collections.bats @@ -100,6 +100,8 @@ teardown() { } @test "can remove all collections" { + # we may have this too, from package installs + run cscli parsers delete crowdsecurity/whitelists run -0 cscli collections remove --all assert_output --partial "Removed symlink [crowdsecurity/sshd]" assert_output --partial "Removed symlink [crowdsecurity/linux]" diff --git a/tests/bats/30_machines.bats b/tests/bats/30_machines.bats index 8af95913b..8f2c33d72 100644 --- a/tests/bats/30_machines.bats +++ b/tests/bats/30_machines.bats @@ -28,7 +28,7 @@ teardown() { } @test "we have exactly one machine" { - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq -c '[. | length, .[0].machineId[0:32], .[0].isValidated]' <(output) assert_output '[1,"githubciXXXXXXXXXXXXXXXXXXXXXXXX",true]' } @@ -39,7 +39,7 @@ teardown() { assert_output --partial "API credentials dumped to '/dev/null'" # we now have two machines - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq -c '[. | length, .[-1].machineId, .[0].isValidated]' <(output) assert_output '[2,"CiTestMachine",true]' @@ -48,7 +48,7 @@ teardown() { assert_output --partial "machine 'CiTestMachine' deleted successfully" # we now have one machine again - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq '. | length' <(output) assert_output 1 } @@ -58,17 +58,17 @@ teardown() { assert_output --partial "Successfully registered to Local API (LAPI)" assert_output --partial "Local API credentials dumped to '/dev/null'" - # "the machine is not validated yet" { - run -0 cscli machines list -o json + # the machine is not validated yet + run -0 --separate-stderr cscli machines list -o json run -0 jq '.[-1].isValidated' <(output) assert_output 'null' - # "validate the machine" { + # validate the machine run -0 cscli machines validate CiTestMachineRegister -o human assert_output --partial "machine 'CiTestMachineRegister' validated successfully" # the machine is now validated - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq '.[-1].isValidated' <(output) assert_output 'true' @@ -77,7 +77,7 @@ teardown() { assert_output --partial "machine 'CiTestMachineRegister' deleted successfully" # we now have one machine, again - run -0 cscli machines list -o json + run -0 --separate-stderr cscli machines list -o json run -0 jq '. | length' <(output) assert_output 1 } diff --git a/tests/bats/80_alerts.bats b/tests/bats/80_alerts.bats index 514e90d62..94f761f8b 100644 --- a/tests/bats/80_alerts.bats +++ b/tests/bats/80_alerts.bats @@ -123,12 +123,25 @@ teardown() { } @test "cscli alerts delete (by id)" { + run -0 cscli alerts delete --help + if [[ ! "$output" =~ "--id string" ]]; then + skip "cscli alerts delete --id not supported" + fi + + # make sure there is at least one alert run -0 cscli decisions add -i 127.0.0.1 -d 1h -R crowdsecurity/test - run -0 --separate-stderr cscli alerts delete --id 1 + # when testing with global config, alert id is not guaranteed to be 1. + # we'll just remove the first alert we find + run -0 --separate-stderr cscli alerts list -o json + run -0 jq -c '.[0].id' <(output) + ALERT_ID="$output" + + run -0 --separate-stderr cscli alerts delete --id "$ALERT_ID" refute_output assert_stderr --partial "1 alert(s) deleted" - run -1 --separate-stderr cscli alerts delete --id 1 + # can't delete twice + run -1 --separate-stderr cscli alerts delete --id "$ALERT_ID" refute_output assert_stderr --partial "Unable to delete alert" assert_stderr --partial "API error: ent: alert not found" @@ -149,13 +162,13 @@ teardown() { @test "cscli alerts delete (with cascade to decisions)" { run -0 cscli decisions add -i 1.2.3.4 - run -0 cscli decisions list -o json + run -0 --separate-stderr cscli decisions list -o json run -0 jq '. | length' <(output) assert_output 1 run -0 --separate-stderr cscli alerts delete -i 1.2.3.4 assert_stderr --partial 'alert(s) deleted' - run -0 cscli decisions list -o json + run -0 --separate-stderr cscli decisions list -o json assert_output null } @@ -170,7 +183,7 @@ teardown() { @test "bad duration" { skip 'TODO' run -0 cscli decisions add -i 10.20.30.40 -t ban - run -9 cscli decisions list --ip 10.20.30.40 -o json + run -9 --separate-stderr cscli decisions list --ip 10.20.30.40 -o json run -9 jq -r '.[].decisions[].id' <(output) DECISION_ID="${output}" diff --git a/tests/bin/check-requirements b/tests/bin/check-requirements index 3099be877..f6889fc04 100755 --- a/tests/bin/check-requirements +++ b/tests/bin/check-requirements @@ -48,6 +48,12 @@ check_base64() { fi } +check_pkill() { + if ! command -v pkill >/dev/null; then + die "missing required program 'pkill'" + fi +} + check_yq() { # shellcheck disable=SC2016 howto_install='You can install it with your favorite package manager (including snap) or with "go install github.com/mikefarah/yq/v4@latest" and add ~/go/bin to $PATH.' @@ -97,6 +103,7 @@ check_nc check_base64 check_python3 check_yq +check_pkill if [[ -n "${TEST_COVERAGE}" ]]; then check_gocovmerge fi diff --git a/tests/bin/crowdsec-wrapper b/tests/bin/crowdsec-wrapper index eb9725964..8477076e0 100755 --- a/tests/bin/crowdsec-wrapper +++ b/tests/bin/crowdsec-wrapper @@ -17,8 +17,8 @@ mkdir -p "${LOCAL_DIR}/var/lib/coverage" # this would be nice but doesn't work, since the binary is not running in background #_hup() { -# echo "killall -1 crowdsec.cover" -# killall -HUP crowdsec.cover +# echo "pkill -1 crowdsec.cover" +# pkill -HUP crowdsec.cover #} # ## relay the "configuration reload" signal diff --git a/tests/lib/db/instance-sqlite b/tests/lib/db/instance-sqlite index ec1340701..8c7d58f2a 100755 --- a/tests/lib/db/instance-sqlite +++ b/tests/lib/db/instance-sqlite @@ -56,7 +56,8 @@ fi config_yaml() { yq e ' .db_config.type=strenv(DB_BACKEND) | - .db_config.db_path=strenv(DB_FILE) + .db_config.db_path=strenv(DB_FILE) | + .db_config.use_wal=true ' -i "${CONFIG_YAML}" } @@ -64,6 +65,7 @@ config_yaml() { case "$1" in config-yaml) + config_yaml ;; setup) ;;