Skip to content

Instantly share code, notes, and snippets.

@markuskont
Last active January 19, 2019 19:28
Show Gist options
  • Save markuskont/4ce07a81653f105d70fac510f522dd34 to your computer and use it in GitHub Desktop.
Save markuskont/4ce07a81653f105d70fac510f522dd34 to your computer and use it in GitHub Desktop.
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"strconv"
"time"
"github.com/ccdcoe/go-peek/pkg/events"
"github.com/go-redis/redis"
)
type Alerta struct {
Attributes struct {
Region string `json:"region"`
} `json:"attributes,omitemtpty"`
//Correlate []string `json:"correlate,omitemtpty"`
Environment string `json:"environment"`
Event string `json:"event"`
Group string `json:"group"`
Origin string `json:"origin"`
Resource string `json:"resource"`
Service []string `json:"service,omitemtpty"`
Severity string `json:"severity"`
//Tags []string `json:"tags,omitemtpty"`
Text string `json:"text"`
Type string `json:"type"`
Value string `json:"value"`
Timeout int `json:"timeout"`
}
func (a Alerta) Send(host string) error {
out, err := json.Marshal(a)
if err != nil {
return err
}
req, err := http.NewRequest(
"POST",
"http://localhost:8080/api/alert",
bytes.NewBuffer(out),
)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != 201 {
body, _ := ioutil.ReadAll(resp.Body)
return fmt.Errorf(string(body))
}
return nil
}
func NewClient() (*redis.Client, error) {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
DB: 0,
})
if _, err := client.Ping().Result(); err != nil {
return nil, err
}
return client, nil
}
func main() {
client, err := NewClient()
if err != nil {
panic(err)
}
defer client.Close()
assets := map[string]string{
"192.168.144.10": "minion",
"192.168.144.15": "shadow",
"192.168.144.5": "pihole",
}
sevs := map[int]string{
1: "major",
2: "minor",
3: "informational",
}
var asset string
stream := client.Subscribe("suricata")
defer stream.Close()
report := time.NewTicker(3 * time.Second)
sent := 0
loop:
for {
select {
case msg, ok := <-stream.Channel():
if !ok {
break loop
}
data, err := events.NewEVE([]byte(msg.Payload))
if err != nil {
fmt.Fprintf(os.Stderr, "ERR: %s\n", err.Error())
continue loop
}
if data.SrcIP == nil || data.DestIP == nil || data.Alert == nil {
continue loop
}
if data.EventType != "alert" {
continue loop
}
if val, ok := assets[data.SrcIP.String()]; ok {
asset = val
} else if val, ok := assets[data.DestIP.String()]; ok {
asset = val
} else {
asset = data.DestIP.String()
}
var sev string
if val, ok := sevs[data.Alert.Severity]; ok {
sev = val
} else {
sev = sevs[3]
}
err = Alerta{
Event: data.Alert.Signature,
Service: []string{asset},
Environment: "Production",
Resource: asset,
Text: fmt.Sprintf(
"Alert from %s to %s",
data.SrcIP.String(),
data.DestIP.String(),
),
Severity: sev,
Value: strconv.Itoa(data.Alert.Severity),
Timeout: 300,
}.Send("localhost:8080/api/alert")
if err != nil {
fmt.Fprintf(os.Stderr, "%s\n", err.Error())
} else {
sent++
}
case <-report.C:
fmt.Fprintf(os.Stdout, "sent %d alerts to alerta\n", sent)
sent = 0
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment