goss-org / goss

Quick and Easy server testing/validation
https://goss.rocks
Apache License 2.0
5.6k stars 473 forks source link

https test's dont honor Status+Header if expected as "ok" if failed #765

Open ninja-ops opened 2 years ago

ninja-ops commented 2 years ago

Describe the bug

the http request test does not honor the status code 403 in conjunction with a proxy, who denies the request, but its ok either.

in addition to this, headers returned from the proxy, who might be "ok", aren't honored.

How To Reproduce

setup a proxy to allow only certain domains via CONNECT or destination ips.

define different goss test's to use this proxy and test for these url's, who are not allowed in the proxy and goss is configured to accept a 403 or an expected header.

a squid.conf for squid 3.5.20 might look like ..

acl localnet src 10.0.0.0/8
acl SSL_ports port 443
acl Safe_ports port 443
acl CONNECT method CONNECT
acl allowed_sites dstdomain www.google.com
acl allowed_sites dstdomain www.github.com
acl allowed_sites dstdomain github.com
acl allowed_dst dst 10.0.0.100
http_access deny !Safe_ports
http_access deny CONNECT !allowed_sites !allowed_dst
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 3128

using podman you can setup a squid with centos7 using podman with mounting the local dir containing the squid.conf from above ..

podman pull registry.centos.org/centos:7
podman run -dt \
  --publish 3128:3128 \
  --mount type=bind,source=.,destination=/tmp/local \
  --name squid \
  registry.centos.org/centos:7
podman exec squid yum install squid -y

squid can then be fired up in the foreground no-deamon setting with this line, can be break with ctrl+c

podman exec -ti squid squid -N -d debug -f /tmp/local/squid.conf

start another session for controlling what squid is serving ..

podman exec -ti squid tail -f /var/log/squid/access.log

use this goss.yaml for testing ..

port:
  tcp:3128:
    listening: true

http:
  https://www.amazon.com:
    headers: ["X-Squid-Error: ERR_ACCESS_DENIED 0"]
    proxy: http://127.0.0.1:3128

  https://www.amazon.com:
    status: 403
    headers: ["X-Squid-Error: ERR_ACCESS_DENIED 0"]
    proxy: http://127.0.0.1:3128

  https://www.bing.com:
    status: 403
    proxy: http://127.0.0.1:3128

  https://www.google.com:
    status: 200
    proxy: http://127.0.0.1:3128

  https://www.github.com:
    status: 301
    no-follow-redirects: true
    proxy: http://127.0.0.1:3128

  https://github.com:
    status: 200
    proxy: http://127.0.0.1:3128

current output looks like this ..

1..7
not ok 1 - https://www.amazon.com: status: Error: Get "https://www.amazon.com": Forbidden
ok 2 - # SKIP HTTP: https://www.amazon.com: Headers: skipped
not ok 3 - https://www.bing.com: status: Error: Get "https://www.bing.com": Forbidden
ok 4 - Port: tcp:3128: listening: matches expectation: [true]
ok 5 - HTTP: https://www.github.com: status: matches expectation: [301]
ok 6 - HTTP: https://github.com: status: matches expectation: [200]
ok 7 - HTTP: https://www.google.com: status: matches expectation: [200]

Expected Behavior

goss should honor status 403 as "ok" if a proxy responds with 403 and not with "not ok" "Forbidden".

goss should honor response headers if a proxy is used, beside some "error's" during using the proxy and not "SKIP".

Actual Behavior

goss says "not ok" to requests using a proxy, where the proxy returns a 403, but the test condition ist "status: 403" or the headers from the error response of the proxy are set to "ok", either if it is a X-Squid-Error ..

Environment:

aelsabbahy commented 2 years ago

linux something

😂

Agreed, this looks like a bug to me. Thanks for the extremely clear bug report.

aelsabbahy commented 1 year ago

Looked into this, it's a bit more challenging than I expected.

Essentially the net/http client in golang doesn't really expose this:

This was in my notes from a few months back. I'll give a second look through to try and see if there's a solution that doesn't require forking the go stdlib code or if anything changed in the code with the new versions of golang.