mirror of
https://github.com/adnanh/webhook.git
synced 2026-07-26 17:19:17 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f83af97138 | |||
| 5a96a5721a | |||
| 37b310feaa | |||
| ad76b51e6a | |||
| 4304aaa2d5 | |||
| a2fac2373b | |||
| c9adceb5d8 | |||
| 8488d3c432 | |||
| d3f5da5489 | |||
| 59b4954845 | |||
| 36aea82855 | |||
| 652109d46e |
@@ -47,12 +47,15 @@ It will start up on default port 9000 and will provide you with one HTTP endpoin
|
|||||||
http://yourserver:9000/hooks/redeploy-webhook
|
http://yourserver:9000/hooks/redeploy-webhook
|
||||||
```
|
```
|
||||||
|
|
||||||
Check [webhook parameters page](https://github.com/adnanh/webhook/wiki/Webhook-Parameters) to see how to override the ip, port and other settings when starting the [webhook](https://github.com/adnanh/webhook/).
|
Check [webhook parameters page](https://github.com/adnanh/webhook/wiki/Webhook-Parameters) to see how to override the ip, port and other settings such as hook hotreload, verbose output, etc, when starting the [webhook](https://github.com/adnanh/webhook/).
|
||||||
|
|
||||||
By performing a simple HTTP GET or POST request to that endpoint, your specified redeploy script would be executed. Neat!
|
By performing a simple HTTP GET or POST request to that endpoint, your specified redeploy script would be executed. Neat!
|
||||||
|
|
||||||
However, hook defined like that could pose a security threat to your system, because anyone who knows your endpoint, can send a request and execute your command. To prevent that, you can use the `"trigger-rule"` property for your hook, to specify the exact circumstances under which the hook would be triggered. For example, you can use them to add a secret that you must supply as a parameter in order to successfully trigger the hook. Please check out the [Hook rules page](https://github.com/adnanh/webhook/wiki/Hook-Rules) for detailed list of available rules and their usage.
|
However, hook defined like that could pose a security threat to your system, because anyone who knows your endpoint, can send a request and execute your command. To prevent that, you can use the `"trigger-rule"` property for your hook, to specify the exact circumstances under which the hook would be triggered. For example, you can use them to add a secret that you must supply as a parameter in order to successfully trigger the hook. Please check out the [Hook rules page](https://github.com/adnanh/webhook/wiki/Hook-Rules) for detailed list of available rules and their usage.
|
||||||
|
|
||||||
|
# Using HTTPS
|
||||||
|
[webhook](https://github.com/adnanh/webhook/) by default serves hooks using http. If you want [webhook](https://github.com/adnanh/webhook/) to serve secure content using https, you can use the `-secure` flag while starting [webhook](https://github.com/adnanh/webhook/). Files containing a certificate and matching private key for the server must be provided using the `-cert /path/to/cert.pem` and `-key /path/to/key.pem` flags. If the certificate is signed by a certificate authority, the cert file should be the concatenation of the server's certificate followed by the CA's certificate.
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
Check out [Hook examples page](https://github.com/adnanh/webhook/wiki/Hook-Examples) for more complex examples of hooks.
|
Check out [Hook examples page](https://github.com/adnanh/webhook/wiki/Hook-Examples) for more complex examples of hooks.
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ type Hook struct {
|
|||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
ExecuteCommand string `json:"execute-command"`
|
ExecuteCommand string `json:"execute-command"`
|
||||||
CommandWorkingDirectory string `json:"command-working-directory"`
|
CommandWorkingDirectory string `json:"command-working-directory"`
|
||||||
|
ResponseMessage string `json:"response-message"`
|
||||||
PassArgumentsToCommand []Argument `json:"pass-arguments-to-command"`
|
PassArgumentsToCommand []Argument `json:"pass-arguments-to-command"`
|
||||||
TriggerRule *Rules `json:"trigger-rule"`
|
TriggerRule *Rules `json:"trigger-rule"`
|
||||||
}
|
}
|
||||||
|
|||||||
+87
-12
@@ -17,17 +17,26 @@ import (
|
|||||||
|
|
||||||
"github.com/codegangsta/negroni"
|
"github.com/codegangsta/negroni"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
|
||||||
|
fsnotify "gopkg.in/fsnotify.v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "2.0.0"
|
version = "2.2.2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ip = flag.String("ip", "", "ip the webhook should serve hooks on")
|
ip = flag.String("ip", "", "ip the webhook should serve hooks on")
|
||||||
port = flag.Int("port", 9000, "port the webhook should serve hooks on")
|
port = flag.Int("port", 9000, "port the webhook should serve hooks on")
|
||||||
verbose = flag.Bool("verbose", false, "show verbose output")
|
verbose = flag.Bool("verbose", false, "show verbose output")
|
||||||
hooksFilePath = flag.String("hooks", "hooks.json", "path to the json file containing defined hooks the webhook should serve")
|
hotReload = flag.Bool("hotreload", false, "watch hooks file for changes and reload them automatically")
|
||||||
|
hooksFilePath = flag.String("hooks", "hooks.json", "path to the json file containing defined hooks the webhook should serve")
|
||||||
|
hooksURLPrefix = flag.String("urlprefix", "hooks", "url prefix to use for served hooks (protocol://yourserver:port/PREFIX/:hook-id)")
|
||||||
|
secure = flag.Bool("secure", false, "use HTTPS instead of HTTP")
|
||||||
|
cert = flag.String("cert", "cert.pem", "path to the HTTPS certificate pem file")
|
||||||
|
key = flag.String("key", "key.pem", "path to the HTTPS certificate private key pem file")
|
||||||
|
|
||||||
|
watcher *fsnotify.Watcher
|
||||||
|
|
||||||
hooks hook.Hooks
|
hooks hook.Hooks
|
||||||
)
|
)
|
||||||
@@ -60,11 +69,30 @@ func init() {
|
|||||||
log.Printf("\t> %s\n", hook.ID)
|
log.Printf("\t> %s\n", hook.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// set up file watcher
|
|
||||||
//log.Printf("setting up file watcher for %s\n", *hooksFilePath)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
if *hotReload {
|
||||||
|
// set up file watcher
|
||||||
|
log.Printf("setting up file watcher for %s\n", *hooksFilePath)
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
watcher, err = fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error creating file watcher instance", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
go watchForFileChange()
|
||||||
|
|
||||||
|
err = watcher.Add(*hooksFilePath)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("error adding hooks file to the watcher", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
l := log.New(os.Stdout, "[webhook] ", log.Ldate|log.Ltime)
|
l := log.New(os.Stdout, "[webhook] ", log.Ldate|log.Ltime)
|
||||||
|
|
||||||
negroniLogger := &negroni.Logger{l}
|
negroniLogger := &negroni.Logger{l}
|
||||||
@@ -79,13 +107,27 @@ func main() {
|
|||||||
n := negroni.New(negroniRecovery, negroniLogger)
|
n := negroni.New(negroniRecovery, negroniLogger)
|
||||||
|
|
||||||
router := mux.NewRouter()
|
router := mux.NewRouter()
|
||||||
router.HandleFunc("/hooks/{id}", hookHandler)
|
|
||||||
|
var hooksURL string
|
||||||
|
|
||||||
|
if *hooksURLPrefix == "" {
|
||||||
|
hooksURL = "/{id}"
|
||||||
|
} else {
|
||||||
|
hooksURL = "/" + *hooksURLPrefix + "/{id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
router.HandleFunc(hooksURL, hookHandler)
|
||||||
|
|
||||||
n.UseHandler(router)
|
n.UseHandler(router)
|
||||||
|
|
||||||
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))
|
if *secure {
|
||||||
|
log.Printf("starting secure (https) webhook on %s:%d", *ip, *port)
|
||||||
|
log.Fatal(http.ListenAndServeTLS(fmt.Sprintf("%s:%d", *ip, *port), *cert, *key, n))
|
||||||
|
} else {
|
||||||
|
log.Printf("starting insecure (http) webhook on %s:%d", *ip, *port)
|
||||||
|
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))
|
||||||
|
}
|
||||||
|
|
||||||
log.Printf("listening on %s:%d", *ip, *port)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -133,9 +175,10 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
// handle hook
|
// handle hook
|
||||||
go handleHook(hook, &headers, &query, &payload, &body)
|
go handleHook(hook, &headers, &query, &payload, &body)
|
||||||
|
|
||||||
// say thanks
|
// send the hook defined response message
|
||||||
fmt.Fprintf(w, "Thanks.")
|
fmt.Fprintf(w, hook.ResponseMessage)
|
||||||
} else {
|
} else {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
fmt.Fprintf(w, "Hook not found.")
|
fmt.Fprintf(w, "Hook not found.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,3 +205,35 @@ func handleHook(hook *hook.Hook, headers, query, payload *map[string]interface{}
|
|||||||
log.Printf("%s hook did not get triggered\n", hook.ID)
|
log.Printf("%s hook did not get triggered\n", hook.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func watchForFileChange() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event := <-(*watcher).Events:
|
||||||
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
log.Println("hooks file modified")
|
||||||
|
|
||||||
|
newHooks := hook.Hooks{}
|
||||||
|
|
||||||
|
// parse and swap
|
||||||
|
log.Printf("attempting to reload hooks from %s\n", *hooksFilePath)
|
||||||
|
|
||||||
|
err := newHooks.LoadFromFile(*hooksFilePath)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("couldn't load hooks from file! %+v\n", err)
|
||||||
|
} else {
|
||||||
|
log.Printf("loaded %d hook(s) from file\n", len(hooks))
|
||||||
|
|
||||||
|
for _, hook := range hooks {
|
||||||
|
log.Printf("\t> %s\n", hook.ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks = newHooks
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case err := <-(*watcher).Errors:
|
||||||
|
log.Println("watcher error:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user