api/pkg/audit/event.go
Peter Kurfer af0a7a2375
Capture source and destination addresses as byte arrays
- update necessary tests

This removes a lot of complexity because IPv4 and IPv6 addresses can be handled the same way.
To distinguish between them it's enough to take their length into account.
Parsing should be straight forward in any language.
2021-01-26 18:20:51 +01:00

131 lines
3.2 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() *EventEntity {
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: e.SourceIP,
DestinationIP: e.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) {
ev = Event{
ID: msg.GetId(),
Timestamp: msg.GetTimestamp().AsTime(),
Transport: msg.GetTransport(),
Application: msg.GetApplication(),
SourceIP: msg.SourceIP,
DestinationIP: msg.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
}
}