diff --git a/hook/hook.go b/hook/hook.go index 2d2c70a..98fb975 100644 --- a/hook/hook.go +++ b/hook/hook.go @@ -162,7 +162,6 @@ func CheckScalrSignature(headers map[string]interface{}, body []byte, signingKey } // Example format: Fri 08 Sep 2017 11:24:32 UTC date, err := time.Parse("Mon 02 Jan 2006 15:04:05 MST", dateHeader) - //date, err := time.Parse(time.RFC1123, dateHeader) if err != nil { return false, err } @@ -185,6 +184,7 @@ func CheckIPWhitelist(remoteAddr string, ipRange string) (bool, error) { if i := strings.LastIndex(ip, ":"); i != -1 { ip = ip[:i] + ip = strings.Trim(ip, " []") } parsedIP := net.ParseIP(ip) @@ -222,7 +222,6 @@ func ReplaceParameter(s string, params interface{}, value interface{}) bool { if paramsValue := reflect.ValueOf(params); paramsValue.Kind() == reflect.Slice { if paramsValueSliceLength := paramsValue.Len(); paramsValueSliceLength > 0 { - if p := strings.SplitN(s, ".", 2); len(p) > 1 { index, err := strconv.ParseUint(p[0], 10, 64) @@ -257,8 +256,12 @@ func GetParameter(s string, params interface{}) (interface{}, bool) { return nil, false } - if paramsValue := reflect.ValueOf(params); paramsValue.Kind() == reflect.Slice { - if paramsValueSliceLength := paramsValue.Len(); paramsValueSliceLength > 0 { + paramsValue := reflect.ValueOf(params) + + switch paramsValue.Kind() { + case reflect.Slice: + paramsValueSliceLength := paramsValue.Len() + if paramsValueSliceLength > 0 { if p := strings.SplitN(s, ".", 2); len(p) > 1 { index, err := strconv.ParseUint(p[0], 10, 64) @@ -280,18 +283,20 @@ func GetParameter(s string, params interface{}) (interface{}, bool) { } return nil, false - } - if p := strings.SplitN(s, ".", 2); len(p) > 1 { - if paramsValue := reflect.ValueOf(params); paramsValue.Kind() == reflect.Map { - if pValue, ok := params.(map[string]interface{})[p[0]]; ok { + case reflect.Map: + // Check for raw key + if v, ok := params.(map[string]interface{})[s]; ok { + return v, true + } + + // Checked for dotted references + p := strings.SplitN(s, ".", 2) + if pValue, ok := params.(map[string]interface{})[p[0]]; ok { + if len(p) > 1 { return GetParameter(p[1], pValue) } - } else { - return nil, false - } - } else { - if pValue, ok := params.(map[string]interface{})[p[0]]; ok { + return pValue, true } } @@ -334,7 +339,6 @@ func (ha *Argument) Get(headers, query, payload *map[string]interface{}) (string return ha.Name, true case SourceEntirePayload: r, err := json.Marshal(payload) - if err != nil { return "", false } @@ -342,7 +346,6 @@ func (ha *Argument) Get(headers, query, payload *map[string]interface{}) (string return string(r), true case SourceEntireHeaders: r, err := json.Marshal(headers) - if err != nil { return "", false } @@ -350,7 +353,6 @@ func (ha *Argument) Get(headers, query, payload *map[string]interface{}) (string return string(r), true case SourceEntireQuery: r, err := json.Marshal(query) - if err != nil { return "", false } @@ -440,7 +442,7 @@ type Hook struct { // ParseJSONParameters decodes specified arguments to JSON objects and replaces the // string with the newly created object func (h *Hook) ParseJSONParameters(headers, query, payload *map[string]interface{}) []error { - var errors = make([]error, 0) + errors := make([]error, 0) for i := range h.JSONStringParameters { if arg, ok := h.JSONStringParameters[i].Get(headers, query, payload); ok { @@ -450,7 +452,6 @@ func (h *Hook) ParseJSONParameters(headers, query, payload *map[string]interface decoder.UseNumber() err := decoder.Decode(&newArg) - if err != nil { errors = append(errors, &ParseError{err}) continue @@ -493,8 +494,8 @@ func (h *Hook) ParseJSONParameters(headers, query, payload *map[string]interface // ExtractCommandArguments creates a list of arguments, based on the // PassArgumentsToCommand property that is ready to be used with exec.Command() func (h *Hook) ExtractCommandArguments(headers, query, payload *map[string]interface{}) ([]string, []error) { - var args = make([]string, 0) - var errors = make([]error, 0) + args := make([]string, 0) + errors := make([]error, 0) args = append(args, h.ExecuteCommand) @@ -518,8 +519,8 @@ func (h *Hook) ExtractCommandArguments(headers, query, payload *map[string]inter // format, based on the PassEnvironmentToCommand property that is ready to be used // with exec.Command(). func (h *Hook) ExtractCommandArgumentsForEnv(headers, query, payload *map[string]interface{}) ([]string, []error) { - var args = make([]string, 0) - var errors = make([]error, 0) + args := make([]string, 0) + errors := make([]error, 0) for i := range h.PassEnvironmentToCommand { if arg, ok := h.PassEnvironmentToCommand[i].Get(headers, query, payload); ok { if h.PassEnvironmentToCommand[i].EnvName != "" { @@ -552,8 +553,8 @@ type FileParameter struct { // format, based on the PassFileToCommand property that is ready to be used // with exec.Command(). func (h *Hook) ExtractCommandArgumentsForFile(headers, query, payload *map[string]interface{}) ([]FileParameter, []error) { - var args = make([]FileParameter, 0) - var errors = make([]error, 0) + args := make([]FileParameter, 0) + errors := make([]error, 0) for i := range h.PassFileToCommand { if arg, ok := h.PassFileToCommand[i].Get(headers, query, payload); ok { diff --git a/hook/hook_test.go b/hook/hook_test.go index e6bfce2..e8a98bb 100644 --- a/hook/hook_test.go +++ b/hook/hook_test.go @@ -7,6 +7,38 @@ import ( "testing" ) +func TestGetParameter(t *testing.T) { + for _, test := range []struct { + key string + val interface{} + expect interface{} + ok bool + }{ + // True + {"a", map[string]interface{}{"a": "1"}, "1", true}, + {"a.b", map[string]interface{}{"a.b": "1"}, "1", true}, + {"a.c", map[string]interface{}{"a": map[string]interface{}{"c": 2}}, 2, true}, + {"a.1", map[string]interface{}{"a": map[string]interface{}{"1": 3}}, 3, true}, + {"a.1", map[string]interface{}{"a": []interface{}{"a", "b"}}, "b", true}, + {"0", []interface{}{"a", "b"}, "a", true}, + + // False + {"z", map[string]interface{}{"a": "1"}, nil, false}, + {"a.z", map[string]interface{}{"a": map[string]interface{}{"b": 2}}, nil, false}, + {"z.b", map[string]interface{}{"a": map[string]interface{}{"z": 2}}, nil, false}, + {"a.2", map[string]interface{}{"a": []interface{}{"a", "b"}}, nil, false}, + } { + res, ok := GetParameter(test.key, test.val) + if ok != test.ok { + t.Errorf("unexpected result given {%q, %q}: %t\n", test.key, test.val, ok) + } + + if !reflect.DeepEqual(res, test.expect) { + t.Errorf("failed given {%q, %q}:\nexpected {%#v}\ngot {%#v}\n", test.key, test.val, test.expect, res) + } + } +} + var checkPayloadSignatureTests = []struct { payload []byte secret string