This commit is contained in:
Zack Mullaly 2018-10-29 19:40:59 -04:00
Родитель 0d161acb07
Коммит 685018106b
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 1486642516ED3535
5 изменённых файлов: 471 добавлений и 0 удалений

65
vendor/github.com/mozilla/gozdef/README.md сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,65 @@
gozdef - Go client to send events to MozDef
===========================================
http://godoc.org/github.com/jvehent/gozdef
```go
package main
import (
"github.com/jvehent/gozdef"
"log"
)
func main() {
// initialize a publisher to mozdef's rabbitmq relay
conf := gozdef.MqConf{
Host: "mozdef.rabbitmq.example.net",
Port: 5671,
User: "gozdefclient",
Pass: "s3cr3tpassw0rd",
Vhost: "mozdef",
Exchange: "eventtask",
RoutingKey: "eventtask",
UseTLS: true,
CACertPath: "/etc/pki/CA/certs/ca.crt",
Timeout: "10s",
}
publisher, err := gozdef.InitAmqp(conf)
if err != nil {
log.Fatal(err)
}
// create a new event and set values in the fields
ev, err := gozdef.NewEvent()
if err != nil {
log.Fatal(err)
}
ev.Category = "demo"
ev.Source = "test client"
ev.Summary = "tl;dr: everything's fine!"
ev.Tags = append(ev.Tags, "gozdef")
// add details to the event, these fields are completely customizable
ev.Details = struct {
SrcIP string `json:"sourceipaddress"`
DestIP string `json:"destinationipaddress"`
Offense string `json:"offense"`
Blocked bool
}{
SrcIP: "10.0.1.2",
DestIP: "192.168.1.5",
Offense: "brute force",
Blocked: true,
}
// set the event severity to INFO
ev.Info()
// publish to mozdef
err = publisher.Send(ev)
if err != nil {
log.Fatal(err)
}
}
```

106
vendor/github.com/mozilla/gozdef/event.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,106 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
package gozdef
import (
"fmt"
"os"
"regexp"
"time"
)
// Generic MozDef event handling
// Event represent a piece of information being passed to MozDef
type Event struct {
Timestamp time.Time `json:"timestamp"` // Full date plus time timestamp of the event in ISO format including the timezone offset
Category string `json:"category"` // General category/type of event
Hostname string `json:"hostname"` // The fully qualified domain name of the host sending the message
ProcessID float64 `json:"processid"` // The PID of the process sending the log
ProcessName string `json:"processname"` // The name of the process sending the log
Severity string `json:"severity"` // RFC5424 severity level of the event in all caps: DEBUG, INFO, NOTICE, WARNING, ERROR, CRITICAL, ALERT, EMERGENCY
Source string `json:"source"` // Source of the event (file name, system name, component name)
Summary string `json:"summary"` // Short human-readable version of the event suitable for IRC, SMS, etc.
Tags []string `json:"tags"` // An array or list of any tags you would like applied to the event
Details interface{} `json:"details"` // Additional, event-specific fields included with the event
}
// NewEvent returns a new generic event that can be populated and submitted to MozDef
func NewEvent() (e Event, err error) {
e.Timestamp = time.Now().UTC()
e.Hostname, err = os.Hostname()
if err != nil {
return
}
e.ProcessID = float64(os.Getpid())
e.ProcessName = os.Args[0]
return
}
const severityRegex string = "^(DEBUG|INFO|NOTICE|WARNING|ERROR|CRITICAL|ALERT|EMERGENCY)$"
// Debug sets the severity level of the event to DEBUG
func (e *Event) Debug() {
e.Severity = "DEBUG"
}
// Info sets the severity level of the event to INFO
func (e *Event) Info() {
e.Severity = "INFO"
}
// Notice sets the severity level of the event to NOTICE
func (e *Event) Notice() {
e.Severity = "NOTICE"
}
// Warning sets the severity level of the event to WARNING
func (e *Event) Warning() {
e.Severity = "WARNING"
}
// Error sets the severity level of the event to ERROR
func (e *Event) Error() {
e.Severity = "ERROR"
}
// Critical sets the severity level of the event to CRITICAL
func (e *Event) Critical() {
e.Severity = "CRITICAL"
}
// Alert sets the severity level of the event to ALERT
func (e *Event) Alert() {
e.Severity = "ALERT"
}
// Emergency sets the severity level of the event to EMERGENCY
func (e *Event) Emergency() {
e.Severity = "EMERGENCY"
}
// Validate verifies that an event is formatted correctly
func (e Event) Validate() error {
hostname, err := os.Hostname()
if err != nil {
return err
}
if hostname != e.Hostname {
return fmt.Errorf("event hostname does not match the host's fqdn")
}
if float64(os.Getpid()) != e.ProcessID {
return fmt.Errorf("event processid does not match the id of the current process")
}
if os.Args[0] != e.ProcessName {
return fmt.Errorf("event processname does not match the name of the current process")
}
resev := regexp.MustCompile(severityRegex)
if !resev.MatchString(e.Severity) {
return fmt.Errorf("invalid severity '%s', must be one of %s", e.Severity, severityRegex)
}
return nil
}

