pkg/generator/cef/cef.go (963 lines of code) (raw):
// Package cef implements the generator for generic CEF logs.
//
// Configuration file supports including timestamps in log messages
//
// generator:
// type: "generic:cef"
// max_extensions: 20
// vendors: ["VaporCorp", ...]
// products: ["VaporWare"]
// versions: ["0.1", "0.1-alpha"]
// classes: ["APPSS"]
// names: ["APPSS_UL", "APPSS_LTUL"]
// must_include: ["src", "spt", "dst", "dpt",...]
// must_exclude: ["art",...]
//
package cef
import (
"bytes"
"fmt"
"math/rand"
"net"
"net/http"
"sort"
"strconv"
"strings"
"text/template"
"time"
"github.com/elastic/go-ucfg"
"github.com/google/uuid"
"github.com/elastic/spigot/pkg/generator"
"github.com/elastic/spigot/pkg/random"
)
// Name is the name of the generator in the configuration file and registry
const Name = "generic:cef"
var (
tmpl = `CEF:{{.CEFVersion}}|{{.Vendor}}|{{.Product}}|{{.Version}}|{{.Class}}|{{.Name}}|{{.Severity}}|{{range $i, $v := .Extensions}}{{if $i}} {{end}}{{$v}}{{end}}`
msgTemplates = []string{
tmpl,
}
)
type CEF struct {
CEFVersion int
Vendor string
Product string
Version string
Class string
Name string
Severity int
Extensions []string
config
templates []*template.Template
}
func init() {
generator.Register(Name, New)
}
// New returns a new CEF log line generator.
func New(cfg *ucfg.Config) (generator.Generator, error) {
config := defaultConfig()
if err := cfg.Unpack(&config); err != nil {
return nil, err
}
c := &CEF{config: config}
c.randomize()
for i, v := range msgTemplates {
t, err := template.New(strconv.Itoa(i)).Funcs(generator.FunctionMap).Parse(v)
if err != nil {
return nil, err
}
c.templates = append(c.templates, t)
}
return c, nil
}
// Next produces the next CEF log entry.
func (c *CEF) Next() ([]byte, error) {
var buf bytes.Buffer
err := c.templates[rand.Intn(len(c.templates))].Execute(&buf, c)
if err != nil {
return nil, err
}
c.randomize()
return buf.Bytes(), err
}
func (c *CEF) randomize() {
c.CEFVersion = randInt(c.CEFVersions)
c.Vendor = randString(c.Vendors)
c.Product = randString(c.Products)
c.Version = randString(c.Versions)
c.Class = randString(c.Classes)
c.Name = randString(c.Names)
c.Severity = randInt(c.Severities)
c.Extensions = c.Extensions[:0]
if c.Max == 0 {
return
}
have := make(map[string]bool)
for _, x := range c.Exclude {
have[x] = true
}
for _, m := range c.Must {
c.addExtension(m, have)
}
perm := rand.Perm(len(extensions))
max := rand.Intn(c.Max)
for _, p := range perm {
if len(c.Extensions) >= max {
break
}
c.addExtension(extensions[p], have)
}
rand.Shuffle(len(c.Extensions), func(i, j int) { c.Extensions[i], c.Extensions[j] = c.Extensions[j], c.Extensions[i] })
}
func (c *CEF) addExtension(abbrev string, have map[string]bool) {
cand := extensionMapping[abbrev]
if cand.Wants == "" && !have[cand.Abbrev] {
c.Extensions = append(c.Extensions, cand.Render(c.config))
have[cand.Abbrev] = true
return
}
var add []mappedField
seen := make(map[string]bool)
for {
if seen[cand.Abbrev] {
panic(fmt.Sprintf("cycle including %s", cand.Abbrev))
}
seen[cand.Abbrev] = true
add = append(add, cand)
if cand.Wants == "" {
if len(add) > c.Max {
add = add[len(add)-c.Max:]
}
for _, a := range add {
if have[a.Abbrev] {
continue
}
c.Extensions = append(c.Extensions, a.Render(c.config))
have[a.Abbrev] = true
}
break
}
cand = extensionMapping[cand.Wants]
}
}
func randInt(i []int) int {
return i[rand.Intn(len(i))]
}
func randString(s []string) string {
return s[rand.Intn(len(s))]
}
type mappedField struct {
Abbrev string
Target string
Value func(config) fmt.Stringer
Wants string
}
func (f mappedField) Render(c config) string {
if f.Value == nil {
return ""
}
return fmt.Sprintf("%s=%s", f.Abbrev, f.Value(c))
}
func init() {
for k, v := range extensionMapping {
if v.Value == nil {
continue
}
v.Abbrev = k
extensionMapping[k] = v
extensions = append(extensions, k)
if strings.HasSuffix(k, "Label") {
_, ok := extensionMapping[v.Wants]
if !ok {
panic(fmt.Sprintf("label mapping without target: %v", v.Target))
}
}
}
sort.Strings(extensions)
}
var extensions []string
// extensionMapping is a mapping of CEF key names to full field names and data
// types. This mapping was generated from tables contained in:
// - "Micro Focus Security ArcSight Common Event Format Version 25"
// dated September 28, 2017.
// - "Check Point Log Exporter CEF Field Mappings"
// dated November 23, 2018.
// - "HPE Security ArcSight Common Event Format Version 23"
// dated May 16, 2016.
var extensionMapping = map[string]mappedField{
"agt": {
Target: "agentAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"agentDnsDomain": {
Target: "agentDnsDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"ahost": {
Target: "agentHostName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"aid": {
Target: "agentId",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"amac": {
Target: "agentMacAddress",
Value: func(c config) fmt.Stringer { return hwaddrValue{6} },
},
"agentNtDomain": {
Target: "agentNtDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"art": {
Target: "agentReceiptTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"atz": {
Target: "agentTimeZone",
Value: func(c config) fmt.Stringer { return keywordValue(c.TimeZones) },
},
"agentTranslatedAddress": {
Target: "agentTranslatedAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"agentTranslatedZoneExternalID": {
Target: "agentTranslatedZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"agentTranslatedZoneURI": {
Target: "agentTranslatedZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"at": {
Target: "agentType",
Value: func(c config) fmt.Stringer { return keywordValue{"local", "network"} },
},
"av": {
Target: "agentVersion",
Value: func(c config) fmt.Stringer { return integerValue{0, 5} },
},
"agentZoneExternalID": {
Target: "agentZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"agentZoneURI": {
Target: "agentZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"app": {
Target: "applicationProtocol",
Value: func(c config) fmt.Stringer {
return keywordValue{"tcp", "TCP", "udp", "UDP", "sip", "SIP", "http", "HTTP"}
},
},
"cnt": {
Target: "baseEventCount",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e3} },
},
"in": {
Target: "bytesIn",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"out": {
Target: "bytesOut",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"customerExternalID": {
Target: "customerExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"customerURI": {
Target: "customerURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"dst": {
Target: "destinationAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"destinationDnsDomain": {
Target: "destinationDnsDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"dlat": {
Target: "destinationGeoLatitude",
Value: func(c config) fmt.Stringer { return floatValue{-180, 180} },
},
"dlong": {
Target: "destinationGeoLongitude",
Value: func(c config) fmt.Stringer { return floatValue{-90, 90} },
},
"dhost": {
Target: "destinationHostName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"dmac": {
Target: "destinationMacAddress",
Value: func(c config) fmt.Stringer { return hwaddrValue{6} },
},
"dntdom": {
Target: "destinationNtDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"dpt": {
Target: "destinationPort",
Wants: "dst",
Value: func(c config) fmt.Stringer { return integerValue{0, 65535} },
},
"dpid": {
Target: "destinationProcessId",
Value: func(c config) fmt.Stringer { return integerValue{0, 65535} },
},
"dproc": {
Target: "destinationProcessName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"destinationServiceName": {
Target: "destinationServiceName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"destinationTranslatedAddress": {
Target: "destinationTranslatedAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"destinationTranslatedPort": {
Target: "destinationTranslatedPort",
Value: func(c config) fmt.Stringer { return integerValue{0, 65535} },
},
"destinationTranslatedZoneExternalID": {
Target: "destinationTranslatedZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"destinationTranslatedZoneURI": {
Target: "destinationTranslatedZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"duid": {
Target: "destinationUserId",
Value: func(c config) fmt.Stringer { return keywordValue(c.Users) },
},
"duser": {
Target: "destinationUserName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Users) },
},
"dpriv": {
Target: "destinationUserPrivileges",
Value: func(c config) fmt.Stringer { return keywordValue(c.Privs) },
},
"destinationZoneExternalID": {
Target: "destinationZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"destinationZoneURI": {
Target: "destinationZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"act": {
Target: "deviceAction",
Value: func(c config) fmt.Stringer { return keywordValue(actions) },
},
"dvc": {
Target: "deviceAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"cfp1": {
Target: "deviceCustomFloatingPoint1",
Value: func(c config) fmt.Stringer { return floatValue{0, 100} },
},
"cfp1Label": {
Target: "deviceCustomFloatingPoint1Label",
Wants: "cfp1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cfp2": {
Target: "deviceCustomFloatingPoint2",
Value: func(c config) fmt.Stringer { return floatValue{0, 100} },
},
"cfp2Label": {
Target: "deviceCustomFloatingPoint2Label",
Wants: "cfp2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cfp3": {
Target: "deviceCustomFloatingPoint3",
Value: func(c config) fmt.Stringer { return floatValue{0, 100} },
},
"cfp3Label": {
Target: "deviceCustomFloatingPoint3Label",
Wants: "cfp3",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cfp4": {
Target: "deviceCustomFloatingPoint4",
Value: func(c config) fmt.Stringer { return floatValue{0, 100} },
},
"cfp4Label": {
Target: "deviceCustomFloatingPoint4Label",
Wants: "cfp4",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"deviceCustomDate1": {
Target: "deviceCustomDate1",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"deviceCustomDate1Label": {
Target: "deviceCustomDate1Label",
Wants: "deviceCustomDate1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"deviceCustomDate2": {
Target: "deviceCustomDate2",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"deviceCustomDate2Label": {
Target: "deviceCustomDate2Label",
Wants: "deviceCustomDate2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"c6a1": {
Target: "deviceCustomIPv6Address1",
Value: func(c config) fmt.Stringer { return ipv6Value{} },
},
"c6a1Label": {
Target: "deviceCustomIPv6Address1Label",
Wants: "c6a1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"c6a2": {
Target: "deviceCustomIPv6Address2",
Value: func(c config) fmt.Stringer { return ipv6Value{} },
},
"c6a2Label": {
Target: "deviceCustomIPv6Address2Label",
Wants: "c6a2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"c6a3": {
Target: "deviceCustomIPv6Address3",
Value: func(c config) fmt.Stringer { return ipv6Value{} },
},
"c6a3Label": {
Target: "deviceCustomIPv6Address3Label",
Wants: "c6a3",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"c6a4": {
Target: "deviceCustomIPv6Address4",
Value: func(c config) fmt.Stringer { return ipv6Value{} },
},
"C6a4Label": {
Target: "deviceCustomIPv6Address4Label",
Wants: "c6a4",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cn1": {
Target: "deviceCustomNumber1",
Value: func(c config) fmt.Stringer { return integerValue{0, 1000} },
},
"cn1Label": {
Target: "deviceCustomNumber1Label",
Wants: "cn1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cn2": {
Target: "deviceCustomNumber2",
Value: func(c config) fmt.Stringer { return integerValue{0, 1000} },
},
"cn2Label": {
Target: "deviceCustomNumber2Label",
Wants: "cn2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cn3": {
Target: "deviceCustomNumber3",
Value: func(c config) fmt.Stringer { return integerValue{0, 1000} },
},
"cn3Label": {
Target: "deviceCustomNumber3Label",
Wants: "cn3",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs1": {
Target: "deviceCustomString1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs1Label": {
Target: "deviceCustomString1Label",
Wants: "cs1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs2": {
Target: "deviceCustomString2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs2Label": {
Target: "deviceCustomString2Label",
Wants: "cs2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs3": {
Target: "deviceCustomString3",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs3Label": {
Target: "deviceCustomString3Label",
Wants: "cs3",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs4": {
Target: "deviceCustomString4",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs4Label": {
Target: "deviceCustomString4Label",
Wants: "cs4",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs5": {
Target: "deviceCustomString5",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs5Label": {
Target: "deviceCustomString5Label",
Wants: "cs5",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs6": {
Target: "deviceCustomString6",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"cs6Label": {
Target: "deviceCustomString6Label",
Wants: "cs6",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"deviceDirection": {
Target: "deviceDirection",
Value: func(c config) fmt.Stringer { return integerValue{0, 1} },
},
"deviceDnsDomain": {
Target: "deviceDnsDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"cat": {
Target: "deviceEventCategory",
},
"deviceExternalId": {
Target: "deviceExternalId",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"deviceFacility": {
Target: "deviceFacility",
Value: func(c config) fmt.Stringer {
return keywordValue{"auth", "authpriv", "cron", "daemon", "kern", "lpr", "mail", "mark", "news", "syslog", "user", "uucp", "local0", "local1", "local2", "local3", "local4", "local5", "local6", "local7"}
},
},
"dvchost": {
Target: "deviceHostName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"deviceInboundInterface": {
Target: "deviceInboundInterface",
Value: func(c config) fmt.Stringer { return keywordValue(c.Interfaces) },
},
"dvcmac": {
Target: "deviceMacAddress",
Value: func(c config) fmt.Stringer { return hwaddrValue{6} },
},
"deviceNtDomain": {
Target: "deviceNtDomain",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"DeviceOutboundInterface": {
Target: "deviceOutboundInterface",
Value: func(c config) fmt.Stringer { return keywordValue(c.Interfaces) },
},
"DevicePayloadId": {
Target: "devicePayloadId",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"dvcpid": {
Target: "deviceProcessId",
Value: func(c config) fmt.Stringer { return integerValue{0, 65535} },
},
"deviceProcessName": {
Target: "deviceProcessName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"rt": {
Target: "deviceReceiptTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"dtz": {
Target: "deviceTimeZone",
Value: func(c config) fmt.Stringer { return keywordValue(c.TimeZones) },
Wants: "rt",
},
"deviceTranslatedAddress": {
Target: "deviceTranslatedAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"deviceTranslatedZoneExternalID": {
Target: "deviceTranslatedZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"deviceTranslatedZoneURI": {
Target: "deviceTranslatedZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"deviceZoneExternalID": {
Target: "deviceZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"deviceZoneURI": {
Target: "deviceZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"end": {
Target: "endTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"eventId": {
Target: "eventId",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"outcome": {
Target: "eventOutcome",
Value: func(c config) fmt.Stringer { return keywordValue{"success", "failure"} },
},
"externalId": {
Target: "externalId",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"fileCreateTime": {
Target: "fileCreateTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"fileHash": {
Target: "fileHash",
Value: func(c config) fmt.Stringer { return hashValue{16} },
},
"fileId": {
Target: "fileId",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"fileModificationTime": {
Target: "fileModificationTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"flexNumber1": {
Target: "deviceFlexNumber1",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"flexNumber1Label": {
Target: "deviceFlexNumber1Label",
Wants: "flexNumber1",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"flexNumber2": {
Target: "deviceFlexNumber2",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"flexNumber2Label": {
Target: "deviceFlexNumber2Label",
Wants: "flexNumber2",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"fname": {
Target: "filename",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"filePath": {
Target: "filePath",
},
"filePermission": {
Target: "filePermission",
},
"fsize": {
Target: "fileSize",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"fileType": {
Target: "fileType",
Value: func(c config) fmt.Stringer { return keywordValue{"directory", "regular", "pipe", "socket"} },
},
"flexDate1": {
Target: "flexDate1",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"flexDate1Label": {
Target: "flexDate1Label",
Wants: "flexDate1",
},
"flexString1": {
Target: "flexString1",
},
"flexString2": {
Target: "flexString2",
},
"flexString1Label": {
Target: "flexString1Label",
Wants: "flexString1",
},
"flexString2Label": {
Target: "flexString2Label",
Wants: "flexString2",
},
"msg": {
Target: "message",
Value: func(c config) fmt.Stringer { return keywordValue(messages) },
},
"oldFileCreateTime": {
Target: "oldFileCreateTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"oldFileHash": {
Target: "oldFileHash",
Value: func(c config) fmt.Stringer { return hashValue{16} },
},
"oldFileId": {
Target: "oldFileId",
},
"oldFileModificationTime": {
Target: "oldFileModificationTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"oldFileName": {
Target: "oldFileName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"oldFilePath": {
Target: "oldFilePath",
},
"oldFilePermission": {
Target: "oldFilePermission",
},
"oldFileSize": {
Target: "oldFileSize",
Value: func(c config) fmt.Stringer { return integerValue{0, 1e5} },
},
"oldFileType": {
Target: "oldFileType",
Value: func(c config) fmt.Stringer { return keywordValue{"directory", "regular", "pipe", "socket"} },
},
"rawEvent": {
Target: "rawEvent",
Value: func(c config) fmt.Stringer { return textValue{1, 500} },
},
"reason": {
Target: "Reason",
Value: func(c config) fmt.Stringer { return keywordValue{"bad password", "unknown user", "banned"} },
},
"requestClientApplication": {
Target: "requestClientApplication",
Value: func(c config) fmt.Stringer { return stringerise(random.UserAgent) },
},
"requestContext": {
Target: "requestContext",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"requestCookies": {
Target: "requestCookies",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"requestMethod": {
Target: "requestMethod",
Value: func(c config) fmt.Stringer {
return keywordValue{http.MethodConnect, http.MethodDelete, http.MethodGet, http.MethodPost, http.MethodPut}
},
},
"request": {
Target: "requestUrl",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"src": {
Target: "sourceAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"sourceDnsDomain": {
Target: "sourceDnsDomain",
Value: func(c config) fmt.Stringer { return domainValue(c.Words) },
},
"slat": {
Target: "sourceGeoLatitude",
Value: func(c config) fmt.Stringer { return floatValue{-180, 180} },
},
"slong": {
Target: "sourceGeoLongitude",
Value: func(c config) fmt.Stringer { return floatValue{-90, 90} },
},
"shost": {
Target: "sourceHostName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"smac": {
Target: "sourceMacAddress",
Value: func(c config) fmt.Stringer { return hwaddrValue{6} },
},
"sntdom": {
Target: "sourceNtDomain",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"spt": {
Target: "sourcePort",
Value: func(c config) fmt.Stringer { return integerValue{min: 0, max: 65535} },
},
"spid": {
Target: "sourceProcessId",
Value: func(c config) fmt.Stringer { return integerValue{min: 0, max: 65535} },
},
"sproc": {
Target: "sourceProcessName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"sourceServiceName": {
Target: "sourceServiceName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Words) },
},
"sourceTranslatedAddress": {
Target: "sourceTranslatedAddress",
Value: func(c config) fmt.Stringer { return ipv4Value{} },
},
"sourceTranslatedPort": {
Target: "sourceTranslatedPort",
Value: func(c config) fmt.Stringer { return integerValue{min: 0, max: 65535} },
},
"sourceTranslatedZoneExternalID": {
Target: "sourceTranslatedZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"sourceTranslatedZoneURI": {
Target: "sourceTranslatedZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"suid": {
Target: "sourceUserId",
Value: func(c config) fmt.Stringer { return keywordValue(c.Users) },
},
"suser": {
Target: "sourceUserName",
Value: func(c config) fmt.Stringer { return keywordValue(c.Users) },
},
"spriv": {
Target: "sourceUserPrivileges",
Value: func(c config) fmt.Stringer { return keywordValue(c.Privs) },
},
"sourceZoneExternalID": {
Target: "sourceZoneExternalID",
Value: func(c config) fmt.Stringer { return uuidValue{zero: c.ZeroUUID} },
},
"sourceZoneURI": {
Target: "sourceZoneURI",
Value: func(c config) fmt.Stringer { return urlValue(c.Words) },
},
"start": {
Target: "startTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
"proto": {
Target: "transportProtocol",
Value: func(c config) fmt.Stringer { return keywordValue{"tcp", "TCP", "udp", "UDP"} },
},
"type": {
Target: "type",
Value: func(c config) fmt.Stringer { return integerValue{0, 15} },
},
// This is an ArcSight categorization field that is commonly used, but its
// short name is not contained in the documentation used for the above list.
"catdt": {
Target: "categoryDeviceType",
Value: func(c config) fmt.Stringer { return keywordValue{"Operating system", "Network-based IDS/IPS"} },
},
"mrt": {
Target: "managerReceiptTime",
Value: func(c config) fmt.Stringer {
return integerValue{int(c.Now().Add(-time.Hour).UnixMilli()), int(c.Now().UnixMilli())}
},
},
}
type urlValue []string
func (u urlValue) String() string {
return fmt.Sprintf("%s://%s/%s%s%s",
keywordValue{"http", "https"}, domainValue(u), keywordValue(u), keywordValue{"/", "?"}, keywordValue(u),
)
}
type domainValue []string
func (d domainValue) String() string {
return fmt.Sprintf("%s.%s.%s", keywordValue(d), keywordValue(d), keywordValue{"com", "org", "co"})
}
type keywordValue []string
func (k keywordValue) String() string {
return k[rand.Intn(len(k))]
}
type uuidValue struct {
zero bool
}
func (u uuidValue) String() string {
if u.zero {
uuid, _ := uuid.NewRandomFromReader(bytes.NewReader(make([]byte, 16)))
return uuid.String()
}
return uuid.New().String()
}
type hashValue struct {
bytes int
}
func (h hashValue) String() string {
buf := make([]byte, h.bytes)
rand.Read(buf)
return fmt.Sprintf("%0*x", h.bytes, buf)
}
type hwaddrValue struct {
bytes int
}
func (a hwaddrValue) String() string {
buf := make(net.HardwareAddr, a.bytes)
rand.Read(buf)
return buf.String()
}
type ipv4Value struct{}
func (ipv4Value) String() string {
buf := make(net.IP, 4)
rand.Read(buf)
return buf.String()
}
type ipv6Value struct{}
func (ipv6Value) String() string {
buf := make(net.IP, 16)
rand.Read(buf)
for i := range buf {
if rand.Float64() < 0.3 {
buf[i] = 0
}
}
return buf.String()
}
type timeValue struct {
min, max int64
format string
}
func newTimeValue(min, max time.Time, format string) timeValue {
return timeValue{min: min.UnixMilli(), max: max.UnixMilli(), format: format}
}
func (t timeValue) String() string {
return time.UnixMilli(rand.Int63n(t.max-t.min) + t.min).Format(t.format)
}
type integerValue struct {
min, max int
}
func (t integerValue) String() string {
return strconv.Itoa(rand.Intn(t.max-t.min+1) + t.min)
}
type floatValue struct {
min, max float64
}
func (t floatValue) String() string {
return strconv.FormatFloat(((t.max-t.min)*rand.Float64())+t.min, 'f', -1, 64)
}
type textValue struct {
min, max int
}
func (t textValue) String() string {
idx := rand.Intn(t.max-t.min) + t.min
words := strings.Split(loremIpsum, " ")
if idx >= len(words) {
return loremIpsum
}
return strings.Join(words[:idx], " ")
}
type stringerise func() string
func (s stringerise) String() string { return s() }