mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-11 08:04:44 +00:00
Fix environment and argument passing
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.
This commit is contained in:
parent
a7aa7f2327
commit
d2e315d9c6
5 changed files with 97 additions and 17 deletions
17
hook/hook.go
17
hook/hook.go
|
@ -5,7 +5,6 @@ import (
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -31,8 +30,17 @@ const (
|
||||||
EnvNamespace string = "HOOK_"
|
EnvNamespace string = "HOOK_"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrInvalidPayloadSignature describes an invalid payload signature.
|
// SignatureError describes an invalid payload signature passed to Hook.
|
||||||
var ErrInvalidPayloadSignature = errors.New("invalid payload signature")
|
type SignatureError struct {
|
||||||
|
Signature string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SignatureError) Error() string {
|
||||||
|
if e == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("invalid payload signature %s", e.Signature)
|
||||||
|
}
|
||||||
|
|
||||||
// ArgumentError describes an invalid argument passed to Hook.
|
// ArgumentError describes an invalid argument passed to Hook.
|
||||||
type ArgumentError struct {
|
type ArgumentError struct {
|
||||||
|
@ -84,7 +92,7 @@ func CheckPayloadSignature(payload []byte, secret string, signature string) (str
|
||||||
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
|
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
|
||||||
err = ErrInvalidPayloadSignature
|
return expectedMAC, &SignatureError{expectedMAC}
|
||||||
}
|
}
|
||||||
return expectedMAC, err
|
return expectedMAC, err
|
||||||
}
|
}
|
||||||
|
@ -302,6 +310,7 @@ func (h *Hook) ExtractCommandArguments(headers, query, payload *map[string]inter
|
||||||
if arg, ok := h.PassArgumentsToCommand[i].Get(headers, query, payload); ok {
|
if arg, ok := h.PassArgumentsToCommand[i].Get(headers, query, payload); ok {
|
||||||
args = append(args, arg)
|
args = append(args, arg)
|
||||||
} else {
|
} else {
|
||||||
|
args = append(args, "")
|
||||||
return args, &ArgumentError{h.PassArgumentsToCommand[i]}
|
return args, &ArgumentError{h.PassArgumentsToCommand[i]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ var hookExtractCommandArgumentsTests = []struct {
|
||||||
}{
|
}{
|
||||||
{"test", []Argument{Argument{"header", "a"}}, &map[string]interface{}{"a": "z"}, nil, nil, []string{"test", "z"}, true},
|
{"test", []Argument{Argument{"header", "a"}}, &map[string]interface{}{"a": "z"}, nil, nil, []string{"test", "z"}, true},
|
||||||
// failures
|
// failures
|
||||||
{"fail", []Argument{Argument{"payload", "a"}}, &map[string]interface{}{"a": "z"}, nil, nil, []string{"fail"}, false},
|
{"fail", []Argument{Argument{"payload", "a"}}, &map[string]interface{}{"a": "z"}, nil, nil, []string{"fail", ""}, false},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHookExtractCommandArguments(t *testing.T) {
|
func TestHookExtractCommandArguments(t *testing.T) {
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"source": "payload",
|
"source": "payload",
|
||||||
"name": "pusher.email"
|
"name": "head_commit.timestamp"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"pass-arguments-to-command":
|
"pass-arguments-to-command":
|
||||||
|
@ -19,11 +19,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"source": "payload",
|
"source": "payload",
|
||||||
"name": "pusher.name"
|
"name": "head_commit.author.email"
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": "payload",
|
|
||||||
"name": "pusher.email"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"trigger-rule":
|
"trigger-rule":
|
||||||
|
|
10
webhook.go
10
webhook.go
|
@ -238,16 +238,16 @@ func handleHook(h *hook.Hook, headers, query, payload *map[string]interface{}, b
|
||||||
cmd.Args, err = h.ExtractCommandArguments(headers, query, payload)
|
cmd.Args, err = h.ExtractCommandArguments(headers, query, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error extracting command arguments: %s", err)
|
log.Printf("error extracting command arguments: %s", err)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Env, err = h.ExtractCommandArgumentsForEnv(headers, query, payload)
|
var envs []string
|
||||||
|
envs, err = h.ExtractCommandArgumentsForEnv(headers, query, payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error extracting command arguments: %s", err)
|
log.Printf("error extracting command arguments for environment: %s", err)
|
||||||
return ""
|
|
||||||
}
|
}
|
||||||
|
cmd.Env = append(os.Environ(), envs...)
|
||||||
|
|
||||||
log.Printf("executing %s (%s) with arguments %s and environment %s using %s as cwd\n", h.ExecuteCommand, cmd.Path, cmd.Args, cmd.Env, cmd.Dir)
|
log.Printf("executing %s (%s) with arguments %q and environment %s using %s as cwd\n", h.ExecuteCommand, cmd.Path, cmd.Args, envs, cmd.Dir)
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.CombinedOutput()
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ var hookHandlerTests = []struct {
|
||||||
}`,
|
}`,
|
||||||
false,
|
false,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb Garen Torikian lolwut@noway.biz\nenv: HOOK_pusher.email=lolwut@noway.biz\n"}`,
|
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\nenv: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00\n"}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bitbucket", // bitbucket sends their payload using uriencoded params.
|
"bitbucket", // bitbucket sends their payload using uriencoded params.
|
||||||
|
@ -434,5 +434,80 @@ var hookHandlerTests = []struct {
|
||||||
`{"message":"success","output":"arg: b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327 John Smith john@example.com\n"}`,
|
`{"message":"success","output":"arg: b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327 John Smith john@example.com\n"}`,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"missing-cmd-arg", // missing head_commit.author.email
|
||||||
|
"github",
|
||||||
|
map[string]string{"X-Hub-Signature": "ab03955b9377f530aa298b1b6d273ae9a47e1e40"},
|
||||||
|
`{
|
||||||
|
"head_commit":{
|
||||||
|
"added":[
|
||||||
|
"words/madame-bovary.txt"
|
||||||
|
],
|
||||||
|
"author":{
|
||||||
|
"email":"lolwut@noway.biz",
|
||||||
|
"name":"Garen Torikian",
|
||||||
|
"username":"octokitty"
|
||||||
|
},
|
||||||
|
"committer":{
|
||||||
|
"email":"lolwut@noway.biz",
|
||||||
|
"name":"Garen Torikian",
|
||||||
|
"username":"octokitty"
|
||||||
|
},
|
||||||
|
"distinct":true,
|
||||||
|
"id":"1481a2de7b2a7d02428ad93446ab166be7793fbb",
|
||||||
|
"message":"Rename madame-bovary.txt to words/madame-bovary.txt",
|
||||||
|
"modified":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"removed":[
|
||||||
|
"madame-bovary.txt"
|
||||||
|
],
|
||||||
|
"timestamp":"2013-03-12T08:14:29-07:00",
|
||||||
|
"url":"https://github.com/octokitty/testing/commit/1481a2de7b2a7d02428ad93446ab166be7793fbb"
|
||||||
|
},
|
||||||
|
"ref":"refs/heads/master"
|
||||||
|
}`,
|
||||||
|
false,
|
||||||
|
http.StatusOK,
|
||||||
|
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\nenv: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00\n"}`,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
"missing-env-arg", // missing head_commit.timestamp
|
||||||
|
"github",
|
||||||
|
map[string]string{"X-Hub-Signature": "2cf8b878cb6b74a25090a140fa4a474be04b97fa"},
|
||||||
|
`{
|
||||||
|
"head_commit":{
|
||||||
|
"added":[
|
||||||
|
"words/madame-bovary.txt"
|
||||||
|
],
|
||||||
|
"author":{
|
||||||
|
"email":"lolwut@noway.biz",
|
||||||
|
"name":"Garen Torikian",
|
||||||
|
"username":"octokitty"
|
||||||
|
},
|
||||||
|
"committer":{
|
||||||
|
"email":"lolwut@noway.biz",
|
||||||
|
"name":"Garen Torikian",
|
||||||
|
"username":"octokitty"
|
||||||
|
},
|
||||||
|
"distinct":true,
|
||||||
|
"id":"1481a2de7b2a7d02428ad93446ab166be7793fbb",
|
||||||
|
"message":"Rename madame-bovary.txt to words/madame-bovary.txt",
|
||||||
|
"modified":[
|
||||||
|
|
||||||
|
],
|
||||||
|
"removed":[
|
||||||
|
"madame-bovary.txt"
|
||||||
|
],
|
||||||
|
"url":"https://github.com/octokitty/testing/commit/1481a2de7b2a7d02428ad93446ab166be7793fbb"
|
||||||
|
},
|
||||||
|
"ref":"refs/heads/master"
|
||||||
|
}`,
|
||||||
|
false,
|
||||||
|
http.StatusOK,
|
||||||
|
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\n"}`,
|
||||||
|
},
|
||||||
|
|
||||||
{"empty payload", "github", nil, `{}`, false, http.StatusOK, `Hook rules were not satisfied.`},
|
{"empty payload", "github", nil, `{}`, false, http.StatusOK, `Hook rules were not satisfied.`},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue