Initial commit

This commit is contained in:
Akbar Rahman 2021-07-28 16:20:06 +01:00
commit 0370e58aec
6 changed files with 137 additions and 0 deletions

9
config.json Normal file
View File

@ -0,0 +1,9 @@
{
"Services": {
"test": {
"Script": "./example.sh",
"Secret": "THISISVERYSECRET",
"SignatureHeader": "X-Gitea-Signature"
}
}
}

2
example.sh Executable file
View File

@ -0,0 +1,2 @@
#!/usr/bin/bash
date >> test_output

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module git.alra.uk/alvierahman90/ghookr
go 1.16
require github.com/gorilla/mux v1.8.0

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=

112
main.go Normal file
View File

@ -0,0 +1,112 @@
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"os/exec"
"github.com/gorilla/mux"
)
var config_filename = "/etc/ghookr.json"
func main() {
// Used for testing purposes... generates hmac string
if os.Getenv("HMACGEN") == "true" {
input, err := ioutil.ReadAll(os.Stdin)
secret := os.Getenv("SECRET")
if err != nil {
panic(err.Error())
}
fmt.Println(getSha256HMACSignature([]byte(secret), string(input)))
return
}
r := mux.NewRouter()
r.HandleFunc("/webhook/{service}", webhook)
port := ":80"
if p, ok := os.LookupEnv("PORT"); ok {
port = fmt.Sprintf(":%v", p)
}
if p, ok := os.LookupEnv("CONFIG"); ok {
config_filename = p
}
log.Fatal(http.ListenAndServe(port, r))
}
func webhook(w http.ResponseWriter, r *http.Request) {
// TODO run any specified tests before running script
service_name := mux.Vars(r)["service"]
payload := ""
if p, err := ioutil.ReadAll(r.Body); err != nil {
writeResponse(w, 500, "Internal Server Error: Could not read payload")
return
} else {
payload = string(p)
}
raw_config, err := ioutil.ReadFile(config_filename)
if err != nil {
writeResponse(w, 500, "Internal Server Error: Could not open config file")
return
}
config := Config{}
json.Unmarshal(raw_config, &config)
var service = Service{}
if val, ok := config.Services[string(service_name)]; !ok {
writeResponse(w, 404, "Service Not Found")
return
} else {
service = val
}
signature := r.Header.Get(service.SignatureHeader)
if signature == getSha256HMACSignature([]byte(service.Secret), payload) {
writeResponse(w, 400, "Bad Request: Signatures do not match")
return
}
if stdout, err := exec.Command(service.Script, payload).Output(); err != nil {
writeResponse(w, 500, err.Error())
return
} else {
writeResponse(w, 200, string(stdout))
return
}
}
func writeResponse(w http.ResponseWriter, responseCode int, responseString string) {
w.WriteHeader(responseCode)
w.Write([]byte(fmt.Sprintf("%v %v", responseCode, responseString)))
}
func getSha256HMACSignature(secret []byte, data string) string {
h := hmac.New(sha256.New, secret)
io.WriteString(h, data)
return hex.EncodeToString(h.Sum(nil))
}
type Service struct {
Gitea bool
Script string
Secret string
SignatureHeader string
Tests []string
}
type Config struct {
Services map[string]Service
}

7
readme.md Normal file
View File

@ -0,0 +1,7 @@
# gohookr
A _really_ simple webhook receiver.
Check config.json for an example configuration.
Default config path is `/etc/ghookr.conf`, can be overriden with `CONFIG` environment variable.