190
vendor/github.com/mozilla/gozdef/gozdef.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,190 @@
// gozdef is a client for MozDef's AMQP and Rest endpoints. It formats
// messages into MozDef's standard event format and publishes them.
//
// Reference: http://mozdef.readthedocs.org/en/latest/usage.html#json-format
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
// Package gozdef provides an interface for submitting events to MozDef in a
// standardized format.
package gozdef
import (
"bytes"
"crypto/rand"
"crypto/tls"
"crypto/x509"
"encoding/json"
"fmt"
"github.com/streadway/amqp"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
)
// Publisher sends events to MozDef, either via AMQP (if initialized
// with InitAmqp()) or via rest API (if initialized via InitAPI())
type Publisher struct {
useAmqp bool // selects the sending mode, if set to false use rest api instead of amqp
amqpChan *amqp.Channel // channel handler
mqconf MqConf // rabbitmq configuration the publisher was initialized with
apiClient *http.Client // http client handler
apiconf APIConf // api configuration the publisher was initialized with
}
// Send submits an event indicated by ExternalEvent e to the initialized publisher p
func (p Publisher) Send(e ExternalEvent) error {
err := e.Validate()
if err != nil {
return err
}
data, err := json.Marshal(e)
if err != nil {
return err
}
// If using AMQP, publish the event on the configured queue
if p.useAmqp {
msg := amqp.Publishing{
DeliveryMode: amqp.Persistent,
Timestamp: time.Now(),
ContentType: "text/plain",
Body: data,
}
return p.amqpChan.Publish(p.mqconf.Exchange, p.mqconf.RoutingKey, false, false, msg)
}
// Otherwise, we will be sending the event to the REST API
b := bytes.NewBufferString(string(data))
resp, err := p.apiClient.Post(p.apiconf.URL, "application/json", b)
if err != nil {
return err
}
resp.Body.Close()
return nil
}
// MqConf holds the configuration parameters to connect to a rabbitmq instance
type MqConf struct {
Host string // hostname of the rabbitmq host
Port int // port of the rabbitmq host
User string // username to authenticate on rabbitmq
Pass string // password to authenticate on rabbitmq
Vhost string // the virtual host to connect to
Exchange string // the amqp exchange to publish to
RoutingKey string // the amqp routing key events should be published with
UseTLS bool // if set, establish the connection using AMQPS
ClientCertPath string // (optional) file system path to a client certificate
ClientKeyPath string // (optional) file system path to a client private key
CACertPath string // file system path to the Root CA cert
Timeout string // connection timeout
}
// InitAmqp establishes a connection to the rabbitmq endpoint defined in the configuration
func InitAmqp(conf MqConf) (p Publisher, err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("InitAmqp failed with error: %v", e)
}
}()
var scheme, user, pass, host, port, vhost string
if conf.UseTLS {
scheme = "amqps"
} else {
scheme = "amqp"
}
if conf.User == "" {
panic("MQ User is missing")
}
user = conf.User
if conf.Pass == "" {
panic("MQ Pass is missing")
}
pass = conf.Pass
if conf.Host == "" {
panic("MQ Host is missing")
}
host = conf.Host
if conf.Port < 1 {
panic("MQ Port is missing")
}
port = fmt.Sprintf("%d", conf.Port)
vhost = conf.Vhost
dialaddr := scheme + "://" + user + ":" + pass + "@" + host + ":" + port + "/" + vhost
timeout, _ := time.ParseDuration(conf.Timeout)
var dialConfig amqp.Config
dialConfig.Heartbeat = timeout
dialConfig.Dial = func(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
if conf.UseTLS {
// import the ca cert
data, err := ioutil.ReadFile(conf.CACertPath)
if err != nil {
panic(err)
}
ca := x509.NewCertPool()
if ok := ca.AppendCertsFromPEM(data); !ok {
panic("failed to import CA Certificate")
}
TLSconfig := tls.Config{
RootCAs: ca,
InsecureSkipVerify: false,
Rand: rand.Reader,
}
dialConfig.TLSClientConfig = &TLSconfig
if conf.ClientCertPath != "" && conf.ClientKeyPath != "" {
// import the client certificates
cert, err := tls.LoadX509KeyPair(conf.ClientCertPath, conf.ClientKeyPath)
if err != nil {
panic(err)
}
TLSconfig.Certificates = []tls.Certificate{cert}
}
}
// Setup the AMQP broker connection
amqpConn, err := amqp.DialConfig(dialaddr, dialConfig)
if err != nil {
panic(err)
}
p.amqpChan, err = amqpConn.Channel()
if err != nil {
panic(err)
}
p.useAmqp = true
p.mqconf = conf
return
}
// APIConf holds the configuration parameters to publish events to the REST API
type APIConf struct {
URL string // a fully qualified URL where events are posted
UseProxy bool
}
// InitAPI initializes a new Publisher that can be used to submit events to the
// REST API
func InitAPI(conf APIConf) (p Publisher, err error) {
if conf.URL == "" {
return p, fmt.Errorf("must set URL value in APIConf")
}
if conf.UseProxy {
p.apiClient = &http.Client{}
} else {
p.apiClient = &http.Client{
Transport: &http.Transport{
Proxy: func(_ *http.Request) (*url.URL, error) {
return nil, nil
},
},
}
}
p.useAmqp = false
p.apiconf = conf
return p, nil
}

