webhookd/README.md

307 lines
8.0 KiB
Markdown
Raw Normal View History

2015-04-20 17:26:44 +00:00
# webhookd
2014-09-19 18:46:04 +00:00
2018-08-28 15:45:10 +00:00
[![Build Status](https://travis-ci.org/ncarlier/webhookd.svg?branch=master)](https://travis-ci.org/ncarlier/webhookd)
2018-01-15 10:52:11 +00:00
[![Image size](https://images.microbadger.com/badges/image/ncarlier/webhookd.svg)](https://microbadger.com/images/ncarlier/webhookd)
2015-12-11 14:00:41 +00:00
[![Docker pulls](https://img.shields.io/docker/pulls/ncarlier/webhookd.svg)](https://hub.docker.com/r/ncarlier/webhookd/)
2015-12-11 13:58:57 +00:00
2014-09-21 20:00:55 +00:00
A very simple webhook server to launch shell scripts.
2018-08-23 21:30:22 +00:00
![Logo](webhookd.svg)
2015-04-20 17:26:44 +00:00
## Installation
2014-09-21 20:00:55 +00:00
2018-01-02 16:57:27 +00:00
Run the following command:
2015-03-24 20:41:05 +00:00
2018-01-02 16:57:27 +00:00
```bash
2018-11-17 09:23:50 +00:00
$ go get -v github.com/ncarlier/webhookd
2018-01-02 16:57:27 +00:00
```
2014-09-21 20:00:55 +00:00
2018-01-02 16:57:27 +00:00
**Or** download the binary regarding your architecture:
2014-09-21 20:00:55 +00:00
2018-01-02 16:57:27 +00:00
```bash
$ sudo curl -s https://raw.githubusercontent.com/ncarlier/webhookd/master/install.sh | bash
2015-04-20 17:26:44 +00:00
```
2014-09-21 20:00:55 +00:00
2018-01-02 16:57:27 +00:00
**Or** use Docker:
2015-03-24 20:41:05 +00:00
2018-01-02 16:57:27 +00:00
```bash
2015-04-20 17:26:44 +00:00
$ docker run -d --name=webhookd \
-v ${PWD}/scripts:/var/opt/webhookd/scripts \
-p 8080:8080 \
2018-12-31 09:16:51 +00:00
ncarlier/webhookd \
webhookd --scripts=/var/opt/webhookd/scripts
2015-04-20 17:26:44 +00:00
```
2015-03-24 20:41:05 +00:00
> Note that this image extends `docker:dind` Docker image.
> Therefore you are able to interact with a Docker daemon with yours shell scripts.
2015-03-24 20:41:05 +00:00
2018-07-06 14:08:51 +00:00
## Configuration
You can configure the daemon by:
### Setting environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `APP_LISTEN_ADDR` | `:8080` | HTTP service address |
| `APP_PASSWD_FILE` | `.htpasswd` | Password file for HTTP basic authentication |
| `APP_NB_WORKERS` | `2` | The number of workers to start |
2018-07-06 14:08:51 +00:00
| `APP_HOOK_TIMEOUT` | `10` | Hook maximum delay before timeout (in second) |
| `APP_SCRIPTS_DIR` | `./scripts` | Scripts directory |
| `APP_SCRIPTS_GIT_URL` | none | GIT repository that contains scripts (Note: this is only used by the Docker image or by using the Docker entrypoint script) |
| `APP_SCRIPTS_GIT_KEY` | none | GIT SSH private key used to clone the repository (Note: this is only used by the Docker image or by using the Docker entrypoint script) |
| `APP_LOG_DIR` | `/tmp` (OS temp dir) | Directory to store execution logs |
| `APP_NOTIFICATION_URI` | none | Notification configuration URI |
| `APP_DEBUG` | `false` | Output debug logs |
2018-07-06 14:08:51 +00:00
### Using command parameters:
| Parameter | Default | Description |
|----------|---------|-------------|
2018-07-23 08:57:48 +00:00
| `-l <address> or --listen <address>` | `:8080` | HTTP service address |
| `-p or --passwd <htpasswd file>` | `.htpasswd` | Password file for HTTP basic authentication
2018-07-23 08:57:48 +00:00
| `-d or --debug` | false | Output debug logs |
| `--nb-workers <workers>` | `2` | The number of workers to start |
| `--scripts <dir>` | `./scripts` | Scripts directory |
| `--timeout <timeout>` | `10` | Hook maximum delay before timeout (in second) |
| `--notification-uri <uri>` | | Notification configuration URI |
| `--log-dir <dir>` | `/tmp` | Directory to store execution logs |
2018-07-06 14:08:51 +00:00
2015-04-20 17:26:44 +00:00
## Usage
2014-09-21 20:00:55 +00:00
### Directory structure
Webhooks are simple scripts dispatched into a directory structure.
2014-09-21 20:00:55 +00:00
By default inside the `./scripts` directory.
You can override the default using the `APP_SCRIPTS_DIR` environment variable.
*Example:*
2014-09-21 20:00:55 +00:00
2015-04-20 17:26:44 +00:00
```
/scripts
|--> /github
|--> /build.sh
|--> /deploy.sh
|--> /ping.sh
|--> ...
2015-04-20 17:26:44 +00:00
```
2014-09-21 20:00:55 +00:00
### Webhook URL
2015-03-24 20:41:05 +00:00
The directory structure define the webhook URL.
If the script exists, the output the will be streamed to the HTTP response.
The streaming technology depends on the HTTP method used.
With `POST` the response will be chunked.
With `GET` the response will use [Server-sent events][sse].
[sse]: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events
*Example:*
The script: `./scripts/foo/bar.sh`
```bash
#!/bin/bash
echo "foo foo foo"
echo "bar bar bar"
2015-04-20 17:26:44 +00:00
```
2015-03-24 20:41:05 +00:00
Output using `POST` (`Chunked transfer encoding`):
```bash
$ curl -v -XPOST http://localhost:8080/foo/bar
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Transfer-Encoding: chunked
< X-Hook-Id: 7
foo foo foo
bar bar bar
done
```
Output using `GET` (`Server-sent events`):
```bash
$ curl -v -XGET http://localhost:8080/foo/bar
< HTTP/1.1 200 OK
< Content-Type: text/event-stream
< Transfer-Encoding: chunked
< X-Hook-Id: 8
data: foo foo foo
data: bar bar bar
2015-03-24 20:41:05 +00:00
data: done
```
2014-09-21 20:00:55 +00:00
### Webhook parameters
2014-09-21 20:00:55 +00:00
You have several way to provide parameters to your webhook script:
- URL query parameters and HTTP headers are converted into environment variables.
Variable names follows "snakecase" naming convention.
Therefore the name can be altered.
*ex: `CONTENT-TYPE` will become `content_type`.*
- When using `POST`, body content (text/plain or application/json) is transmit to the script as parameter.
2014-09-21 20:00:55 +00:00
*Example:*
2014-09-21 20:00:55 +00:00
The script:
2014-09-21 20:00:55 +00:00
```bash
#!/bin/bash
2014-09-21 20:00:55 +00:00
echo "Query parameter: foo=$foo"
echo "Header parameter: user-agent=$user_agent"
echo "Script parameters: $1"
2015-04-20 17:26:44 +00:00
```
2018-08-06 10:52:58 +00:00
The result:
```bash
$ curl --data @test.json http://localhost:8080/echo?foo=bar
Query parameter: foo=bar
Header parameter: user-agent=curl/7.52.1
Script parameter: {"foo": "bar"}
done
2015-04-20 17:26:44 +00:00
```
2014-09-21 20:00:55 +00:00
2018-01-09 09:18:16 +00:00
### Webhook timeout configuration
2018-08-06 10:52:58 +00:00
By default a webhook has a timeout of 10 seconds.
2018-01-09 09:18:16 +00:00
This timeout is globally configurable by setting the environment variable:
`APP_HOOK_TIMEOUT` (in seconds).
You can override this global behavior per request by setting the HTTP header:
`X-Hook-Timeout` (in seconds).
*Example:*
```bash
$ curl -H "X-Hook-Timeout: 5" http://localhost:8080/echo?foo=bar
```
### Webhook logs
As mentioned above, web hook logs are stream in real time during the call.
However, you can retrieve the logs of a previous call by using the hook ID: `http://localhost:8080/<NAME>/<ID>`
The hook ID is returned as an HTTP header with the Webhook response: `X-Hook-ID`
*Example:*
```bash
$ # Call webhook
$ curl -v http://localhost:8080/echo?foo=bar
...
< HTTP/1.1 200 OK
< Content-Type: text/event-stream
< X-Hook-Id: 2
...
$ # Retrieve logs afterwards
$ curl http://localhost:8080/echo/2
2018-01-09 09:18:16 +00:00
```
### Post hook notifications
2014-09-21 20:00:55 +00:00
The output of the script is collected and stored into a log file
(configured by the `APP_LOG_DIR` environment variable).
Once the script is executed, you can send the result and this log file to a notification channel.
Currently, only two channels are supported: `Email` and `HTTP`.
Notifications configuration can be done as follow:
```bash
$ export APP_NOTIFICATION_URI=http://requestb.in/v9b229v9
$ # or
$ webhookd --notification-uri=http://requestb.in/v9b229v9
```
Note that only the output of the script prefixed by "notify:" is sent to the notification channel.
If the output does not contain a prefixed line, no notification will be sent.
**Example:**
```bash
#!/bin/bash
echo "notify: Hello World" # Will be notified
echo "Goodbye" # Will not be notified
```
You can overide the notification prefix by adding `prefix` as a query parameter to the configuration URL.
**Example:** http://requestb.in/v9b229v9?prefix="foo:"
#### HTTP notification
Configuration URI: `http://example.org`
Options (using query parameters):
- `prefix`: Prefix to filter output log
The following JSON payload is POST to the target URL:
```json
{
"id": "42",
"name": "echo",
"text": "foo\nbar...\n",
"error": "Error cause... if present",
}
```
2014-09-21 20:00:55 +00:00
Note that because the payload have a `text` attribute, you can use a [Mattermost][mattermost] webhook endpoint.
2014-09-21 20:00:55 +00:00
[mattermost]: https://docs.mattermost.com/developer/webhooks-incoming.html
2014-09-21 20:00:55 +00:00
#### Email notification
Configuration URI: `mailto:foo@bar.com`
2014-09-21 20:00:55 +00:00
Options (using query parameters):
2014-09-21 20:00:55 +00:00
- `prefix`: Prefix to filter output log
- `smtp`: SMTP host to use (by default: `localhost:25`)
- `from`: Sender email (by default: `webhookd <noreply@nunux.org>`)
### Authentication
You can restrict access to webhooks using HTTP basic authentication.
To activate basic authentication, you have to create a `htpasswd` file:
```bash
$ # create passwd file the user 'api'
$ htpasswd -B -c .htpasswd api
```
This command will ask for a password and store it in the htpawsswd file.
Please note that by default, the daemon will try to load the `.htpasswd` file.
But you can override this behavior by specifying the location of the file:
```bash
$ APP_PASSWD_FILE=/etc/webhookd/users.htpasswd
$ # or
$ webhookd -p /etc/webhookd/users.htpasswd
```
Once configured, you must call webhooks using basic authentication:
```bash
$ curl -u api:test -XPOST "http://localhost:8080/echo?msg=hello"
```
---
2014-09-19 18:46:04 +00:00