Files
teleport/lib/restrictedsession/audit.go
T
Vitor Enes c96809399a Add server_hostname to session.* events (#18812)
With this commit, `session.*` events now also contain a `server_hostname` field.

Example:

```json
{
  "argv": null,
  "cgroup_id": 6926,
  "cluster_name": "vitor.teleport.sh",
  "code": "T4000I",
  "ei": 17,
  "event": "session.command",
  "login": "root",
  "namespace": "default",
  "path": "/usr/bin/date",
  "pid": 98679,
  "ppid": 98668,
  "program": "date",
  "return_code": 0,
  "server_hostname": "ip-172-31-10-157",
  "server_id": "8369d1d1-eea5-4074-8f64-0103f1e1fb00",
  "sid": "a40353c4-93dc-4d6b-a481-5546ecafb83e",
  "time": "2022-11-28T16:32:34.342Z",
  "uid": "cbd9e562-8932-405d-974c-11637f91d711",
  "user": "vitor@goteleport.com"
}
```
2022-11-28 20:28:41 +00:00

159 lines
4.1 KiB
Go

//go:build bpf && !386
// +build bpf,!386
/*
Copyright 2020 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package restrictedsession
import (
"bytes"
"encoding/binary"
"fmt"
"net"
"unsafe"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/lib/bpf"
api "github.com/gravitational/teleport/lib/events"
)
const (
BlockedIP4 = iota
BlockedIP6
)
//
// Audit Event types communicated between the kernel and userspace
//
// auditEventHeader matches audit_event_header in the C file
type auditEventHeader struct {
CGroupID uint64
PID uint32
EventType int32
Command [bpf.CommMax]byte
}
// auditEventBlockedIPv4 matches audit_event_blocked_ipv4 in the C file
type auditEventBlockedIPv4 struct {
SrcIP [4]byte
DstIP [4]byte
DstPort uint16
Op uint8
}
// auditEventBlockedIPv6 matches audit_event_blocked_ipv6 in the C file
type auditEventBlockedIPv6 struct {
SrcIP [16]byte
DstIP [16]byte
DstPort uint16
Op uint8
}
// newNetworkAuditEvent creates events.SessionNetwork, filling in common fields
// from the SessionContext
func newNetworkAuditEvent(ctx *bpf.SessionContext, hdr *auditEventHeader) events.SessionNetwork {
return events.SessionNetwork{
Metadata: events.Metadata{
Type: api.SessionNetworkEvent,
Code: api.SessionNetworkCode,
},
ServerMetadata: events.ServerMetadata{
ServerID: ctx.ServerID,
ServerHostname: ctx.ServerHostname,
ServerNamespace: ctx.Namespace,
},
SessionMetadata: events.SessionMetadata{
SessionID: ctx.SessionID,
},
UserMetadata: events.UserMetadata{
User: ctx.User,
Login: ctx.Login,
},
BPFMetadata: events.BPFMetadata{
CgroupID: hdr.CGroupID,
Program: bpf.ConvertString(unsafe.Pointer(&hdr.Command)),
PID: uint64(hdr.PID),
},
}
}
// parseAuditEventHeader parse the header portion of the event.
// buf is consumed so that only body bytes remain.
func parseAuditEventHeader(buf *bytes.Buffer) (auditEventHeader, error) {
var hdr auditEventHeader
err := binary.Read(buf, binary.LittleEndian, &hdr)
if err != nil {
return auditEventHeader{}, trace.BadParameter("corrupt event header: %v", err)
}
return hdr, nil
}
// ip6String is similar to IP.String but retains mapped addresses
// in IPv6 form.
func ip6String(ip net.IP) string {
var prefix string
if ip.To4() != nil {
// IP4 mapped address
prefix = "::ffff:"
}
return prefix + ip.String()
}
// parseAuditEvent parses the body of the audit event
func parseAuditEvent(buf *bytes.Buffer, hdr *auditEventHeader, ctx *bpf.SessionContext) (events.AuditEvent, error) {
switch hdr.EventType {
case BlockedIP4:
var body auditEventBlockedIPv4
if err := binary.Read(buf, binary.LittleEndian, &body); err != nil {
return nil, trace.Wrap(err)
}
event := newNetworkAuditEvent(ctx, hdr)
event.DstPort = int32(body.DstPort)
event.DstAddr = net.IP(body.DstIP[:]).String()
event.SrcAddr = net.IP(body.SrcIP[:]).String()
event.TCPVersion = 4
event.Operation = events.SessionNetwork_NetworkOperation(body.Op)
event.Action = events.EventAction_DENIED
return &event, nil
case BlockedIP6:
var body auditEventBlockedIPv6
if err := binary.Read(buf, binary.LittleEndian, &body); err != nil {
return nil, trace.Wrap(err)
}
event := newNetworkAuditEvent(ctx, hdr)
event.DstPort = int32(body.DstPort)
event.DstAddr = ip6String(net.IP(body.DstIP[:]))
event.SrcAddr = ip6String(net.IP(body.SrcIP[:]))
event.TCPVersion = 6
event.Operation = events.SessionNetwork_NetworkOperation(body.Op)
event.Action = events.EventAction_DENIED
return &event, nil
}
return nil, fmt.Errorf("received unknown event type: %v", hdr.EventType)
}