From 431253fd7798c6bf487afbb3dd765cc4b5c896b5 Mon Sep 17 00:00:00 2001 From: foobaar Date: Tue, 13 Sep 2016 16:09:32 -0400 Subject: [PATCH 01/15] Create a temp dir that works on Linux and Darwin --- smoke.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smoke.sh b/smoke.sh index bbba7aa..9e7d646 100644 --- a/smoke.sh +++ b/smoke.sh @@ -1,6 +1,6 @@ #!/bin/bash -SMOKE_TMP_DIR=$(mktemp -d) - +# Create a temporary directory that works on both Linux and Darwin +SMOKE_TMP_DIR=`mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir'` SMOKE_AFTER_RESPONSE="" SMOKE_CURL_CODE="$SMOKE_TMP_DIR/smoke_curl_code" From 5840ad79bfd3f9c77ffa5562ee2bddd2588a5745 Mon Sep 17 00:00:00 2001 From: Pedro Manoel Evangelista Date: Mon, 11 Dec 2017 11:35:32 -0200 Subject: [PATCH 02/15] Allow testing redirect return codes --- README.md | 19 +++++++++++++++++++ smoke.sh | 12 +++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 5f78385..acf48e2 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,25 @@ The minimal smoke test will check if a URL returns with a 200 response code: smoke_url_ok "http://google.com" ``` +It is also possible to check for other response codes explicitly: + +```bash +smoke_url "http://google.com/doesnotexist" +smoke_assert_code 404 +``` + +### GET a URL and check for redirects + +In order to check for redirects, you must call `smoke_no_follow` before calling `smoke_url`: + +```bash +smoke_no_follow +smoke_url "http://google.com" +smoke_assert_code 302 +``` + +You can follow redirects again by calling `smoke_follow` + ### POST a URL and check the response code A more advanced smoke test will POST data to a URL. Such a test can be used to diff --git a/smoke.sh b/smoke.sh index 21d859b..82dd31a 100644 --- a/smoke.sh +++ b/smoke.sh @@ -7,6 +7,7 @@ SMOKE_CURL_CODE="$SMOKE_TMP_DIR/smoke_curl_code" SMOKE_CURL_HEADERS="$SMOKE_TMP_DIR/smoke_curl_headers" SMOKE_CURL_BODY="$SMOKE_TMP_DIR/smoke_curl_body" SMOKE_CURL_COOKIE_JAR="$SMOKE_TMP_DIR/smoke_curl_cookie_jar" +SMOKE_CURL_FOLLOW="--location" SMOKE_CSRF_TOKEN="" SMOKE_CSRF_FORM_DATA="$SMOKE_TMP_DIR/smoke_csrf_form_data" @@ -22,6 +23,15 @@ smoke_csrf() { SMOKE_CSRF_TOKEN="$1" } + +smoke_follow() { + SMOKE_CURL_FOLLOW="--location" +} + +smoke_no_follow() { + SMOKE_CURL_FOLLOW="" +} + smoke_form() { URL="$1" FORMDATA="$2" @@ -173,7 +183,7 @@ _smoke_success() { ## Curl helpers _curl() { - local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR --location --dump-header $SMOKE_CURL_HEADERS --silent) + local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS --silent) if [[ -n "$SMOKE_HEADER_HOST" ]] then opt+=(-H "Host: $SMOKE_HEADER_HOST") From 137b92170dbba9a2b072218c052d1bac2aa5847e Mon Sep 17 00:00:00 2001 From: Pedro Manoel Evangelista Date: Mon, 11 Dec 2017 11:35:56 -0200 Subject: [PATCH 03/15] Add functions to allow debugging requests --- README.md | 11 +++++++++++ smoke.sh | 10 +++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index acf48e2..49d93dd 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,17 @@ smoke_response_body # raw body (html/json/...) smoke_response_headers # list of headers ``` +### Debugging + +In order to debug your requests, call `smoke_debug` before calling `smoke_url`: + +```bash +smoke_debug +smoke_url_ok "http://google.com" +``` + +You can turn off debugging by calling `smoke_no_debug` + Advanced example ---------------- diff --git a/smoke.sh b/smoke.sh index 82dd31a..fed70a8 100644 --- a/smoke.sh +++ b/smoke.sh @@ -8,6 +8,7 @@ SMOKE_CURL_HEADERS="$SMOKE_TMP_DIR/smoke_curl_headers" SMOKE_CURL_BODY="$SMOKE_TMP_DIR/smoke_curl_body" SMOKE_CURL_COOKIE_JAR="$SMOKE_TMP_DIR/smoke_curl_cookie_jar" SMOKE_CURL_FOLLOW="--location" +SMOKE_CURL_VERBOSE="--silent" SMOKE_CSRF_TOKEN="" SMOKE_CSRF_FORM_DATA="$SMOKE_TMP_DIR/smoke_csrf_form_data" @@ -23,6 +24,13 @@ smoke_csrf() { SMOKE_CSRF_TOKEN="$1" } +smoke_debug() { + SMOKE_CURL_VERBOSE="--verbose" +} + +smoke_no_debug() { + SMOKE_CURL_VERBOSE="--silent" +} smoke_follow() { SMOKE_CURL_FOLLOW="--location" @@ -183,7 +191,7 @@ _smoke_success() { ## Curl helpers _curl() { - local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS --silent) + local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE) if [[ -n "$SMOKE_HEADER_HOST" ]] then opt+=(-H "Host: $SMOKE_HEADER_HOST") From 8c12bf9cac009b60ff7d29c20fb5068ce44b6ac4 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Tue, 10 Jul 2018 11:36:30 +0200 Subject: [PATCH 04/15] Add authentication support (through curl -u option) --- smoke.sh | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/smoke.sh b/smoke.sh index 45729f3..ec9b825 100644 --- a/smoke.sh +++ b/smoke.sh @@ -9,6 +9,7 @@ SMOKE_CURL_BODY="$SMOKE_TMP_DIR/smoke_curl_body" SMOKE_CURL_COOKIE_JAR="$SMOKE_TMP_DIR/smoke_curl_cookie_jar" SMOKE_CURL_FOLLOW="--location" SMOKE_CURL_VERBOSE="--silent" +SMOKE_CURL_CREDENTIALS="" SMOKE_CSRF_TOKEN="" SMOKE_CSRF_FORM_DATA="$SMOKE_TMP_DIR/smoke_csrf_form_data" @@ -40,6 +41,21 @@ smoke_no_follow() { SMOKE_CURL_FOLLOW="" } +smoke_credentials() { + USERNAME="$1" + local PASSWORD="$2" + + if [[ -z "${USERNAME// /}" ]]; then + _smoke_print_failure "Username is unset or empty" + _smoke_cleanup + exit 1 + fi + SMOKE_CURL_CREDENTIALS="-u $USERNAME" + if [[ -n "$PASSWORD" ]]; then + SMOKE_CURL_CREDENTIALS="$SMOKE_CURL_CREDENTIALS:$PASSWORD" + fi +} + smoke_form() { URL="$1" FORMDATA="$2" @@ -191,9 +207,8 @@ _smoke_success() { ## Curl helpers _curl() { - local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE) - if [[ -n "$SMOKE_HEADER_HOST" ]] - then + local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE $SMOKE_CURL_CREDENTIALS) + if [[ -n "$SMOKE_HEADER_HOST" ]]; then opt+=(-H "Host: $SMOKE_HEADER_HOST") fi curl "${opt[@]}" "$@" > $SMOKE_CURL_BODY @@ -264,5 +279,9 @@ _smoke_print_success() { _smoke_print_url() { TEXT="$1" - echo "> $TEXT" + local url_to_print="> $TEXT" + if [[ -n "${USERNAME}" ]]; then + url_to_print="$url_to_print (authenticate as ${USERNAME})" + fi + echo "$url_to_print" } From c0bef903d43d8c28a6ab4dd0edd4f2bea9c24537 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Tue, 10 Jul 2018 17:37:53 +0200 Subject: [PATCH 05/15] Update Readme with credential function --- README.md | 537 +++++++++++++++++++++++++++--------------------------- 1 file changed, 269 insertions(+), 268 deletions(-) diff --git a/README.md b/README.md index 49d93dd..d99a863 100644 --- a/README.md +++ b/README.md @@ -1,268 +1,269 @@ -smoke.sh -======== - -A minimal smoke testing framework in Bash. - -Features: - -- Response body checks -- Response code checks -- Response header checks -- GET/POST on endpoints -- CSRF tokens -- Reporting and sane exit codes - -![smoke sh](https://f.cloud.github.com/assets/657357/1238166/6f47f56a-29e4-11e3-9e19-394ca12b5fd0.png) - -Example -------- - -Checking if the Google Search home page works and contains the word "search": - -```bash -#!/bin/bash - -. smoke.sh - -smoke_url_ok "http://google.com/" - smoke_assert_body "search" -smoke_report -``` - -Running: - -```bash -$ ./smoke-google -> http://google.com/ - [ OK ] 2xx Response code - [ OK ] Body contains "search" -OK (2/2) -``` - -For a more advanced and complete example, see below. - -Setup and usage --------------- - -The recommended setup includes copying the `smoke.sh` file in the appropriate -place and creating a new file in the same directory that you will write your -tests in. - -```bash - $ tree -n - . - ├── smoke-google - └── smoke.sh - -``` - -In your file containing the tests, start with sourcing the `smoke.sh` file and -end with calling `smoke_report` if you want a final report + appropriate exit -code. - -```bash -#!/bin/bash - -. smoke.sh - -# your test assertions go here - -smoke_report -``` - -### GET a URL and check the response code - -The minimal smoke test will check if a URL returns with a 200 response code: - -```bash -smoke_url_ok "http://google.com" -``` - -It is also possible to check for other response codes explicitly: - -```bash -smoke_url "http://google.com/doesnotexist" -smoke_assert_code 404 -``` - -### GET a URL and check for redirects - -In order to check for redirects, you must call `smoke_no_follow` before calling `smoke_url`: - -```bash -smoke_no_follow -smoke_url "http://google.com" -smoke_assert_code 302 -``` - -You can follow redirects again by calling `smoke_follow` - -### POST a URL and check the response code - -A more advanced smoke test will POST data to a URL. Such a test can be used to -for example check if the login form is functional: - -```bash -smoke_form_ok "http://example.org/login" path/to/postdata -``` - -And the POST data (`path/to/postdata`): -``` -username=smoke&password=test -``` - -### Checking if the response body contains a certain string - -By checking if the response body contains certain strings you can rule out that -your server is serving a `200 OK`, which seems fine, while it is actually -serving the apache default page: - -```bash -smoke_assert_body "Password *" -``` - -### Checking if the response headers contain a certain string - -By checking response headers, you can make sure to get the correct content type: - -```bash -smoke_assert_headers "Content-Type: text/html; charset=utf-8" -``` - -### Configuring a base URL - -It is possible to setup a base URL that is prepended for each URL that is -requested. - -```bash -smoke_url_prefix "http://example.org" -smoke_url_ok "/" -smoke_url_ok "/login" -``` - -### Overriding the host - -If the server requires a certain host header to be set, override the host from the URL with - -``` -smoke_host "example.org" -``` - -To un-override, set it empty: - -``` -smoke_host "" -``` - -### CSRF tokens - -Web applications that are protected with CSRF tokens will need to extract a -CSRF token from the responses. The CSRF token will then be used in each POST -request issued by `smoke.sh`. - -Setup an after response callback to extract the token and set it. Example: - -```bash -#!/bin/bash - -. smoke.sh - -_extract_csrf() { - CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") - - if [[ $CSRF != "" ]]; then - smoke_csrf "$CSRF" # set the new CSRF token - fi -} - -SMOKE_AFTER_RESPONSE="_extract_csrf" -``` - -When the CSRF token is set, `smoke.sh` will replace the string -`__SMOKE_CSRF_TOKEN__` in your post data with the given token: - -``` -username=smoke&password=test&csrf=__SMOKE_CSRF_TOKEN__ -``` - -To get data from the last response, three helper functions are available: - -```bash -smoke_response_code # e.g. 200, 201, 400... -smoke_response_body # raw body (html/json/...) -smoke_response_headers # list of headers -``` - -### Debugging - -In order to debug your requests, call `smoke_debug` before calling `smoke_url`: - -```bash -smoke_debug -smoke_url_ok "http://google.com" -``` - -You can turn off debugging by calling `smoke_no_debug` - -Advanced example ----------------- - -More advanced example showing all features of `smoke.sh`: - -```bash -#!/bin/bash - -BASE_URL="$1" - -if [[ -z "$1" ]]; then - echo "Usage:" $(basename $0) "" - exit 1 -fi - -. smoke.sh - -_extract_csrf() { - CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") - - if [[ $CSRF != "" ]]; then - smoke_csrf "$CSRF" # set the new CSRF token - fi -} - -SMOKE_AFTER_RESPONSE="_extract_csrf" - -smoke_url_prefix "$BASE_URL" -smoke_host "example.org" - -smoke_url_ok "/" - smoke_assert_body "Welcome" - smoke_assert_body "Login" - smoke_assert_body "Password" - smoke_assert_headers "Content-Type: text/html; charset=utf-8" -smoke_form_ok "/login" postdata/login - smoke_assert_body "Hi John Doe" - smoke_assert_headers "Content-Type: text/html; charset=utf-8" -smoke_report -``` - -API ---- - -| function | description | -|---------------------------------|------------------------------------------------------| -|`smoke_assert_body ` | assert that the body contains `` | -|`smoke_assert_code ` | assert that there was a `` response code | -|`smoke_assert_code_ok` | assert that there was a `2xx` response code | -|`smoke_assert_headers ` | assert that the headers contain `` | -|`smoke_csrf ` | set the csrf token to use in POST requests | -|`smoke_form ` | POST data on url | -|`smoke_form_ok ` | POST data on url and check for a `2xx` response code | -|`smoke_report` | prints the report and exits | -|`smoke_response_body` | body of the last response | -|`smoke_response_code` | code of the last response | -|`smoke_response_headers` | headers of the last response | -|`smoke_url ` | GET a url | -|`smoke_url_ok ` | GET a url and check for a `2xx` response code | -|`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | -|`smoke_host ` | set the host header to use | -|`smoke_tcp_ok ` | open a tcp connection and check for a `Connected` response | +smoke.sh +======== + +A minimal smoke testing framework in Bash. + +Features: + +- Response body checks +- Response code checks +- Response header checks +- GET/POST on endpoints +- CSRF tokens +- Reporting and sane exit codes + +![smoke sh](https://f.cloud.github.com/assets/657357/1238166/6f47f56a-29e4-11e3-9e19-394ca12b5fd0.png) + +Example +------- + +Checking if the Google Search home page works and contains the word "search": + +```bash +#!/bin/bash + +. smoke.sh + +smoke_url_ok "http://google.com/" + smoke_assert_body "search" +smoke_report +``` + +Running: + +```bash +$ ./smoke-google +> http://google.com/ + [ OK ] 2xx Response code + [ OK ] Body contains "search" +OK (2/2) +``` + +For a more advanced and complete example, see below. + +Setup and usage +-------------- + +The recommended setup includes copying the `smoke.sh` file in the appropriate +place and creating a new file in the same directory that you will write your +tests in. + +```bash + $ tree -n + . + ├── smoke-google + └── smoke.sh + +``` + +In your file containing the tests, start with sourcing the `smoke.sh` file and +end with calling `smoke_report` if you want a final report + appropriate exit +code. + +```bash +#!/bin/bash + +. smoke.sh + +# your test assertions go here + +smoke_report +``` + +### GET a URL and check the response code + +The minimal smoke test will check if a URL returns with a 200 response code: + +```bash +smoke_url_ok "http://google.com" +``` + +It is also possible to check for other response codes explicitly: + +```bash +smoke_url "http://google.com/doesnotexist" +smoke_assert_code 404 +``` + +### GET a URL and check for redirects + +In order to check for redirects, you must call `smoke_no_follow` before calling `smoke_url`: + +```bash +smoke_no_follow +smoke_url "http://google.com" +smoke_assert_code 302 +``` + +You can follow redirects again by calling `smoke_follow` + +### POST a URL and check the response code + +A more advanced smoke test will POST data to a URL. Such a test can be used to +for example check if the login form is functional: + +```bash +smoke_form_ok "http://example.org/login" path/to/postdata +``` + +And the POST data (`path/to/postdata`): +``` +username=smoke&password=test +``` + +### Checking if the response body contains a certain string + +By checking if the response body contains certain strings you can rule out that +your server is serving a `200 OK`, which seems fine, while it is actually +serving the apache default page: + +```bash +smoke_assert_body "Password *" +``` + +### Checking if the response headers contain a certain string + +By checking response headers, you can make sure to get the correct content type: + +```bash +smoke_assert_headers "Content-Type: text/html; charset=utf-8" +``` + +### Configuring a base URL + +It is possible to setup a base URL that is prepended for each URL that is +requested. + +```bash +smoke_url_prefix "http://example.org" +smoke_url_ok "/" +smoke_url_ok "/login" +``` + +### Overriding the host + +If the server requires a certain host header to be set, override the host from the URL with + +``` +smoke_host "example.org" +``` + +To un-override, set it empty: + +``` +smoke_host "" +``` + +### CSRF tokens + +Web applications that are protected with CSRF tokens will need to extract a +CSRF token from the responses. The CSRF token will then be used in each POST +request issued by `smoke.sh`. + +Setup an after response callback to extract the token and set it. Example: + +```bash +#!/bin/bash + +. smoke.sh + +_extract_csrf() { + CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") + + if [[ $CSRF != "" ]]; then + smoke_csrf "$CSRF" # set the new CSRF token + fi +} + +SMOKE_AFTER_RESPONSE="_extract_csrf" +``` + +When the CSRF token is set, `smoke.sh` will replace the string +`__SMOKE_CSRF_TOKEN__` in your post data with the given token: + +``` +username=smoke&password=test&csrf=__SMOKE_CSRF_TOKEN__ +``` + +To get data from the last response, three helper functions are available: + +```bash +smoke_response_code # e.g. 200, 201, 400... +smoke_response_body # raw body (html/json/...) +smoke_response_headers # list of headers +``` + +### Debugging + +In order to debug your requests, call `smoke_debug` before calling `smoke_url`: + +```bash +smoke_debug +smoke_url_ok "http://google.com" +``` + +You can turn off debugging by calling `smoke_no_debug` + +Advanced example +---------------- + +More advanced example showing all features of `smoke.sh`: + +```bash +#!/bin/bash + +BASE_URL="$1" + +if [[ -z "$1" ]]; then + echo "Usage:" $(basename $0) "" + exit 1 +fi + +. smoke.sh + +_extract_csrf() { + CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") + + if [[ $CSRF != "" ]]; then + smoke_csrf "$CSRF" # set the new CSRF token + fi +} + +SMOKE_AFTER_RESPONSE="_extract_csrf" + +smoke_url_prefix "$BASE_URL" +smoke_host "example.org" + +smoke_url_ok "/" + smoke_assert_body "Welcome" + smoke_assert_body "Login" + smoke_assert_body "Password" + smoke_assert_headers "Content-Type: text/html; charset=utf-8" +smoke_form_ok "/login" postdata/login + smoke_assert_body "Hi John Doe" + smoke_assert_headers "Content-Type: text/html; charset=utf-8" +smoke_report +``` + +API +--- + +| function | description | +|-----------------------------------------|-----------------------------------------------------------------------------------------------------| +|`smoke_assert_body ` | assert that the body contains `` | +|`smoke_assert_code ` | assert that there was a `` response code | +|`smoke_assert_code_ok` | assert that there was a `2xx` response code | +|`smoke_assert_headers ` | assert that the headers contain `` | +|`smoke_credentials []` | set the credentials to use : login (and password). If password is not set, it will be prompted | +|`smoke_csrf ` | set the csrf token to use in POST requests | +|`smoke_form ` | POST data on url | +|`smoke_form_ok ` | POST data on url and check for a `2xx` response code | +|`smoke_report` | prints the report and exits | +|`smoke_response_body` | body of the last response | +|`smoke_response_code` | code of the last response | +|`smoke_response_headers` | headers of the last response | +|`smoke_url ` | GET a url | +|`smoke_url_ok ` | GET a url and check for a `2xx` response code | +|`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | +|`smoke_host ` | set the host header to use | +|`smoke_tcp_ok ` | open a tcp connection and check for a `Connected` response | From f002d6f1a485d195c2a1bdc370d5d6f646bcb9c8 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Tue, 10 Jul 2018 17:40:22 +0200 Subject: [PATCH 06/15] Update Readme with credential function --- README.md | 538 +++++++++++++++++++++++++++--------------------------- 1 file changed, 269 insertions(+), 269 deletions(-) diff --git a/README.md b/README.md index d99a863..3a8f0a2 100644 --- a/README.md +++ b/README.md @@ -1,269 +1,269 @@ -smoke.sh -======== - -A minimal smoke testing framework in Bash. - -Features: - -- Response body checks -- Response code checks -- Response header checks -- GET/POST on endpoints -- CSRF tokens -- Reporting and sane exit codes - -![smoke sh](https://f.cloud.github.com/assets/657357/1238166/6f47f56a-29e4-11e3-9e19-394ca12b5fd0.png) - -Example -------- - -Checking if the Google Search home page works and contains the word "search": - -```bash -#!/bin/bash - -. smoke.sh - -smoke_url_ok "http://google.com/" - smoke_assert_body "search" -smoke_report -``` - -Running: - -```bash -$ ./smoke-google -> http://google.com/ - [ OK ] 2xx Response code - [ OK ] Body contains "search" -OK (2/2) -``` - -For a more advanced and complete example, see below. - -Setup and usage --------------- - -The recommended setup includes copying the `smoke.sh` file in the appropriate -place and creating a new file in the same directory that you will write your -tests in. - -```bash - $ tree -n - . - ├── smoke-google - └── smoke.sh - -``` - -In your file containing the tests, start with sourcing the `smoke.sh` file and -end with calling `smoke_report` if you want a final report + appropriate exit -code. - -```bash -#!/bin/bash - -. smoke.sh - -# your test assertions go here - -smoke_report -``` - -### GET a URL and check the response code - -The minimal smoke test will check if a URL returns with a 200 response code: - -```bash -smoke_url_ok "http://google.com" -``` - -It is also possible to check for other response codes explicitly: - -```bash -smoke_url "http://google.com/doesnotexist" -smoke_assert_code 404 -``` - -### GET a URL and check for redirects - -In order to check for redirects, you must call `smoke_no_follow` before calling `smoke_url`: - -```bash -smoke_no_follow -smoke_url "http://google.com" -smoke_assert_code 302 -``` - -You can follow redirects again by calling `smoke_follow` - -### POST a URL and check the response code - -A more advanced smoke test will POST data to a URL. Such a test can be used to -for example check if the login form is functional: - -```bash -smoke_form_ok "http://example.org/login" path/to/postdata -``` - -And the POST data (`path/to/postdata`): -``` -username=smoke&password=test -``` - -### Checking if the response body contains a certain string - -By checking if the response body contains certain strings you can rule out that -your server is serving a `200 OK`, which seems fine, while it is actually -serving the apache default page: - -```bash -smoke_assert_body "Password *" -``` - -### Checking if the response headers contain a certain string - -By checking response headers, you can make sure to get the correct content type: - -```bash -smoke_assert_headers "Content-Type: text/html; charset=utf-8" -``` - -### Configuring a base URL - -It is possible to setup a base URL that is prepended for each URL that is -requested. - -```bash -smoke_url_prefix "http://example.org" -smoke_url_ok "/" -smoke_url_ok "/login" -``` - -### Overriding the host - -If the server requires a certain host header to be set, override the host from the URL with - -``` -smoke_host "example.org" -``` - -To un-override, set it empty: - -``` -smoke_host "" -``` - -### CSRF tokens - -Web applications that are protected with CSRF tokens will need to extract a -CSRF token from the responses. The CSRF token will then be used in each POST -request issued by `smoke.sh`. - -Setup an after response callback to extract the token and set it. Example: - -```bash -#!/bin/bash - -. smoke.sh - -_extract_csrf() { - CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") - - if [[ $CSRF != "" ]]; then - smoke_csrf "$CSRF" # set the new CSRF token - fi -} - -SMOKE_AFTER_RESPONSE="_extract_csrf" -``` - -When the CSRF token is set, `smoke.sh` will replace the string -`__SMOKE_CSRF_TOKEN__` in your post data with the given token: - -``` -username=smoke&password=test&csrf=__SMOKE_CSRF_TOKEN__ -``` - -To get data from the last response, three helper functions are available: - -```bash -smoke_response_code # e.g. 200, 201, 400... -smoke_response_body # raw body (html/json/...) -smoke_response_headers # list of headers -``` - -### Debugging - -In order to debug your requests, call `smoke_debug` before calling `smoke_url`: - -```bash -smoke_debug -smoke_url_ok "http://google.com" -``` - -You can turn off debugging by calling `smoke_no_debug` - -Advanced example ----------------- - -More advanced example showing all features of `smoke.sh`: - -```bash -#!/bin/bash - -BASE_URL="$1" - -if [[ -z "$1" ]]; then - echo "Usage:" $(basename $0) "" - exit 1 -fi - -. smoke.sh - -_extract_csrf() { - CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") - - if [[ $CSRF != "" ]]; then - smoke_csrf "$CSRF" # set the new CSRF token - fi -} - -SMOKE_AFTER_RESPONSE="_extract_csrf" - -smoke_url_prefix "$BASE_URL" -smoke_host "example.org" - -smoke_url_ok "/" - smoke_assert_body "Welcome" - smoke_assert_body "Login" - smoke_assert_body "Password" - smoke_assert_headers "Content-Type: text/html; charset=utf-8" -smoke_form_ok "/login" postdata/login - smoke_assert_body "Hi John Doe" - smoke_assert_headers "Content-Type: text/html; charset=utf-8" -smoke_report -``` - -API ---- - -| function | description | -|-----------------------------------------|-----------------------------------------------------------------------------------------------------| -|`smoke_assert_body ` | assert that the body contains `` | -|`smoke_assert_code ` | assert that there was a `` response code | -|`smoke_assert_code_ok` | assert that there was a `2xx` response code | -|`smoke_assert_headers ` | assert that the headers contain `` | -|`smoke_credentials []` | set the credentials to use : login (and password). If password is not set, it will be prompted | -|`smoke_csrf ` | set the csrf token to use in POST requests | -|`smoke_form ` | POST data on url | -|`smoke_form_ok ` | POST data on url and check for a `2xx` response code | -|`smoke_report` | prints the report and exits | -|`smoke_response_body` | body of the last response | -|`smoke_response_code` | code of the last response | -|`smoke_response_headers` | headers of the last response | -|`smoke_url ` | GET a url | -|`smoke_url_ok ` | GET a url and check for a `2xx` response code | -|`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | -|`smoke_host ` | set the host header to use | -|`smoke_tcp_ok ` | open a tcp connection and check for a `Connected` response | +smoke.sh +======== + +A minimal smoke testing framework in Bash. + +Features: + +- Response body checks +- Response code checks +- Response header checks +- GET/POST on endpoints +- CSRF tokens +- Reporting and sane exit codes + +![smoke sh](https://f.cloud.github.com/assets/657357/1238166/6f47f56a-29e4-11e3-9e19-394ca12b5fd0.png) + +Example +------- + +Checking if the Google Search home page works and contains the word "search": + +```bash +#!/bin/bash + +. smoke.sh + +smoke_url_ok "http://google.com/" + smoke_assert_body "search" +smoke_report +``` + +Running: + +```bash +$ ./smoke-google +> http://google.com/ + [ OK ] 2xx Response code + [ OK ] Body contains "search" +OK (2/2) +``` + +For a more advanced and complete example, see below. + +Setup and usage +-------------- + +The recommended setup includes copying the `smoke.sh` file in the appropriate +place and creating a new file in the same directory that you will write your +tests in. + +```bash + $ tree -n + . + ├── smoke-google + └── smoke.sh + +``` + +In your file containing the tests, start with sourcing the `smoke.sh` file and +end with calling `smoke_report` if you want a final report + appropriate exit +code. + +```bash +#!/bin/bash + +. smoke.sh + +# your test assertions go here + +smoke_report +``` + +### GET a URL and check the response code + +The minimal smoke test will check if a URL returns with a 200 response code: + +```bash +smoke_url_ok "http://google.com" +``` + +It is also possible to check for other response codes explicitly: + +```bash +smoke_url "http://google.com/doesnotexist" +smoke_assert_code 404 +``` + +### GET a URL and check for redirects + +In order to check for redirects, you must call `smoke_no_follow` before calling `smoke_url`: + +```bash +smoke_no_follow +smoke_url "http://google.com" +smoke_assert_code 302 +``` + +You can follow redirects again by calling `smoke_follow` + +### POST a URL and check the response code + +A more advanced smoke test will POST data to a URL. Such a test can be used to +for example check if the login form is functional: + +```bash +smoke_form_ok "http://example.org/login" path/to/postdata +``` + +And the POST data (`path/to/postdata`): +``` +username=smoke&password=test +``` + +### Checking if the response body contains a certain string + +By checking if the response body contains certain strings you can rule out that +your server is serving a `200 OK`, which seems fine, while it is actually +serving the apache default page: + +```bash +smoke_assert_body "Password *" +``` + +### Checking if the response headers contain a certain string + +By checking response headers, you can make sure to get the correct content type: + +```bash +smoke_assert_headers "Content-Type: text/html; charset=utf-8" +``` + +### Configuring a base URL + +It is possible to setup a base URL that is prepended for each URL that is +requested. + +```bash +smoke_url_prefix "http://example.org" +smoke_url_ok "/" +smoke_url_ok "/login" +``` + +### Overriding the host + +If the server requires a certain host header to be set, override the host from the URL with + +``` +smoke_host "example.org" +``` + +To un-override, set it empty: + +``` +smoke_host "" +``` + +### CSRF tokens + +Web applications that are protected with CSRF tokens will need to extract a +CSRF token from the responses. The CSRF token will then be used in each POST +request issued by `smoke.sh`. + +Setup an after response callback to extract the token and set it. Example: + +```bash +#!/bin/bash + +. smoke.sh + +_extract_csrf() { + CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") + + if [[ $CSRF != "" ]]; then + smoke_csrf "$CSRF" # set the new CSRF token + fi +} + +SMOKE_AFTER_RESPONSE="_extract_csrf" +``` + +When the CSRF token is set, `smoke.sh` will replace the string +`__SMOKE_CSRF_TOKEN__` in your post data with the given token: + +``` +username=smoke&password=test&csrf=__SMOKE_CSRF_TOKEN__ +``` + +To get data from the last response, three helper functions are available: + +```bash +smoke_response_code # e.g. 200, 201, 400... +smoke_response_body # raw body (html/json/...) +smoke_response_headers # list of headers +``` + +### Debugging + +In order to debug your requests, call `smoke_debug` before calling `smoke_url`: + +```bash +smoke_debug +smoke_url_ok "http://google.com" +``` + +You can turn off debugging by calling `smoke_no_debug` + +Advanced example +---------------- + +More advanced example showing all features of `smoke.sh`: + +```bash +#!/bin/bash + +BASE_URL="$1" + +if [[ -z "$1" ]]; then + echo "Usage:" $(basename $0) "" + exit 1 +fi + +. smoke.sh + +_extract_csrf() { + CSRF=$(smoke_response_body | grep OUR_CSRF_TOKEN | grep -oE "[a-f0-9]{40}") + + if [[ $CSRF != "" ]]; then + smoke_csrf "$CSRF" # set the new CSRF token + fi +} + +SMOKE_AFTER_RESPONSE="_extract_csrf" + +smoke_url_prefix "$BASE_URL" +smoke_host "example.org" + +smoke_url_ok "/" + smoke_assert_body "Welcome" + smoke_assert_body "Login" + smoke_assert_body "Password" + smoke_assert_headers "Content-Type: text/html; charset=utf-8" +smoke_form_ok "/login" postdata/login + smoke_assert_body "Hi John Doe" + smoke_assert_headers "Content-Type: text/html; charset=utf-8" +smoke_report +``` + +API +--- + +| function | description | +|-----------------------------------------|-----------------------------------------------------------------------------------------------------| +|`smoke_assert_body ` | assert that the body contains `` | +|`smoke_assert_code ` | assert that there was a `` response code | +|`smoke_assert_code_ok` | assert that there was a `2xx` response code | +|`smoke_assert_headers ` | assert that the headers contain `` | +|`smoke_credentials []` | set the credentials to use : login (and password). If password is not set, it will be prompted | +|`smoke_csrf ` | set the csrf token to use in POST requests | +|`smoke_form ` | POST data on url | +|`smoke_form_ok ` | POST data on url and check for a `2xx` response code | +|`smoke_report` | prints the report and exits | +|`smoke_response_body` | body of the last response | +|`smoke_response_code` | code of the last response | +|`smoke_response_headers` | headers of the last response | +|`smoke_url ` | GET a url | +|`smoke_url_ok ` | GET a url and check for a `2xx` response code | +|`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | +|`smoke_host ` | set the host header to use | +|`smoke_tcp_ok ` | open a tcp connection and check for a `Connected` response | From 76e667f0ee558656cb1c37470b8dcfed205e863a Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Thu, 26 Jul 2018 17:37:34 +0200 Subject: [PATCH 07/15] Add smoke_no_credentials to reset credentials and when smoke_assert_code fail, display actual HTTP code --- README.md | 20 ++++++++++++++++++-- smoke.sh | 12 ++++++++---- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3a8f0a2..d207e39 100644 --- a/README.md +++ b/README.md @@ -144,13 +144,13 @@ smoke_url_ok "/login" If the server requires a certain host header to be set, override the host from the URL with -``` +```bash smoke_host "example.org" ``` To un-override, set it empty: -``` +```bash smoke_host "" ``` @@ -193,6 +193,22 @@ smoke_response_body # raw body (html/json/...) smoke_response_headers # list of headers ``` +### Authentication + +If the server requires an authentication (for example : HTTP Basic authentication), you must call `smoke_credentials` before calling `smoke_url`. +If you simply specify the user name, you will be prompted for a password. + +```bash +smoke_credentials "username" "password" +smoke_url "http://secured-website.com" +``` + +To un-set credentials, call `smoke_no_credentials` : + +```bash +smoke_no_credentials +``` + ### Debugging In order to debug your requests, call `smoke_debug` before calling `smoke_url`: diff --git a/smoke.sh b/smoke.sh index ec9b825..53dff0e 100644 --- a/smoke.sh +++ b/smoke.sh @@ -56,6 +56,10 @@ smoke_credentials() { fi } +smoke_no_credentials() { + SMOKE_CURL_CREDENTIALS="" +} + smoke_form() { URL="$1" FORMDATA="$2" @@ -130,10 +134,10 @@ smoke_assert_code() { EXPECTED="$1" CODE=$(cat $SMOKE_CURL_CODE) - if [[ $CODE == $1 ]]; then - _smoke_success "$1 Response code" + if [[ $CODE == $EXPECTED ]]; then + _smoke_success "$EXPECTED Response code" else - _smoke_fail "$1 Response code" + _smoke_fail "$EXPECTED Response code ($CODE)" fi } @@ -143,7 +147,7 @@ smoke_assert_code_ok() { if [[ $CODE == 2* ]]; then _smoke_success "2xx Response code" else - _smoke_fail "2xx Response code" + _smoke_fail "2xx Response code ($CODE)" fi } From 16cfbbb2509fe994842425da1504cf16cb63c4fd Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Fri, 27 Jul 2018 10:32:17 +0200 Subject: [PATCH 08/15] Add an assertion to check that a server is not responding : smoke_assert_no_response --- README.md | 10 ++++++++++ smoke.sh | 13 +++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d207e39..371f5b5 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,15 @@ By checking response headers, you can make sure to get the correct content type: smoke_assert_headers "Content-Type: text/html; charset=utf-8" ``` +### Checking the server is not responding + +In order to check a server is not responding, you can use `smoke_assert_no_response` after calling `smoke_url`: + +```bash +smoke_url "http://myserver.com:5000/" +smoke_assert_no_response +``` + ### Configuring a base URL It is possible to setup a base URL that is prepended for each URL that is @@ -270,6 +279,7 @@ API |`smoke_assert_code ` | assert that there was a `` response code | |`smoke_assert_code_ok` | assert that there was a `2xx` response code | |`smoke_assert_headers ` | assert that the headers contain `` | +|`smoke_assert_no_response` | assert that the server is not responding | |`smoke_credentials []` | set the credentials to use : login (and password). If password is not set, it will be prompted | |`smoke_csrf ` | set the csrf token to use in POST requests | |`smoke_form ` | POST data on url | diff --git a/smoke.sh b/smoke.sh index 53dff0e..56fc49d 100644 --- a/smoke.sh +++ b/smoke.sh @@ -132,7 +132,7 @@ smoke_host() { smoke_assert_code() { EXPECTED="$1" - CODE=$(cat $SMOKE_CURL_CODE) + CODE=$(smoke_response_code) if [[ $CODE == $EXPECTED ]]; then _smoke_success "$EXPECTED Response code" @@ -142,7 +142,7 @@ smoke_assert_code() { } smoke_assert_code_ok() { - CODE=$(cat $SMOKE_CURL_CODE) + CODE=$(smoke_response_code) if [[ $CODE == 2* ]]; then _smoke_success "2xx Response code" @@ -151,6 +151,15 @@ smoke_assert_code_ok() { fi } +smoke_assert_no_response() { + CODE=$(smoke_response_code) + if [[ -z "${CODE// }" ]]; then + _smoke_success "No response from server" + else + _smoke_fail "Got a response from server" + fi +} + smoke_assert_body() { STRING="$1" From 760581dde104b0597a8041d89ffa75743c396762 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Fri, 27 Jul 2018 13:44:33 +0200 Subject: [PATCH 09/15] smoke_no_credentials does not reset USERNAME & PASSWORD + _smoke_print_url should rely on SMOKE_CURL_CREDENTIALS to know if username should be displayed --- smoke.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/smoke.sh b/smoke.sh index 56fc49d..bc6b91b 100644 --- a/smoke.sh +++ b/smoke.sh @@ -43,7 +43,7 @@ smoke_no_follow() { smoke_credentials() { USERNAME="$1" - local PASSWORD="$2" + PASSWORD="$2" if [[ -z "${USERNAME// /}" ]]; then _smoke_print_failure "Username is unset or empty" @@ -57,6 +57,8 @@ smoke_credentials() { } smoke_no_credentials() { + USERNAME="" + PASSWORD="" SMOKE_CURL_CREDENTIALS="" } @@ -293,7 +295,7 @@ _smoke_print_success() { _smoke_print_url() { TEXT="$1" local url_to_print="> $TEXT" - if [[ -n "${USERNAME}" ]]; then + if [[ -n "${SMOKE_CURL_CREDENTIALS}" ]]; then url_to_print="$url_to_print (authenticate as ${USERNAME})" fi echo "$url_to_print" From 65202718496a94bec243098440d3a825c77a44da Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Fri, 27 Jul 2018 15:15:06 +0200 Subject: [PATCH 10/15] in smoke_assert_code*, if no response code, display 'no response' --- smoke.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smoke.sh b/smoke.sh index bc6b91b..8572af2 100644 --- a/smoke.sh +++ b/smoke.sh @@ -139,7 +139,7 @@ smoke_assert_code() { if [[ $CODE == $EXPECTED ]]; then _smoke_success "$EXPECTED Response code" else - _smoke_fail "$EXPECTED Response code ($CODE)" + _smoke_fail "$EXPECTED Response code (${CODE:-No response})" fi } @@ -149,7 +149,7 @@ smoke_assert_code_ok() { if [[ $CODE == 2* ]]; then _smoke_success "2xx Response code" else - _smoke_fail "2xx Response code ($CODE)" + _smoke_fail "2xx Response code (${CODE:-No response})" fi } From 3ece1348d24c03646e5759b8ab2cc69c66b6444e Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Wed, 1 Aug 2018 18:09:40 +0200 Subject: [PATCH 11/15] Add new function 'smoke_custom_header' to add a custom header (can be called several times) and 'smoke_no_custom_headers' to reset all custom headers + tidy up functions order (configuration, request, response...) --- README.md | 2 ++ smoke.sh | 63 +++++++++++++++++++++++++++++++++++-------------------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 371f5b5..eaf058e 100644 --- a/README.md +++ b/README.md @@ -292,4 +292,6 @@ API |`smoke_url_ok ` | GET a url and check for a `2xx` response code | |`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | |`smoke_host ` | set the host header to use | +|`smoke_custom_header ` | add a custom header with the first string as the key and the second as the value | +|`smoke_no_custom_headers` | remove all custom headers | |`smoke_tcp_ok ` | open a tcp connection and check for a `Connected` response | diff --git a/smoke.sh b/smoke.sh index 8572af2..572c8fd 100644 --- a/smoke.sh +++ b/smoke.sh @@ -18,9 +18,15 @@ SMOKE_TESTS_FAILED=0 SMOKE_TESTS_RUN=0 SMOKE_URL_PREFIX="" SMOKE_HEADER_HOST="" +SMOKE_CUSTOM_HEADERS=() ## "Public API" +# Configuration +smoke_url_prefix() { + SMOKE_URL_PREFIX="$1" +} + smoke_csrf() { SMOKE_CSRF_TOKEN="$1" } @@ -62,6 +68,19 @@ smoke_no_credentials() { SMOKE_CURL_CREDENTIALS="" } +smoke_host() { + SMOKE_HEADER_HOST="$1" +} + +smoke_custom_header() { + SMOKE_CUSTOM_HEADERS+=("$1: $2") +} + +smoke_no_custom_headers() { + SMOKE_CUSTOM_HEADERS=() +} + +# Request smoke_form() { URL="$1" FORMDATA="$2" @@ -83,15 +102,18 @@ smoke_form_ok() { smoke_assert_code_ok } -smoke_report() { - _smoke_cleanup - if [[ $SMOKE_TESTS_FAILED -ne 0 ]]; then - _smoke_print_report_failure "FAIL ($SMOKE_TESTS_FAILED/$SMOKE_TESTS_RUN)" - exit 1 - fi - _smoke_print_report_success "OK ($SMOKE_TESTS_RUN/$SMOKE_TESTS_RUN)" +smoke_url() { + URL="$1" + _curl_get $URL } +smoke_url_ok() { + URL="$1" + smoke_url "$URL" + smoke_assert_code_ok +} + +# Response smoke_response_code() { cat $SMOKE_CURL_CODE } @@ -111,24 +133,16 @@ smoke_tcp_ok() { smoke_assert_body "Connected" } -smoke_url() { - URL="$1" - _curl_get $URL -} - -smoke_url_ok() { - URL="$1" - smoke_url "$URL" - smoke_assert_code_ok -} - -smoke_url_prefix() { - SMOKE_URL_PREFIX="$1" +# Report +smoke_report() { + _smoke_cleanup + if [[ $SMOKE_TESTS_FAILED -ne 0 ]]; then + _smoke_print_report_failure "FAIL ($SMOKE_TESTS_FAILED/$SMOKE_TESTS_RUN)" + exit 1 + fi + _smoke_print_report_success "OK ($SMOKE_TESTS_RUN/$SMOKE_TESTS_RUN)" } -smoke_host() { - SMOKE_HEADER_HOST="$1" -} ## Assertions @@ -226,6 +240,9 @@ _curl() { if [[ -n "$SMOKE_HEADER_HOST" ]]; then opt+=(-H "Host: $SMOKE_HEADER_HOST") fi + for header in "${SMOKE_CUSTOM_HEADERS[@]}"; do + opt+=(-H "$header") + done curl "${opt[@]}" "$@" > $SMOKE_CURL_BODY } From 158e2d6eb07416026f45d0861ede78e4f1290a7d Mon Sep 17 00:00:00 2001 From: websid Date: Fri, 14 Jun 2019 16:00:31 +0200 Subject: [PATCH 12/15] replace --quiet option in grep by -q Needed to work in docker containers --- smoke.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/smoke.sh b/smoke.sh index 21d859b..fb7bfe0 100644 --- a/smoke.sh +++ b/smoke.sh @@ -116,7 +116,7 @@ smoke_assert_code_ok() { smoke_assert_body() { STRING="$1" - smoke_response_body | grep --quiet "$STRING" + smoke_response_body | grep -q "$STRING" if [[ $? -eq 0 ]]; then _smoke_success "Body contains \"$STRING\"" @@ -128,7 +128,7 @@ smoke_assert_body() { smoke_assert_headers() { STRING="$1" - smoke_response_headers | grep --quiet "$STRING" + smoke_response_headers | grep -q "$STRING" if [[ $? -eq 0 ]]; then _smoke_success "Headers contain \"$STRING\"" From ae5ce6186ebb0106fdfd698d76ce7d1dad1499d6 Mon Sep 17 00:00:00 2001 From: "Pedro J. Molina" Date: Wed, 6 Nov 2019 21:25:10 +0100 Subject: [PATCH 13/15] Added CORS: Options + Origin support. Show Verb on report. Documentation. --- README.md | 23 +++++++++++++++++++++-- smoke.sh | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5f78385..1220788 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,8 @@ Features: - Response body checks - Response code checks - Response header checks -- GET/POST on endpoints +- GET/POST/OPTIONS on endpoints +- ORIGIN support for testing CORS responses - CSRF tokens - Reporting and sane exit codes @@ -33,7 +34,7 @@ Running: ```bash $ ./smoke-google -> http://google.com/ +> GET http://google.com/ [ OK ] 2xx Response code [ OK ] Body contains "search" OK (2/2) @@ -135,6 +136,22 @@ To un-override, set it empty: smoke_host "" ``` +### Checking CORS is enabled for a certain Origin + +First of all, set the origin header with: + +``` +smoke_origin "https://acme.corp" +``` + +Then test for CORS headers using: + +``` +smoke_url_cors "https://api.com/endpoint" + smoke_assert_headers "Access-Control-Allow-Credentials: true" + smoke_assert_headers "Access-Control-Allow-Origin: https://acme.corp" +``` + ### CSRF tokens Web applications that are protected with CSRF tokens will need to extract a @@ -227,11 +244,13 @@ API |`smoke_csrf ` | set the csrf token to use in POST requests | |`smoke_form ` | POST data on url | |`smoke_form_ok ` | POST data on url and check for a `2xx` response code | +|`smoke_origin ` | sets the `Origin` header | |`smoke_report` | prints the report and exits | |`smoke_response_body` | body of the last response | |`smoke_response_code` | code of the last response | |`smoke_response_headers` | headers of the last response | |`smoke_url ` | GET a url | +|`smoke_url_cors ` | Check CORS via OPTIONS verb | |`smoke_url_ok ` | GET a url and check for a `2xx` response code | |`smoke_url_prefix ` | set the prefix to use for every url (e.g. domain) | |`smoke_host ` | set the host header to use | diff --git a/smoke.sh b/smoke.sh index 1c821ea..83c3382 100644 --- a/smoke.sh +++ b/smoke.sh @@ -15,6 +15,7 @@ SMOKE_TESTS_FAILED=0 SMOKE_TESTS_RUN=0 SMOKE_URL_PREFIX="" SMOKE_HEADER_HOST="" +SMOKE_ORIGIN="" ## "Public API" @@ -22,6 +23,10 @@ smoke_csrf() { SMOKE_CSRF_TOKEN="$1" } +smoke_origin() { + SMOKE_ORIGIN="$1" +} + smoke_form() { URL="$1" FORMDATA="$2" @@ -66,7 +71,7 @@ smoke_response_headers() { smoke_tcp_ok() { URL="$1 $2" - _smoke_print_url "$URL" + _smoke_print_url "TCP" "$URL" echo EOF | telnet $URL > $SMOKE_CURL_BODY smoke_assert_body "Connected" } @@ -76,6 +81,11 @@ smoke_url() { _curl_get $URL } +smoke_url_cors() { + URL="$1" + _curl_options $URL +} + smoke_url_ok() { URL="$1" smoke_url "$URL" @@ -178,6 +188,10 @@ _curl() { then opt+=(-H "Host: $SMOKE_HEADER_HOST") fi + if [[ -n "$SMOKE_ORIGIN" ]] + then + opt+=(-H "Origin: $SMOKE_ORIGIN") + fi curl "${opt[@]}" "$@" > $SMOKE_CURL_BODY } @@ -185,7 +199,7 @@ _curl_get() { URL="$1" SMOKE_URL="$SMOKE_URL_PREFIX$URL" - _smoke_print_url "$SMOKE_URL" + _smoke_print_url "GET" "$SMOKE_URL" _curl $SMOKE_URL @@ -194,13 +208,26 @@ _curl_get() { $SMOKE_AFTER_RESPONSE } +_curl_options() { + URL="$1" + + SMOKE_URL="$SMOKE_URL_PREFIX$URL" + _smoke_print_url "OPTIONS" "$SMOKE_URL" + + _curl -X OPTIONS $SMOKE_URL + + grep -oE 'HTTP[^ ]+ [0-9]{3}' $SMOKE_CURL_HEADERS | tail -n1 | grep -oE '[0-9]{3}' > $SMOKE_CURL_CODE + + $SMOKE_AFTER_RESPONSE +} + _curl_post() { URL="$1" FORMDATA="$2" FORMDATA_FILE="@"$(_smoke_prepare_formdata $FORMDATA) SMOKE_URL="$SMOKE_URL_PREFIX$URL" - _smoke_print_url "$SMOKE_URL" + _smoke_print_url "POST" "$SMOKE_URL" _curl --data "$FORMDATA_FILE" $SMOKE_URL @@ -245,6 +272,7 @@ _smoke_print_success() { } _smoke_print_url() { - TEXT="$1" - echo "> $TEXT" + VERB="$1" + URL="$2" + echo "> ${VERB} ${bold}${URL}${normal}" } From b4a57063ce8ae5a11feb7cb0564156f0398f2949 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Wed, 21 Oct 2020 15:29:10 +0200 Subject: [PATCH 14/15] Add an option to set proxy and noproxy options --- README.md | 4 +++- smoke.sh | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e62c29f..2c589d9 100644 --- a/README.md +++ b/README.md @@ -312,7 +312,9 @@ API |`smoke_csrf ` | set the csrf token to use in POST requests | |`smoke_form ` | POST data on url | |`smoke_form_ok ` | POST data on url and check for a `2xx` response code | -|`smoke_origin ` | sets the `Origin` header | +|`smoke_origin ` | set the `Origin` header | +|`smoke_proxy ` | set the HTTP proxy to use [protocol://][user:password@]proxyhost[:port] | +|`smoke_no_proxy []` | Comma-separated list of hosts which do not use a proxy | |`smoke_report` | prints the report and exits | |`smoke_response_body` | body of the last response | |`smoke_response_code` | code of the last response | diff --git a/smoke.sh b/smoke.sh index 6485ad9..2a8fb87 100644 --- a/smoke.sh +++ b/smoke.sh @@ -18,6 +18,9 @@ SMOKE_HEADERS=() SMOKE_ORIGIN="" +SMOKE_NO_PROXY="" +SMOKE_PROXY="" + SMOKE_TESTS_FAILED=0 SMOKE_TESTS_RUN=0 SMOKE_URL_PREFIX="" @@ -74,6 +77,15 @@ smoke_origin() { SMOKE_ORIGIN="$1" } +smoke_proxy() { + SMOKE_PROXY="--proxy '$1'" +} + +smoke_no_proxy() { + local noproxy="${1-*}" + SMOKE_NO_PROXY="--noproxy '$noproxy'" +} + # Request smoke_form() { URL="$1" @@ -250,7 +262,7 @@ _smoke_prepare_formdata() { ## Curl helpers _curl() { # Prepare request - local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE $SMOKE_CURL_CREDENTIALS) + local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE $SMOKE_CURL_CREDENTIALS $SMOKE_PROXY $SMOKE_NO_PROXY) # Add headers if (( ${#SMOKE_HEADERS[@]} )); then From 06677b75ad154638f89420815bdc665b144d8c88 Mon Sep 17 00:00:00 2001 From: Benjamin CARTEREAU Date: Thu, 22 Oct 2020 16:33:37 +0200 Subject: [PATCH 15/15] Transform proxy and noproxy vars as array to prevent escape/expansion issues with special chars ("*") --- smoke.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/smoke.sh b/smoke.sh index 2a8fb87..1d1ddb4 100644 --- a/smoke.sh +++ b/smoke.sh @@ -18,8 +18,8 @@ SMOKE_HEADERS=() SMOKE_ORIGIN="" -SMOKE_NO_PROXY="" -SMOKE_PROXY="" +SMOKE_NO_PROXY=() +SMOKE_PROXY=() SMOKE_TESTS_FAILED=0 SMOKE_TESTS_RUN=0 @@ -78,12 +78,13 @@ smoke_origin() { } smoke_proxy() { - SMOKE_PROXY="--proxy '$1'" + SMOKE_PROXY=('--proxy' "$1") } smoke_no_proxy() { + # Default is "*" for all (need to use an array to prevent escape/expansion issues) local noproxy="${1-*}" - SMOKE_NO_PROXY="--noproxy '$noproxy'" + SMOKE_NO_PROXY=('--noproxy' "$noproxy") } # Request @@ -262,7 +263,7 @@ _smoke_prepare_formdata() { ## Curl helpers _curl() { # Prepare request - local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE $SMOKE_CURL_CREDENTIALS $SMOKE_PROXY $SMOKE_NO_PROXY) + local opt=(--cookie $SMOKE_CURL_COOKIE_JAR --cookie-jar $SMOKE_CURL_COOKIE_JAR $SMOKE_CURL_FOLLOW --dump-header $SMOKE_CURL_HEADERS $SMOKE_CURL_VERBOSE $SMOKE_CURL_CREDENTIALS "${SMOKE_PROXY[@]}" "${SMOKE_NO_PROXY[@]}") # Add headers if (( ${#SMOKE_HEADERS[@]} )); then