Peter Kurfer
af0a7a2375
- 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.
131 lines
3.2 KiB
Go
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
|
|
}
|
|
}
|