diff --git a/.github/workflows/bats-hub.yml b/.github/workflows/bats-hub.yml index faff0a799..a5e797a3e 100644 --- a/.github/workflows/bats-hub.yml +++ b/.github/workflows/bats-hub.yml @@ -42,7 +42,7 @@ jobs: env: GOBIN: /usr/local/bin run: | - sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev + sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev - name: "Build crowdsec and fixture" run: make bats-clean bats-build bats-fixture BUILD_STATIC=1 diff --git a/.github/workflows/bats-mysql.yml b/.github/workflows/bats-mysql.yml index bceaf6ce7..aafa14cf2 100644 --- a/.github/workflows/bats-mysql.yml +++ b/.github/workflows/bats-mysql.yml @@ -49,7 +49,7 @@ jobs: env: GOBIN: /usr/local/bin run: | - sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev + sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev - name: "Build crowdsec and fixture" run: | diff --git a/.github/workflows/bats-postgres.yml b/.github/workflows/bats-postgres.yml index b058f79b2..a8e4ef280 100644 --- a/.github/workflows/bats-postgres.yml +++ b/.github/workflows/bats-postgres.yml @@ -58,7 +58,7 @@ jobs: env: GOBIN: /usr/local/bin run: | - sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev + sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev - name: "Build crowdsec and fixture (DB_BACKEND: pgx)" run: | diff --git a/.github/workflows/bats-sqlite-coverage.yml b/.github/workflows/bats-sqlite-coverage.yml index ee1908b92..7d7c51f2d 100644 --- a/.github/workflows/bats-sqlite-coverage.yml +++ b/.github/workflows/bats-sqlite-coverage.yml @@ -39,7 +39,7 @@ jobs: env: GOBIN: /usr/local/bin run: | - sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq netcat-openbsd libre2-dev + sudo apt -qq -y -o=Dpkg::Use-Pty=0 install build-essential daemonize jq libre2-dev - name: "Build crowdsec and fixture" run: | diff --git a/test/README.md b/test/README.md index 7f34bd3db..723ee5d3e 100644 --- a/test/README.md +++ b/test/README.md @@ -63,7 +63,6 @@ architectures. - `jq` - `nc` - `openssl` - - `openbsd-netcat` - `python3` ## Running all tests diff --git a/test/ansible/README.md b/test/ansible/README.md index 70d29413f..d5ef9c081 100644 --- a/test/ansible/README.md +++ b/test/ansible/README.md @@ -18,7 +18,7 @@ installation and run the tests, or run the playbooks separately to iterate while - run-all.yml: run the other playbooks in the correct order. -- provision-dependencies.yml: install the bats requirements (bash, netcat, cfssl, etc.), compilers, and database. +- provision-dependencies.yml: install the bats requirements (bash, cfssl, etc.), compilers, and database. - provision-test-suite.yml: install the tests scripts and bats environment, and the crowdsec sources if we want to build the `crowdsec under test`. diff --git a/test/ansible/vagrant/experimental/alpine-3.16/bootstrap b/test/ansible/vagrant/experimental/alpine-3.16/bootstrap index 7fb806bb5..e4ac615f6 100755 --- a/test/ansible/vagrant/experimental/alpine-3.16/bootstrap +++ b/test/ansible/vagrant/experimental/alpine-3.16/bootstrap @@ -3,5 +3,5 @@ unset IFS set -euf # coreutils -> for timeout (busybox is not enough) -sudo apk add python3 go tar procps netcat-openbsd coreutils +sudo apk add python3 go tar procps coreutils diff --git a/test/ansible/vagrant/experimental/gentoo/bootstrap b/test/ansible/vagrant/experimental/gentoo/bootstrap index 513af50f9..52f622983 100755 --- a/test/ansible/vagrant/experimental/gentoo/bootstrap +++ b/test/ansible/vagrant/experimental/gentoo/bootstrap @@ -1,3 +1,3 @@ #!/bin/sh -sudo emerge --quiet app-portage/gentoolkit dev-vcs/git net-misc/curl app-misc/jq net-analyzer/openbsd-netcat +sudo emerge --quiet app-portage/gentoolkit dev-vcs/git net-misc/curl app-misc/jq diff --git a/test/bats/01_crowdsec.bats b/test/bats/01_crowdsec.bats index f8034ae5b..be06ac926 100644 --- a/test/bats/01_crowdsec.bats +++ b/test/bats/01_crowdsec.bats @@ -84,7 +84,7 @@ teardown() { config_disable_agent - sleep 5 + sleep 2 rune -0 kill -HUP "$PID" @@ -107,13 +107,13 @@ teardown() { assert_file_contains "$log_old" "Bucket routine exiting" assert_file_contains "$log_old" "serve: shutting down api server" - sleep 5 + sleep 2 assert_file_exists "$log_new" for ((i=0; i<10; i++)); do sleep 1 - grep -q "Reload is finished" <"$log_old" && break + grep -q "Reload is finished" <"$log_new" && break done echo "waited $i seconds" diff --git a/test/bats/02_nolapi.bats b/test/bats/02_nolapi.bats index dec94a86b..f1d810bc1 100644 --- a/test/bats/02_nolapi.bats +++ b/test/bats/02_nolapi.bats @@ -80,7 +80,6 @@ teardown() { @test "lapi status shouldn't be ok without api.server" { config_disable_lapi - ./instance-crowdsec start || true rune -1 cscli machines list assert_stderr --partial "local API is disabled -- this command must be run on the local API machine" } diff --git a/test/bin/check-requirements b/test/bin/check-requirements index c5580c702..7c85d365f 100755 --- a/test/bin/check-requirements +++ b/test/bin/check-requirements @@ -36,12 +36,6 @@ check_jq() { fi } -check_nc() { - if ! command -v nc >/dev/null; then - die "missing required program 'nc' (package 'netcat-openbsd')" - fi -} - check_base64() { if ! command -v base64 >/dev/null; then die "missing required program 'base64'" @@ -66,7 +60,6 @@ check_bats_core check_curl check_daemonizer check_jq -check_nc check_base64 check_python3 check_pkill diff --git a/test/bin/decode-jwt b/test/bin/decode-jwt new file mode 100755 index 000000000..2e36e9a47 --- /dev/null +++ b/test/bin/decode-jwt @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 + +import base64 +import json +import sys + + +def decode_base64url(data): + # Not the same as "bin/base64 -d": + # + -> - + # / -> _ + # = -> '' + pad = len(data) % 4 + if pad > 0: + data += '=' * (4 - pad) + return base64.urlsafe_b64decode(data) + + +def decode_jwt(token): + token = token.rstrip('\n') + header, payload, signature = token.split('.') + decoded_header = json.loads(decode_base64url(header)) + decoded_payload = json.loads(decode_base64url(payload)) + # the signature is binary, so we don't decode it + + return decoded_header, decoded_payload, signature + + +def main(): + header, payload, signature = decode_jwt(sys.stdin.read()) + out = { + 'header': header, + 'payload': payload, + 'signature': signature, + } + print(json.dumps(out, indent=4)) + + +if __name__ == '__main__': + main() diff --git a/test/bin/wait-for-port b/test/bin/wait-for-port index 4c6c55be7..15408b8e5 100755 --- a/test/bin/wait-for-port +++ b/test/bin/wait-for-port @@ -1,42 +1,64 @@ -#!/usr/bin/env bash +#!/usr/bin/env python3 -set -eu +import argparse +import os +import socket +import sys +import time -script_name=$0 +initial_interval = 0.02 +max_interval = 0.5 -die() { - echo >&2 "$@" - exit 1 -} -about() { - die "usage: ${script_name} [-q] " -} +def is_fd_open(fd): + try: + os.fstat(fd) + return True + except OSError: + return False -[[ $# -lt 1 ]] && about -QUIET= -if [[ "$1" == "-q" ]]; then - QUIET=quiet - shift -fi +# write to file descriptor 3 if it is open (during bats tests), otherwise stderr +def write_error(ex): + fd = 2 + if is_fd_open(3): + fd = 3 + os.write(fd, str(ex).encode()) -[[ $# -lt 1 ]] && about -port_number=$1 +def wait(host, port, timeout): + t0 = time.perf_counter() + current_interval = initial_interval + while True: + try: + with socket.create_connection((host, port), timeout=timeout): + break + except OSError as ex: + if time.perf_counter() - t0 >= timeout: + raise TimeoutError(f'Timeout waiting for {host}:{port} after {timeout}s') from ex + time.sleep(current_interval) + current_interval = min(current_interval * 1.5, max_interval) -# 4 seconds may seem long, but the tests must work on embedded, slow arm boxes too -for _ in $(seq 40); do - nc -z localhost "${port_number}" >/dev/null 2>&1 && exit 0 - sleep .1 -done -# send to &3 if open -if { true >&3; } 2>/dev/null; then - [[ -z "${QUIET}" ]] && echo "Can't connect to port ${port_number}" >&3 -else - [[ -z "${QUIET}" ]] && echo "Can't connect to port ${port_number}" >&2 -fi +def main(argv): + parser = argparse.ArgumentParser(description="Check if a port is open.") + parser.add_argument("port", type=int, help="Port number to check") + parser.add_argument("--host", type=str, default="localhost", help="Host to check") + parser.add_argument("-t", "--timeout", type=float, default=10.0, help="Timeout duration in seconds") + parser.add_argument("-q", "--quiet", action="store_true", help="Enable quiet mode") + args = parser.parse_args(argv) -exit 1 + try: + wait(args.host, args.port, args.timeout) + except TimeoutError as ex: + if not args.quiet: + write_error(ex) + sys.exit(1) + else: + sys.exit(0) + sys.exit(1) + + +if __name__ == "__main__": + main(sys.argv[1:])