-
Notifications
You must be signed in to change notification settings - Fork 745
/
payloadserver.go
69 lines (62 loc) · 1.68 KB
/
payloadserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Simple payload server for Github hooks. Payload is the http handler.
// For instructions on deploying as a Google Cloud Function, see README.rst
//
// Eli Bendersky [https://eli.thegreenplace.net]
// This code is in the public domain.
package payloadserver
import (
"crypto/hmac"
"crypto/sha1"
"encoding/hex"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
"strings"
)
// checkMAC reports whether messageMAC is a valid HMAC tag for message.
func checkMAC(message, messageMAC, key []byte) bool {
mac := hmac.New(sha1.New, key)
mac.Write(message)
expectedMAC := mac.Sum(nil)
return hmac.Equal(messageMAC, expectedMAC)
}
// validateSignature validates the MAC signature in the request header using
// the secret key and the message body. Returns true iff valid.
func validateSignature(body []byte, r *http.Request) bool {
sigHeader := r.Header["X-Hub-Signature"]
if len(sigHeader) < 1 {
log.Println("signature header too short")
return false
}
parts := strings.Split(sigHeader[0], "=")
if len(parts) != 2 || parts[0] != "sha1" {
log.Println("Expected signature header 'sha1=XXXXX'")
return false
}
decoded, err := hex.DecodeString(parts[1])
if err != nil {
log.Println(err)
return false
}
return checkMAC(body, decoded, []byte(os.Getenv("HOOK_SECRET_KEY")))
}
// Payload is the entry point HTTP handler.
func Payload(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Println(err)
return
}
log.Println("Header:\n---------")
fmt.Println(r.Header)
if !validateSignature(body, r) {
m := "Signature validation failed"
log.Println(m)
w.Write([]byte(m))
return
}
fmt.Println("Body:\n---------")
log.Println(string(body))
}