Skip to content
This repository was archived by the owner on May 10, 2025. It is now read-only.

Commit 816e93d

Browse files
authored
Merge pull request #1 from 0xma12k/dev
Add graylog line notify gateway feature
2 parents 4c8411e + 1f2b50a commit 816e93d

File tree

14 files changed

+426
-0
lines changed

14 files changed

+426
-0
lines changed

.github/workflows/release.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: goreleaser
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
goreleaser:
13+
runs-on: ubuntu-latest
14+
steps:
15+
-
16+
name: Checkout
17+
uses: actions/checkout@v2
18+
with:
19+
fetch-depth: 0
20+
-
21+
name: Set up Go
22+
uses: actions/setup-go@v2
23+
with:
24+
go-version: 1.16
25+
-
26+
name: Run GoReleaser
27+
uses: goreleaser/goreleaser-action@v2
28+
with:
29+
distribution: goreleaser
30+
version: latest
31+
args: release --rm-dist
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
bin/*
2+
.vscode/*
3+
.debug/*

Dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
FROM golang:1.16 as builder
2+
3+
WORKDIR /app
4+
5+
COPY go.mod .
6+
7+
COPY go.sum .
8+
9+
RUN go mod download
10+
11+
COPY . .
12+
13+
RUN CGO_ENABLED=0 GOOS=linux go build -o app
14+
15+
FROM alpine:latest
16+
17+
ENV TZ=Asia/Bangkok
18+
19+
WORKDIR /app/
20+
21+
COPY --from=builder /app/app .
22+
23+
EXPOSE 3000
24+
25+
ENTRYPOINT ["./app"]

config/config.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
3+
server_port: 3000
4+
log_level: debug
5+
6+
default_template: default
7+
8+
templates:
9+
- name: default
10+
path: templates/default.templ

controllers/webhookhandler.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package controllers
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
7+
"github.com/0xma12k/graylog-line-notify-gateway/internal/entity"
8+
"github.com/0xma12k/graylog-line-notify-gateway/internal/templ"
9+
"github.com/0xma12k/graylog-line-notify-gateway/notify/line"
10+
log "github.com/sirupsen/logrus"
11+
)
12+
13+
// Webhook ...
14+
func Webhook(w http.ResponseWriter, r *http.Request) {
15+
params := r.URL.Query()
16+
templName := params.Get("template")
17+
lineToken := params.Get("token")
18+
19+
// Decode reqeust body to Graylog struct object
20+
var graylog entity.GraylogJSON
21+
if err := json.NewDecoder(r.Body).Decode(&graylog); err != nil {
22+
log.Error(err)
23+
}
24+
25+
// Execute template
26+
msg, err := templ.ExecuteTemplate(templName, &graylog)
27+
if err != nil {
28+
log.Error(err)
29+
30+
defaultMsg, err := templ.DefaultExecute(&graylog)
31+
if err != nil {
32+
log.Fatal(err)
33+
}
34+
msg = defaultMsg
35+
}
36+
37+
statusCode, bodyBytes := line.Notify(msg, lineToken)
38+
39+
w.WriteHeader(statusCode)
40+
w.Write(bodyBytes)
41+
42+
defer r.Body.Close()
43+
}

go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module github.com/0xma12k/graylog-line-notify-gateway
2+
3+
go 1.16
4+
5+
require (
6+
github.com/gorilla/mux v1.8.0
7+
github.com/sirupsen/logrus v1.8.1
8+
gopkg.in/yaml.v2 v2.4.0
9+
)

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
4+
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
8+
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
9+
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
10+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
11+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
12+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
13+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
14+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
15+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
16+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

internal/config/config.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package config
2+
3+
import (
4+
"flag"
5+
"os"
6+
"path"
7+
"runtime"
8+
"strings"
9+
10+
"github.com/sirupsen/logrus"
11+
"gopkg.in/yaml.v2"
12+
)
13+
14+
// Config ...
15+
type Config struct {
16+
Port string `yaml:"server_port"`
17+
LogLevel string `yaml:"log_level"`
18+
DefaultTemplate string `yaml:"default_template"`
19+
Templates []struct {
20+
Name string `yaml:"name"`
21+
Path string `yaml:"path"`
22+
} `yaml:"templates"`
23+
}
24+
25+
var config Config
26+
27+
// Init ...
28+
func Init() {
29+
logrus.SetFormatter(&logrus.TextFormatter{
30+
DisableColors: true,
31+
FullTimestamp: true,
32+
CallerPrettyfier: func(f *runtime.Frame) (string, string) {
33+
s := strings.Split(f.Function, ".")
34+
funcname := s[len(s)-1]
35+
_, filename := path.Split(f.File)
36+
return funcname, filename
37+
},
38+
})
39+
logrus.SetReportCaller(true)
40+
41+
logrus.Info("loading configuration from yaml file")
42+
path := ""
43+
flag.StringVar(&path, "config", "", "`file` to configuration line notify gateway")
44+
flag.Parse()
45+
46+
if path != "" {
47+
logrus.Info("open configuration file at " + path)
48+
f, err := os.Open(path)
49+
if err != nil {
50+
logrus.Fatal(err)
51+
}
52+
defer f.Close()
53+
54+
decoder := yaml.NewDecoder(f)
55+
err = decoder.Decode(&config)
56+
if err != nil {
57+
logrus.Fatal(err)
58+
}
59+
} else {
60+
logrus.Info("not provide configuration file, server run on default port")
61+
config.Port = "3000"
62+
}
63+
logLevel()
64+
}
65+
66+
func logLevel() {
67+
switch config.LogLevel {
68+
case "info":
69+
logrus.SetLevel(logrus.InfoLevel)
70+
case "debug":
71+
logrus.SetLevel(logrus.DebugLevel)
72+
case "warnning":
73+
logrus.SetLevel(logrus.WarnLevel)
74+
default:
75+
logrus.SetLevel(logrus.InfoLevel)
76+
}
77+
logrus.SetOutput(os.Stdout)
78+
}
79+
80+
// Get ..
81+
func Get() Config {
82+
return config
83+
}

internal/entity/graylog.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package entity
2+
3+
// GraylogJSON represent json object receive from Graylog notification, see reference at https://docs.graylog.org/en/3.3/pages/alerts.html
4+
type GraylogJSON struct {
5+
EventDefinitionID string `json:"event_definition_id"`
6+
EventDefinitionType string `json:"event_definition_type"`
7+
EventDefinitionTitle string `json:"event_definition_title"`
8+
EventDefinitionDescription string `json:"event_definition_description"`
9+
JobDefinitionID string `json:"job_definition_id"`
10+
JobTriggerID string `json:"job_trigger_id"`
11+
Event struct {
12+
ID string `json:"id"`
13+
EventDefinitionID string `json:"event_definition_id"`
14+
EventDefinitionType string `json:"event_definition_type"`
15+
OriginContext string `json:"origin_context"`
16+
Timestamp string `json:"timestamp"`
17+
TimestampProcessing string `json:"timestamp_processing"`
18+
TimerangeStart string `json:"timerange_start"`
19+
TimerangeEnd string `json:"timerange_end"`
20+
Streams []string `json:"streams"`
21+
SourceStreams []string `json:"source_streams"`
22+
Alert bool `json:"alert"`
23+
Message string `json:"message"`
24+
Source string `json:"source"`
25+
KeyTuple []string `json:"key_tuple"`
26+
Key string `json:"key"`
27+
Priority int64 `json:"priority"`
28+
Fields map[string]interface{} `json:"fields"`
29+
} `json:"event"`
30+
Backlog []struct {
31+
ID string `json:"id"`
32+
Index string `json:"index"`
33+
Source string `json:"source"`
34+
Message string `json:"message"`
35+
Timestamp string `json:"timestamp"`
36+
SteamIDs []string `json:"stream_ids"`
37+
Fields map[string]interface{} `json:"fields"`
38+
} `json:"backlog"`
39+
// Backlog []interface{} `json:"backlog"`
40+
}

internal/templ/templ.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package templ
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"text/template"
7+
8+
"github.com/0xma12k/graylog-line-notify-gateway/internal/config"
9+
"github.com/0xma12k/graylog-line-notify-gateway/internal/entity"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
var defaultTempl string = "{{.EventDefinitionTitle}}"
14+
15+
func DefaultExecute(graylog *entity.GraylogJSON) (string, error) {
16+
var buf bytes.Buffer
17+
logrus.Debug("using build-in template")
18+
t := template.Must(template.New("default").Parse(defaultTempl))
19+
if err := t.Execute(&buf, graylog); err != nil {
20+
return "", err
21+
}
22+
return buf.String(), nil
23+
}
24+
25+
func ExecuteTemplate(templName string, graylog *entity.GraylogJSON) (string, error) {
26+
27+
var buf bytes.Buffer
28+
29+
if templName == "" {
30+
templName = config.Get().DefaultTemplate
31+
}
32+
33+
path, err := findTemplatePath(templName)
34+
if err != nil {
35+
return "", err
36+
}
37+
38+
tmpl, err := template.ParseFiles(path)
39+
if err != nil {
40+
return "", err
41+
}
42+
t := template.Must(tmpl, err)
43+
44+
if err := t.Execute(&buf, graylog); err != nil {
45+
return "", err
46+
}
47+
return buf.String(), nil
48+
}
49+
50+
func findTemplatePath(name string) (string, error) {
51+
for _, templ := range config.Get().Templates {
52+
if name == templ.Name {
53+
return templ.Path, nil
54+
}
55+
}
56+
return "", fmt.Errorf("template not found")
57+
}

0 commit comments

Comments
 (0)