From d34e1575e6bb72fa28daf36fe8b4979a07af56fc Mon Sep 17 00:00:00 2001 From: Tobiasz Heller Date: Wed, 17 May 2023 12:01:36 +0200 Subject: [PATCH 1/2] athena audit logs - pass teleport user as top level field --- api/types/events/metadata.go | 5 ++++ lib/events/athena/consumer_test.go | 2 +- lib/events/athena/integration_test.go | 1 + .../athena/testdata/events_2023-04-01.parquet | Bin 3413 -> 3597 bytes .../athena/testdata/events_2023-04-02.parquet | Bin 2249 -> 2385 bytes lib/events/athena/types.go | 3 +- lib/events/dynamic.go | 14 ++++++++- lib/events/dynamic_test.go | 28 ++++++++++++++++++ 8 files changed, 50 insertions(+), 3 deletions(-) mode change 100644 => 100755 lib/events/athena/testdata/events_2023-04-01.parquet mode change 100644 => 100755 lib/events/athena/testdata/events_2023-04-02.parquet diff --git a/api/types/events/metadata.go b/api/types/events/metadata.go index 8103f5ab7e94d..03ed89cab5471 100644 --- a/api/types/events/metadata.go +++ b/api/types/events/metadata.go @@ -102,3 +102,8 @@ func (m *ServerMetadata) SetServerNamespace(ns string) { func (m *SessionMetadata) GetSessionID() string { return m.SessionID } + +// GetUser returns event teleport user +func (m *UserMetadata) GetUser() string { + return m.User +} diff --git a/lib/events/athena/consumer_test.go b/lib/events/athena/consumer_test.go index 69246ee3a11f5..e226981d7619f 100644 --- a/lib/events/athena/consumer_test.go +++ b/lib/events/athena/consumer_test.go @@ -589,7 +589,7 @@ func TestErrHandlingFnFromSQS(t *testing.T) { }) } -// TestConsumerWriteToS3 is writing parquet files per date works. +// TestConsumerWriteToS3 checks if writing parquet files per date works. // It receives events from different dates and make sure that multiple // files are created and compare it against file in testdata. // Testdata files should be verified with "parquet tools" cli after changing. diff --git a/lib/events/athena/integration_test.go b/lib/events/athena/integration_test.go index 3f0a407e2d0ba..9463eda0d00c7 100644 --- a/lib/events/athena/integration_test.go +++ b/lib/events/athena/integration_test.go @@ -387,6 +387,7 @@ CREATE EXTERNAL TABLE %s ( session_id string, event_type string, event_time timestamp, + user string, event_data string ) PARTITIONED BY ( diff --git a/lib/events/athena/testdata/events_2023-04-01.parquet b/lib/events/athena/testdata/events_2023-04-01.parquet old mode 100644 new mode 100755 index 4c9b9f481e0195ff7c6ad4188cf5e512781ddbc3..2a9f304ff2322a950436096d84712af9c4b6fee6 GIT binary patch delta 263 zcmcaA)hn~%G~?tIjLMr=Feb20e#OSWnS))4$(l!ufkEsVyC{zs69a>!j@TRy(HD#$ zu}gv=22fCxNwUV2L4v;^v8b>#wIn`0KfWkGzeJR0au8<|D@$o{YSH9{oT8Jja>_8~ zO#Z|f$$m#gR7I>qdU6m~7<+@NsG8U}>B;N4^x2nz*jHpGKjkuWIRj#Uk`a|-P@BLm zBg!Lb%ErMUDFHT4lu3+5tc6jmhY=`eBf%iSAjY5pB!RB_1kyG^7Nl(s$7Bs|1(rD+ wHWHH+SXWLKV6vNR%=4CShMK6B*g9F!b?gjc52PmR@yc_gurM$LI0hL40BF@g8vpy dwZvLvMAxx1h~1H#{ESzgLxhEaA;2-n5CHglGZg>; diff --git a/lib/events/athena/testdata/events_2023-04-02.parquet b/lib/events/athena/testdata/events_2023-04-02.parquet old mode 100644 new mode 100755 index 86ebff17303f003a5da203cc1f5af54442bcc481..96fd361151e2acb479a6a6ee159a606ba74df6b9 GIT binary patch delta 252 zcmX>pcu{D=%Z;pt07~~tV|yngDkk=CvKE^j zdy6oTxs7jfJe!HrED-w~pQr?b+8JgUQ65QCHVy_!39w0`Okzx8PGW9A85;=(2?j9+ z4Is(DAhrRd=^0qlB$mkw*c4bMvDipVe#rQA@;$~^W@5*LMJ2@k@rmAHW)NG(E5^j2 jAqjP`ZhF2#S!z*nW`3SRPGU)FaS1~d3j;%dV~`;LhxI;L@J!a?l;_}KVPFVw H3^D`&DY7dz diff --git a/lib/events/athena/types.go b/lib/events/athena/types.go index db08d3b70ebbc..2bfc4a3b448d6 100644 --- a/lib/events/athena/types.go +++ b/lib/events/athena/types.go @@ -24,13 +24,13 @@ import ( "github.com/gravitational/teleport/lib/utils" ) -// TODO(tobiaszheller): pass user at some point. type eventParquet struct { EventType string `parquet:"name=event_type, type=BYTE_ARRAY, convertedtype=UTF8"` // TODO(tobiaszheller): what precision of timestamp we want. AWS supports micros, maybe we can use it instead of mili? EventTime int64 `parquet:"name=event_time, type=INT64, convertedtype=TIMESTAMP_MILLIS"` UID string `parquet:"name=uid, type=BYTE_ARRAY, convertedtype=UTF8"` SessionID string `parquet:"name=session_id, type=BYTE_ARRAY, convertedtype=UTF8"` + User string `parquet:"name=user, type=BYTE_ARRAY, convertedtype=UTF8"` EventData string `parquet:"name=event_data, type=BYTE_ARRAY, convertedtype=UTF8"` } @@ -49,6 +49,7 @@ func auditEventToParquet(event apievents.AuditEvent) (*eventParquet, error) { EventTime: event.GetTime().UnixMilli(), UID: event.GetID(), SessionID: events.GetSessionID(event), + User: events.GetTeleportUser(event), EventData: string(jsonBlob), }, nil } diff --git a/lib/events/dynamic.go b/lib/events/dynamic.go index edb6032811dd3..8885cc23026c2 100644 --- a/lib/events/dynamic.go +++ b/lib/events/dynamic.go @@ -47,7 +47,7 @@ func FromEventFields(fields EventFields) (events.AuditEvent, error) { return s } - var eventType = getFieldEmpty(EventType) + eventType := getFieldEmpty(EventType) var e events.AuditEvent switch eventType { @@ -354,6 +354,18 @@ func GetSessionID(event events.AuditEvent) string { return sessionID } +// GetTeleportUser pulls the teleport user from the events that have a +// UserMetadata. For other events an empty string is returned. +func GetTeleportUser(event events.AuditEvent) string { + type userGetter interface { + GetUser() string + } + if g, ok := event.(userGetter); ok { + return g.GetUser() + } + return "" +} + // ToEventFields converts from the typed interface-style event representation // to the old dynamic map style representation in order to provide outer compatibility // with existing public API routes when the backend is updated with the typed events. diff --git a/lib/events/dynamic_test.go b/lib/events/dynamic_test.go index 01c964ea14944..7bda40ab1e482 100644 --- a/lib/events/dynamic_test.go +++ b/lib/events/dynamic_test.go @@ -68,3 +68,31 @@ func TestDynamicKnownType(t *testing.T) { printEvent := event.(*events.SessionPrint) require.Equal(t, SessionPrintEvent, printEvent.GetType()) } + +func TestGetTeleportUser(t *testing.T) { + tests := []struct { + name string + event events.AuditEvent + want string + }{ + { + name: "event without user metadata", + event: &events.InstanceJoin{}, + want: "", + }, + { + name: "event with user metadata", + event: &events.SessionStart{ + UserMetadata: events.UserMetadata{ + User: "user-1", + }, + }, + want: "user-1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, GetTeleportUser(tt.event)) + }) + } +} From be73737d03ef55f7a780f6dca25e59787fa6aa90 Mon Sep 17 00:00:00 2001 From: Tobiasz Heller Date: Mon, 22 May 2023 10:33:17 +0200 Subject: [PATCH 2/2] permission on testdata to 644 --- .../athena/testdata/events_2023-04-01.parquet | Bin .../athena/testdata/events_2023-04-02.parquet | Bin 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 lib/events/athena/testdata/events_2023-04-01.parquet mode change 100755 => 100644 lib/events/athena/testdata/events_2023-04-02.parquet diff --git a/lib/events/athena/testdata/events_2023-04-01.parquet b/lib/events/athena/testdata/events_2023-04-01.parquet old mode 100755 new mode 100644 diff --git a/lib/events/athena/testdata/events_2023-04-02.parquet b/lib/events/athena/testdata/events_2023-04-02.parquet old mode 100755 new mode 100644