diff --git a/test_web.sh b/test_web.sh index 3c2846e..605d939 100755 --- a/test_web.sh +++ b/test_web.sh @@ -2,22 +2,75 @@ SCRIPTDIR="$(dirname "$0")" -# Call me with the path to the script/program running the server -# Otherwise we try looking in the parent folder (if the tests are a submodule) +# Used to find executable from several likely locations +# Pass any number of arguments, returns the first one that's +# an executable file. If a file exists but is not executable, +# a warning is printed +# Output is in the form of "WARNING:\nresult" so if exit code is 0 you can safely fetch the last line to find the result +findBin () { + #if [ $# -eq 0 ]; exit; fi + while [ ! $# -eq 0 ]; do + # Resolve symlinks + f="$(readlink -m "$1")" + shift + if [ ! -f "$f" ]; then continue; fi + if [ ! -x "$f" ]; then + echo "WARNING: "$f" exists but is not executable" >&2 + continue + fi + echo "$f" + return + done + # nothing found + return 1 +} + if [ -z "$1" ]; then - potential_server="$(readlink -m "$SCRIPTDIR"/server)" - echo $potential_server - if [ -x "$potential_server" ]; then - export FORGEHOOKENDPOINT="$potential_server" - elif [ -x "$(readlink -m "$potential_server"/../../server)" ]; then - export FORGEHOOKENDPOINT="$(readlink -m "$potential_server"/../../server)" + output="$(findBin "$SCRIPTDIR"/server "$SCRIPTDIR"/../server)" + if [ $? -eq 0 ]; then + if [[ "$(echo "$output" | wc -l)" == "1" ]]; then + export FORGEHOOKENDPOINT="$output" + else + # Some warnings, print but use result from last line + echo "$output" | head -n -1 + export FORGEHOOKENDPOINT="$(echo "$output" | tail -n 1)" + fi else - echo "test.sh SERVER" + echo "ERROR: Could not find webhook endpoint server starting script. Output:" + echo "$output" exit 1 fi else - [ ! -x "$1" ] && echo "Cannot execute "$1"" && exit 2 - export FORGEHOOKENDPOINT="$(readlink -m $1)" + export FORGEHOOKENDPOINT="$1" +fi + +if [ -z "$2" ]; then + # First try symlink from script dir + # Second try compiled version from parent repo (endpoint implementation) in whck submodule + # Third try compiled version from whck folder in grandparent folder (eg. when called from + # forge/endpoints.php/spec/test_web.sh to find forge/whck/target/*/whck) + output="$(findBin \ + "$SCRIPTDIR"/whck \ + "$SCRIPTDIR"/../whck/target/release/whck \ + "$SCRIPTDIR"/../whck/target/debug/whck \ + "$SCRIPTDIR"/../../whck/target/release/whck \ + "$SCRIPTDIR"/../../whck/target/debug/whck \ + )" + if [ $? -eq 0 ]; then + if [[ "$(echo "$output" | wc -l)" == "1" ]]; then + export WHCK="$output" + else + # Some warnings, print but use result from last line + echo "$output" | head -n -1 + export WHCK="$(echo "$output" | tail -n 1)" + fi + else + echo "ERROR: Could not find webhook check program (whck). Output:" + echo "$output" + exit 1 + fi +else + export WHCK="$2" fi ORIGDIR="$(pwd)" @@ -25,6 +78,7 @@ cd "$SCRIPTDIR" export FORGEHOOK="$(pwd)/tests/mock-forgehook.sh" export FORGEHOOKNOTIFY=/bin/true + bats tests/web/*.bats cd "$ORIGDIR" diff --git a/tests/helper.bash b/tests/helper.bash index 6ad8a17..e62003d 100755 --- a/tests/helper.bash +++ b/tests/helper.bash @@ -34,7 +34,9 @@ function send_webhook { fi # --data-binary so that newlines aren't broken # (otherwise, signature won't match) - output="$(curl --header "Content-Type: application/json" \ + outputFile="$(mktemp)" + http_status="$(curl --header "Content-Type: application/json" \ + --output "$outputFile" \ --header ""$4": "$3"" \ --request POST \ --data-binary @$TMPFILE \ @@ -44,8 +46,10 @@ function send_webhook { rm $TMPFILE # Requested succeeded, break out of loop if [ $status -eq 0 ]; then - if [[ ! "$output" = 200 ]]; then - echo "|$output|" + if [[ ! "$http_status" = 200 ]]; then + echo "ERROR: Failed with server returning code $http_status. Body:" + cat "$outputFile" + rm "$outputFile" return 2 fi return 0; diff --git a/tests/web/gitea.bats b/tests/web/gitea.bats index 78556ab..2d61993 100644 --- a/tests/web/gitea.bats +++ b/tests/web/gitea.bats @@ -7,8 +7,9 @@ function setup { if [ -z "$FORGEHOOK" ]; then FORGEHOOK="forgehook"; fi port=$(find_free_port) [ ! -z "$FORGEHOOKENDPOINT" ] - - TMPFILE=$(mktemp) + + if [ -z "$WHCK" ]; then export WHCK="whck"; fi + export WHCK_DIR="$(mktemp -d)" # Need 3>&- so bats doesn't hang because of background task $FORGEHOOKENDPOINT $port 3>&- & @@ -23,24 +24,31 @@ function teardown { # Also kill the PID's children processes kill $(ps -o pid= --ppid $FORGEHOOKPID) fi - if [ -f $TMPFILE ]; then rm $TMPFILE; fi + if [ -d $WHCK_DIR ]; then rm -r $WHCK_DIR; fi } -@test "correct signature works" { +@test "gitea: correct signature works" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook gitea.json "$repo")" - sig="$(hash_hmac sha256 "$webhook" "$($FORGEHOOK secret $repo)")" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../gitea.json "$repo")" + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="$(hash_hmac sha256 "$webhook" "$secret")" run send_webhook "${FORGEHOOKSRV}?action=gitea" "$webhook" "$sig" "X-Gitea-Signature" + echo "$output" [ $status -eq 0 ] - [[ "$output" -eq "200" ]] + [[ "$output" = "" ]] } -@test "incorrect signature fails" { +@test "gitea: incorrect signature fails" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook gitea.json "$repo")" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../gitea.json "$repo")" # Calculate wrong signature - sig="$(hash_hmac sha256 "EXTRA$webhook" "$($FORGEHOOK secret $repo)")" + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="$(hash_hmac sha256 "EXTRA$webhook" "$secret")" run send_webhook "${FORGEHOOKSRV}?action=gitea" "$webhook" "$sig" "X-Gitea-Signature" [ "$status" -eq 2 ] - [[ "$output" = "403" ]] + [[ "$output" != "" ]] } diff --git a/tests/web/github.bats b/tests/web/github.bats index 2b1f440..e58a6a9 100644 --- a/tests/web/github.bats +++ b/tests/web/github.bats @@ -7,8 +7,9 @@ function setup { if [ -z "$FORGEHOOK" ]; then FORGEHOOK="forgehook"; fi port=$(find_free_port) [ ! -z "$FORGEHOOKENDPOINT" ] - - TMPFILE=$(mktemp) + + if [ -z "$WHCK" ]; then export WHCK="whck"; fi + export WHCK_DIR="$(mktemp -d)" # Need 3>&- so bats doesn't hang because of background task $FORGEHOOKENDPOINT $port 3>&- & @@ -23,24 +24,31 @@ function teardown { # Also kill the PID's children processes kill $(ps -o pid= --ppid $FORGEHOOKPID) fi - if [ -f $TMPFILE ]; then rm $TMPFILE; fi + if [ -d $WHCK_DIR ]; then rm -r $WHCK_DIR; fi } -@test "correct signature works" { +@test "github: correct signature works" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook github.json "$repo")" - sig="$(hash_hmac sha256 "$webhook" "$($FORGEHOOK secret $repo)")" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../github.json "$repo")" + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="$(hash_hmac sha256 "$webhook" "$secret")" run send_webhook "${FORGEHOOKSRV}?action=github" "$webhook" "$sig" "X-Hub-Signature" + echo "$output" [ $status -eq 0 ] - [[ "$output" -eq "200" ]] + [[ "$output" = "" ]] } -@test "incorrect signature fails" { +@test "github: incorrect signature fails" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook github.json "$repo")" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../github.json "$repo")" # Calculate wrong signature - sig="$(hash_hmac sha256 "EXTRA$webhook" "$($FORGEHOOK secret $repo)")" + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="$(hash_hmac sha256 "EXTRA$webhook" "$secret")" run send_webhook "${FORGEHOOKSRV}?action=github" "$webhook" "$sig" "X-Hub-Signature" [ "$status" -eq 2 ] - [[ "$output" = "403" ]] + [[ "$output" != "" ]] } diff --git a/tests/web/gitlab.bats b/tests/web/gitlab.bats index ba6b225..3d5d1ef 100644 --- a/tests/web/gitlab.bats +++ b/tests/web/gitlab.bats @@ -7,8 +7,9 @@ function setup { if [ -z "$FORGEHOOK" ]; then FORGEHOOK="forgehook"; fi port=$(find_free_port) [ ! -z "$FORGEHOOKENDPOINT" ] - - TMPFILE=$(mktemp) + + if [ -z "$WHCK" ]; then export WHCK="whck"; fi + export WHCK_DIR="$(mktemp -d)" # Need 3>&- so bats doesn't hang because of background task $FORGEHOOKENDPOINT $port 3>&- & @@ -23,22 +24,31 @@ function teardown { # Also kill the PID's children processes kill $(ps -o pid= --ppid $FORGEHOOKPID) fi - if [ -f $TMPFILE ]; then rm $TMPFILE; fi + if [ -d $WHCK_DIR ]; then rm -r $WHCK_DIR; fi } -@test "correct token works" { +@test "gitlab: correct signature works" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook gitlab.json "$repo")" - run send_webhook "${FORGEHOOKSRV}?action=gitlab" "$webhook" "$($FORGEHOOK secret $repo)" "X-Gitlab-Token" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../gitlab.json "$repo")" + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="$secret" + run send_webhook "${FORGEHOOKSRV}?action=gitlab" "$webhook" "$sig" "X-Gitlab-Token" + echo "$output" [ $status -eq 0 ] - [[ "$output" = "200" ]] + [[ "$output" = "" ]] } -@test "incorrect token fails" { +@test "gitlab: incorrect signature fails" { repo="https://tildegit.org/forge/hook.sh" - webhook="$(gen_webhook gitlab.json "$repo")" - # Send FAKE token - run send_webhook "${FORGEHOOKSRV}?action=gitlab" "$webhook" "FAKE" "X-Gitlab-Token" + id="$(echo -n "$repo" | base64)" + webhook="$(gen_webhook ../gitlab.json "$repo")" + # Calculate wrong signature + secret="$($FORGEHOOK secret $repo)" + echo -n "$secret" > "$WHCK_DIR"/"$id" + sig="EXTRA$secret" + run send_webhook "${FORGEHOOKSRV}?action=gitlab" "$webhook" "$sig" "X-Gitlab-Token" [ "$status" -eq 2 ] - [[ "$output" = "403" ]] + [[ "$output" != "" ]] }