mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-10 23:54:42 +00:00
Transition payload hash option names to hmac
The payload-hash-* options are imprecisely named. Clarify their function as HMAC validations by renaming them. The existing options will continue to work but are deprecated. Log a warning if the old options are used. All tests, examples, and documentation are updated. Fixes #289
This commit is contained in:
parent
6797bf7cf7
commit
6bbf14f7d9
11 changed files with 47 additions and 28 deletions
|
@ -46,7 +46,7 @@ This page is still work in progress. Feel free to contribute!
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "mysecret",
|
"secret": "mysecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
@ -166,7 +166,7 @@ Values in the request body can be accessed in the command or to the match rule b
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha256",
|
"type": "payload-hmac-sha256",
|
||||||
"secret": "mysecret",
|
"secret": "mysecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
* [Match](#match)
|
* [Match](#match)
|
||||||
* [Match value](#match-value)
|
* [Match value](#match-value)
|
||||||
* [Match regex](#match-regex)
|
* [Match regex](#match-regex)
|
||||||
* [Match payload-hash-sha1](#match-payload-hash-sha1)
|
* [Match payload-hmac-sha1](#match-payload-hmac-sha1)
|
||||||
* [Match payload-hash-sha256](#match-payload-hash-sha256)
|
* [Match payload-hmac-sha256](#match-payload-hmac-sha256)
|
||||||
* [Match payload-hash-sha512](#match-payload-hash-sha512)
|
* [Match payload-hmac-sha512](#match-payload-hmac-sha512)
|
||||||
* [Match Whitelisted IP range](#match-whitelisted-ip-range)
|
* [Match Whitelisted IP range](#match-whitelisted-ip-range)
|
||||||
* [Match scalr-signature](#match-scalr-signature)
|
* [Match scalr-signature](#match-scalr-signature)
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@
|
||||||
"source": "header",
|
"source": "header",
|
||||||
"name": "X-Hub-Signature"
|
"name": "X-Hub-Signature"
|
||||||
},
|
},
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "mysecret"
|
"secret": "mysecret"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -150,9 +150,7 @@
|
||||||
|
|
||||||
*Please note:* Due to technical reasons, _number_ and _boolean_ values in the _match rule_ must be wrapped around with a pair of quotes.
|
*Please note:* Due to technical reasons, _number_ and _boolean_ values in the _match rule_ must be wrapped around with a pair of quotes.
|
||||||
|
|
||||||
There are three different match rules:
|
### Match value
|
||||||
|
|
||||||
### 1. Match value
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
|
@ -168,7 +166,7 @@ There are three different match rules:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Match regex
|
### Match regex
|
||||||
For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
|
For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -185,12 +183,13 @@ For the regex syntax, check out <http://golang.org/pkg/regexp/syntax/>
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. Match payload-hash-sha1
|
### Match payload-hmac-sha1
|
||||||
|
Validate the HMAC of the payload using the SHA1 hash and the given *secret*.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "yoursecret",
|
"secret": "yoursecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
@ -208,12 +207,13 @@ will be tried unless a match is found. For example:
|
||||||
X-Hub-Signature: sha1=the-first-signature,sha1=the-second-signature
|
X-Hub-Signature: sha1=the-first-signature,sha1=the-second-signature
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Match payload-hash-sha256
|
### Match payload-hmac-sha256
|
||||||
|
Validate the HMAC of the payload using the SHA256 hash and the given *secret*.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha256",
|
"type": "payload-hmac-sha256",
|
||||||
"secret": "yoursecret",
|
"secret": "yoursecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
@ -231,12 +231,13 @@ will be tried unless a match is found. For example:
|
||||||
X-Hub-Signature: sha256=the-first-signature,sha256=the-second-signature
|
X-Hub-Signature: sha256=the-first-signature,sha256=the-second-signature
|
||||||
```
|
```
|
||||||
|
|
||||||
### 5. Match payload-hash-sha512
|
### Match payload-hmac-sha512
|
||||||
|
Validate the HMAC of the payload using the SHA512 hash and the given *secret*.
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha512",
|
"type": "payload-hmac-sha512",
|
||||||
"secret": "yoursecret",
|
"secret": "yoursecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
@ -254,7 +255,7 @@ will be tried unless a match is found. For example:
|
||||||
X-Hub-Signature: sha512=the-first-signature,sha512=the-second-signature
|
X-Hub-Signature: sha512=the-first-signature,sha512=the-second-signature
|
||||||
```
|
```
|
||||||
|
|
||||||
### 6. Match Whitelisted IP range
|
### Match Whitelisted IP range
|
||||||
|
|
||||||
The IP can be IPv4- or IPv6-formatted, using [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_blocks). To match a single IP address only, use `/32`.
|
The IP can be IPv4- or IPv6-formatted, using [CIDR notation](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing#CIDR_blocks). To match a single IP address only, use `/32`.
|
||||||
|
|
||||||
|
@ -268,7 +269,7 @@ The IP can be IPv4- or IPv6-formatted, using [CIDR notation](https://en.wikipedi
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 7. Match scalr-signature
|
### Match scalr-signature
|
||||||
|
|
||||||
The trigger rule checks the scalr signature and also checks that the request was signed less than 5 minutes before it was received.
|
The trigger rule checks the scalr signature and also checks that the request was signed less than 5 minutes before it was received.
|
||||||
A unqiue signing key is generated for each webhook endpoint URL you register in Scalr.
|
A unqiue signing key is generated for each webhook endpoint URL you register in Scalr.
|
||||||
|
|
|
@ -6,7 +6,7 @@ In additional to the [built-in Go template functions and features][tt], `webhook
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
In the example `hooks.json` file below, the `payload-hash-sha1` matching rule looks up the secret hash from the environment using the `getenv` template function.
|
In the example `hooks.json` file below, the `payload-hmac-sha1` matching rule looks up the HMAC secret from the environment using the `getenv` template function.
|
||||||
Additionally, the result is piped through the built-in Go template function `js` to ensure that the result is a well-formed Javascript/JSON string.
|
Additionally, the result is piped through the built-in Go template function `js` to ensure that the result is a well-formed Javascript/JSON string.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -44,7 +44,7 @@ Additionally, the result is piped through the built-in Go template function `js`
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "{{ getenv "XXXTEST_SECRET" | js }}",
|
"secret": "{{ getenv "XXXTEST_SECRET" | js }}",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "mysecret",
|
"secret": "mysecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "{{ getenv "XXXTEST_SECRET" | js }}",
|
"secret": "{{ getenv "XXXTEST_SECRET" | js }}",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
trigger-rule:
|
trigger-rule:
|
||||||
and:
|
and:
|
||||||
- match:
|
- match:
|
||||||
type: payload-hash-sha1
|
type: payload-hmac-sha1
|
||||||
secret: mysecret
|
secret: mysecret
|
||||||
parameter:
|
parameter:
|
||||||
source: header
|
source: header
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
trigger-rule:
|
trigger-rule:
|
||||||
and:
|
and:
|
||||||
- match:
|
- match:
|
||||||
type: payload-hash-sha1
|
type: payload-hmac-sha1
|
||||||
secret: "{{ getenv "XXXTEST_SECRET" | js }}"
|
secret: "{{ getenv "XXXTEST_SECRET" | js }}"
|
||||||
parameter:
|
parameter:
|
||||||
source: header
|
source: header
|
||||||
|
|
|
@ -883,6 +883,9 @@ type MatchRule struct {
|
||||||
const (
|
const (
|
||||||
MatchValue string = "value"
|
MatchValue string = "value"
|
||||||
MatchRegex string = "regex"
|
MatchRegex string = "regex"
|
||||||
|
MatchHMACSHA1 string = "payload-hmac-sha1"
|
||||||
|
MatchHMACSHA256 string = "payload-hmac-sha256"
|
||||||
|
MatchHMACSHA512 string = "payload-hmac-sha512"
|
||||||
MatchHashSHA1 string = "payload-hash-sha1"
|
MatchHashSHA1 string = "payload-hash-sha1"
|
||||||
MatchHashSHA256 string = "payload-hash-sha256"
|
MatchHashSHA256 string = "payload-hash-sha256"
|
||||||
MatchHashSHA512 string = "payload-hash-sha512"
|
MatchHashSHA512 string = "payload-hash-sha512"
|
||||||
|
@ -907,12 +910,21 @@ func (r MatchRule) Evaluate(req *Request) (bool, error) {
|
||||||
case MatchRegex:
|
case MatchRegex:
|
||||||
return regexp.MatchString(r.Regex, arg)
|
return regexp.MatchString(r.Regex, arg)
|
||||||
case MatchHashSHA1:
|
case MatchHashSHA1:
|
||||||
|
log.Print(`warn: use of deprecated option payload-hash-sha1; use payload-hmac-sha1 instead`)
|
||||||
|
fallthrough
|
||||||
|
case MatchHMACSHA1:
|
||||||
_, err := CheckPayloadSignature(req.Body, r.Secret, arg)
|
_, err := CheckPayloadSignature(req.Body, r.Secret, arg)
|
||||||
return err == nil, err
|
return err == nil, err
|
||||||
case MatchHashSHA256:
|
case MatchHashSHA256:
|
||||||
|
log.Print(`warn: use of deprecated option payload-hash-sha256: use payload-hmac-sha256 instead`)
|
||||||
|
fallthrough
|
||||||
|
case MatchHMACSHA256:
|
||||||
_, err := CheckPayloadSignature256(req.Body, r.Secret, arg)
|
_, err := CheckPayloadSignature256(req.Body, r.Secret, arg)
|
||||||
return err == nil, err
|
return err == nil, err
|
||||||
case MatchHashSHA512:
|
case MatchHashSHA512:
|
||||||
|
log.Print(`warn: use of deprecated option payload-hash-sha512: use payload-hmac-sha512 instead`)
|
||||||
|
fallthrough
|
||||||
|
case MatchHMACSHA512:
|
||||||
_, err := CheckPayloadSignature512(req.Body, r.Secret, arg)
|
_, err := CheckPayloadSignature512(req.Body, r.Secret, arg)
|
||||||
return err == nil, err
|
return err == nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -487,7 +487,9 @@ var matchRuleTests = []struct {
|
||||||
}{
|
}{
|
||||||
{"value", "", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
{"value", "", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
||||||
{"regex", "^z", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
{"regex", "^z", "", "z", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", true, false},
|
||||||
|
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "b17e04cbb22afa8ffbff8796fc1894ed27badd9e"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
|
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "f417af3a21bd70379b5796d5f013915e7029f62c580fb0f500f59a35a6f04c89"}, nil, nil, []byte(`{"a": "z"}`), "", true, false},
|
||||||
// failures
|
// failures
|
||||||
{"value", "", "", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
{"value", "", "", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, false},
|
||||||
|
@ -495,8 +497,12 @@ var matchRuleTests = []struct {
|
||||||
{"value", "", "2", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"Y": "z"}, nil, nil, []byte{}, "", false, true}, // reference invalid header
|
{"value", "", "2", "X", "", Argument{"header", "a", "", false}, map[string]interface{}{"Y": "z"}, nil, nil, []byte{}, "", false, true}, // reference invalid header
|
||||||
// errors
|
// errors
|
||||||
{"regex", "*", "", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, true}, // invalid regex
|
{"regex", "*", "", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": "z"}, nil, nil, []byte{}, "", false, true}, // invalid regex
|
||||||
|
{"payload-hmac-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hash-sha1", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
|
{"payload-hmac-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
{"payload-hash-sha256", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
|
{"payload-hmac-sha512", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
|
{"payload-hash-sha512", "", "secret", "", "", Argument{"header", "a", "", false}, map[string]interface{}{"A": ""}, nil, nil, []byte{}, "", false, true}, // invalid hmac
|
||||||
// IP whitelisting, valid cases
|
// IP whitelisting, valid cases
|
||||||
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
||||||
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
{"ip-whitelist", "", "", "", "192.168.0.1/24", Argument{}, nil, nil, nil, []byte{}, "192.168.0.2:9000", true, false}, // valid IPv4, with range
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "mysecret",
|
"secret": "mysecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
@ -288,7 +288,7 @@
|
||||||
{
|
{
|
||||||
"match":
|
"match":
|
||||||
{
|
{
|
||||||
"type": "payload-hash-sha1",
|
"type": "payload-hmac-sha1",
|
||||||
"secret": "mysecret",
|
"secret": "mysecret",
|
||||||
"parameter":
|
"parameter":
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
source: header
|
source: header
|
||||||
name: X-Hub-Signature
|
name: X-Hub-Signature
|
||||||
secret: mysecret
|
secret: mysecret
|
||||||
type: payload-hash-sha1
|
type: payload-hmac-sha1
|
||||||
- match:
|
- match:
|
||||||
parameter:
|
parameter:
|
||||||
source: payload
|
source: payload
|
||||||
|
@ -174,4 +174,4 @@
|
||||||
source: header
|
source: header
|
||||||
name: X-Hub-Signature
|
name: X-Hub-Signature
|
||||||
secret: mysecret
|
secret: mysecret
|
||||||
type: payload-hash-sha1
|
type: payload-hmac-sha1
|
||||||
|
|
Loading…
Add table
Reference in a new issue