42
vendor/github.com/mozilla/gozdef/types.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,42 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Julien Vehent jvehent@mozilla.com [:ulfr]
package gozdef
// ExternalEvent provides a generalized interface that all event types
// must provide
type ExternalEvent interface {
Validate() error
}
// ComplianceItem measures the compliance of a target
// with particular requirement. The item must be send to mozdef
// in the details of a regular Event.
type ComplianceItem struct {
Utctimestamp string `json:"utctimestamp"`
Target string `json:"target"`
Compliance bool `json:"compliance"`
Link string `json:"link"`
Tags map[string]string `json:"tags"`
Policy struct {
Name string `json:"name"`
URL string `json:"url"`
Level string `json:"level"`
} `json:"policy"`
Check struct {
Ref string `json:"ref"`
Description string `json:"description"`
Name string `json:"name"`
Location string `json:"location"`
Test struct {
Type string `json:"type"`
Value string `json:"value"`
} `json:"test"`
} `json:"check"`
}

68
vendor/github.com/mozilla/gozdef/vulnevent.go сгенерированный поставляемый Normal file
Просмотреть файл

@ -0,0 +1,68 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Contributor: Aaron Meihm ameihm@mozilla.com [:alm]
package gozdef
import (
"fmt"
"time"
)
// MozDef vulnerability event handling
// VulnEvent describes a vulnerability event
type VulnEvent struct {
Description string `json:"description"`
UTCTimestamp time.Time `json:"utctimestamp"`
SourceName string `json:"sourcename"`
CredentialedChecks bool `json:"credentialed_checks"`
Vuln []VulnVuln `json:"vulnerabilities"`
ExemptVuln []VulnVuln `json:"exempt_vulnerabilities"`
Version int `json:"version"`
Zone string `json:"zone"`
Asset struct {
IPAddress string `json:"ipaddress"`
Hostname string `json:"hostname"`
OS string `json:"os"`
Owner struct {
Operator string `json:"operator"`
Team string `json:"team"`
V2Bkey string `json:"v2bkey"`
} `json:"owner"`
} `json:"asset"`
}
// VulnVuln describes individual vulnerabilities for inclusion in a vulnerability
// event
type VulnVuln struct {
Risk string `json:"risk"`
Link string `json:"link"`
CVE string `json:"cve"`
CVSS string `json:"cvss"`
Name string `json:"name"`
Packages []string `json:"vulnerable_packages"`
LikelihoodIndicator string `json:"likelihood_indicator"`
}
// NewVulnEvent initializes a new VulnEvent that can be populated and submitted
// to MozDef
func NewVulnEvent() (e VulnEvent, err error) {
e.UTCTimestamp = time.Now().UTC()
e.Version = 2
return
}
// Validate verifies that an event is formatted correctly
func (e VulnEvent) Validate() error {
if e.SourceName == "" {
return fmt.Errorf("must set SourceName in event")
}
if e.Asset.IPAddress == "" && e.Asset.Hostname == "" {
return fmt.Errorf("must set IPAddress or Hostname in event")
}
return nil
}