* feat: add ability to listen on unix socket/named pipe
Add a -socket option that configures the server to listen on a Unix-domain socket or Windows named pipe instead of a TCP port. This allows webhook to be used behind a reverse proxy on multi-tenant shared hosting without the need to choose (and the permission to bind to) a free port number.
On Windows, -socket is expected to be a named pipe such as \\.\pipe\webhook, and the code uses https://github.com/microsoft/go-winio to bind the listening socket. On other platforms, -socket is the path to a Unix domain socket such as /tmp/webhook.sock, or an abstract socket name starting with @, bound using the regular net.Listen function with the "network" parameter set to "unix".
Note: this pushes our minimum Go version up to 1.21 as that is what go-winio requires, but that is already the minimum version against which we are testing in the CI matrix.
* tests: add test for the -socket option
Refactored webhook_test so that the test HTTP requests are made using an explicitly-provided http.Client, so we can run at least one test with the server bound to a socket instead of a port number, using an http.Client whose transport has been configured with a suitable Unix-domain or Windows named pipe dialer function.
* tests: use GOROOT to find go command
This should ensure that, even if a developer or CI server has multiple versions of go installed, the version used to build the tools under test will be the same version that is running the test harness.
* fix: clean up Unix socket file before exit
If webhook is restarted with the same settings but the socket file has not been deleted, webhook will be unable to bind and will exit with an error.
* docs: add -socket option to documentation
* docs: add a note about reverse proxies
- README mentions the idea of using webhook behind a reverse proxy, including with the -socket flag
- added a note in Hook-Rules that the ip-whitelist rule type does not work as expected behind a reverse proxy, and you should configure IP restrictions at the proxy level instead
The existing `entire-payload` option sends a JSON representation of the
parsed request body. Add a new `raw-request-body` source to send the
raw request body.
Fixes#439
When matching variables in routes, gorilla/mux uses a default pattern of
"[^/]+", thereby prohibiting slashes in variable matching. Override the
default pattern to remove this restriction.
See https://github.com/gorilla/mux/blob/v1.8.0/regexp.go#L50Fixes#421
To avoid having to pass around so many parameters to the hook package,
create a Request object to store all request-specific data. Update APIs
accordingly.
The error returned by exec.LookPath was never surfaced to the user.
Without that detail, the user can't tell the difference between a
non-existent path and a permissions issue.
Additionally, when ExecuteCommand is an absolute path, we were still
attempting to prepend the CommandWorkingDirectory if the ExecuteCommand
was not found, which made it difficult to know which path the user
intended to execute.
This commit simplifies the logic to avoid multiple attempts with
ExecuteCommand is an absolute path and changes the error message from:
error locating command: '/path/to/file'
to:
error in exec: "/path/to/file": stat /path/to/file: no such file or directory
error in exec: "/path/to/file": permission denied
Fixes#457
Detect if leading character in JSON payload is an array bracket. If
found, decode payload into an interface{} and then save the results into
payload["root"]. References to payload values would need to reference
the leading, "virtual" root node (i.e. "root.0.name").
Fixes#215
PR #266 appears to have changed the default response code to StatusOK.
waitForServerReady() was expected a StatusNotFound response, which was
preventing all TestWebhook tests from running.
There's the potential for a race condition where we try to read the logs
buffer before the logs have been flushed by the webhook process. Kill
the process to flush the logs before testing against the log buffer.
This commit incorporates some tests into the main TestWebhook framework. New features to TestWebhook:
- Check log output against Regexp
- Add Testing sub-tests
Updates #225
Two issues are addressed in this commit:
1. Instead of only sending the predefined environment arguments, this
commit appends the arguments to the existing OS environment. Fixes#53.
2. If an argument is not found in the payload, allow the command to run
and pass in an empty string as a placeholder. Fixes#54.
Additionally, I replaced `hook.ErrInvalidPayloadSignature` with a new
`SignatureError` type so that we can embed the signature in the error.
There's a lot in this commit.
1. Add `pass-environment-to-command` option that works much like
`pass-arguments-to-command`. You can see an example usage in the
"github" test case.
2. Add a test program called "hookecho" that is used to test the
webhook package instead of relying upon a system `echo` command.
3. Move hooks_test.json to a template so that we can update the path to
hookecho on the fly.
4. Don't return an error at the end of hook.MatchRule.Evaluate(). All
tests succeed for me now.
This commit adds a testing framework modeled after the godoc tests. It builds
webhook in a temporary directory, runs it with the supplied `hooks_test.json`
configuration, and then tests different payloads. I use `/bin/echo` for the
test executable, so I've added build tags to exclude Windows.
Three minor (I hope) changes in functionality:
- I ended up moving everything from `init()` to `main()` because `init()` was
firing while trying to build the tests, and it was dying since `hooks.json`
didn't exist. I'm still not 100% sure `init()` was firing, but I didn't see
any real need for anything to be in `init()` in the first place.
- make sure logger is using `os.Stderr`
- don't send `http.StatusBadRequest` when the Hook rules don't match. "Bad
Request" is used to identify malformed requests. The request was properly
formed and processed, so I think we should send back `http.StatusOK`. For
example, if I setup a webhook rule to only execute when commits are made to
the `master` branch, we shouldn't send back `http.StatusBadRequest` when we
ingest a payload for the `development` branch.
The test payloads are pretty verbose and could probably be shortened, but I kind
of like having an example payload for each service. We can pare them down if we
want to do more focused, minimalist testing.