api/pkg/audit/event.go
2021-01-26 18:17:37 +01:00

161 lines
4.1 KiB
Go

package audit
import (
"net"
"strconv"
"strings"
"time"
"gitlab.com/inetmock/inetmock/pkg/audit/details"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"google.golang.org/protobuf/types/known/timestamppb"
)
type Details interface {
MarshalToWireFormat() (*anypb.Any, error)
}
type Event struct {
ID int64
Timestamp time.Time
Transport TransportProtocol
Application AppProtocol
SourceIP net.IP
DestinationIP net.IP
SourcePort uint16
DestinationPort uint16
ProtocolDetails Details
TLS *TLSDetails
}
func (e *Event) ProtoMessage() proto.Message {
var sourceIP isEventEntity_SourceIP
if ipv4 := e.SourceIP.To4(); ipv4 != nil {
sourceIP = &EventEntity_SourceIPv4{SourceIPv4: ipv4ToUint32(ipv4)}
} else {
sourceIP = &EventEntity_SourceIPv6{SourceIPv6: ipv6ToBytes(e.SourceIP)}
}
var destinationIP isEventEntity_DestinationIP
if ipv4 := e.DestinationIP.To4(); ipv4 != nil {
destinationIP = &EventEntity_DestinationIPv4{DestinationIPv4: ipv4ToUint32(ipv4)}
} else {
destinationIP = &EventEntity_DestinationIPv6{DestinationIPv6: ipv6ToBytes(e.DestinationIP)}
}
var tlsDetails *TLSDetailsEntity = nil
if e.TLS != nil {
tlsDetails = e.TLS.ProtoMessage()
}
var detailsEntity *anypb.Any = nil
if e.ProtocolDetails != nil {
if any, err := e.ProtocolDetails.MarshalToWireFormat(); err == nil {
detailsEntity = any
}
}
return &EventEntity{
Id: e.ID,
Timestamp: timestamppb.New(e.Timestamp),
Transport: e.Transport,
Application: e.Application,
SourceIP: sourceIP,
DestinationIP: destinationIP,
SourcePort: uint32(e.SourcePort),
DestinationPort: uint32(e.DestinationPort),
Tls: tlsDetails,
ProtocolDetails: detailsEntity,
}
}
func (e *Event) ApplyDefaults(id int64) {
e.ID = id
emptyTime := time.Time{}
if e.Timestamp == emptyTime {
e.Timestamp = time.Now().UTC()
}
}
func (e *Event) SetSourceIPFromAddr(remoteAddr net.Addr) {
ip, port := parseIPPortFromAddr(remoteAddr)
e.SourceIP = ip
e.SourcePort = port
}
func (e *Event) SetDestinationIPFromAddr(localAddr net.Addr) {
ip, port := parseIPPortFromAddr(localAddr)
e.DestinationIP = ip
e.DestinationPort = port
}
func NewEventFromProto(msg *EventEntity) (ev Event) {
var sourceIP net.IP
switch ip := msg.GetSourceIP().(type) {
case *EventEntity_SourceIPv4:
sourceIP = uint32ToIP(ip.SourceIPv4)
case *EventEntity_SourceIPv6:
sourceIP = uint64ToIP(ip.SourceIPv6)
}
var destinationIP net.IP
switch ip := msg.GetDestinationIP().(type) {
case *EventEntity_DestinationIPv4:
destinationIP = uint32ToIP(ip.DestinationIPv4)
case *EventEntity_DestinationIPv6:
destinationIP = uint64ToIP(ip.DestinationIPv6)
}
ev = Event{
ID: msg.GetId(),
Timestamp: msg.GetTimestamp().AsTime(),
Transport: msg.GetTransport(),
Application: msg.GetApplication(),
SourceIP: sourceIP,
DestinationIP: destinationIP,
SourcePort: uint16(msg.GetSourcePort()),
DestinationPort: uint16(msg.GetDestinationPort()),
ProtocolDetails: guessDetailsFromApp(msg.GetProtocolDetails()),
TLS: NewTLSDetailsFromProto(msg.GetTls()),
}
return
}
func parseIPPortFromAddr(addr net.Addr) (ip net.IP, port uint16) {
switch a := addr.(type) {
case *net.TCPAddr:
return a.IP, uint16(a.Port)
case *net.UDPAddr:
return a.IP, uint16(a.Port)
case *net.UnixAddr:
return
default:
ipPortSplit := strings.Split(addr.String(), ":")
if len(ipPortSplit) != 2 {
return
}
ip = net.ParseIP(ipPortSplit[0])
if p, err := strconv.Atoi(ipPortSplit[1]); err == nil {
port = uint16(p)
}
return
}
}
func guessDetailsFromApp(any *anypb.Any) Details {
var detailsProto proto.Message
var err error
if detailsProto, err = any.UnmarshalNew(); err != nil {
return nil
}
switch any.TypeUrl {
case "type.googleapis.com/inetmock.audit.HTTPDetailsEntity":
return details.NewHTTPFromWireFormat(detailsProto.(*details.HTTPDetailsEntity))
case "type.googleapis.com/inetmock.audit.DNSDetailsEntity":
return details.NewDNSFromWireFormat(detailsProto.(*details.DNSDetailsEntity))
default:
return nil
}
}