Skip to content

Commit

Permalink
feat: add client metadata to database session start event
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielcorado committed Jan 2, 2025
1 parent 061b0e2 commit aaae0ed
Show file tree
Hide file tree
Showing 9 changed files with 931 additions and 845 deletions.
6 changes: 6 additions & 0 deletions api/proto/teleport/legacy/types/events/events.proto
Original file line number Diff line number Diff line change
Expand Up @@ -3123,6 +3123,12 @@ message DatabaseSessionStart {
// connection. This can be useful for backend process cancellation or
// termination and it is not a sensitive or secret value.
uint32 PostgresPID = 8 [(gogoproto.jsontag) = "postgres_pid,omitempty"];
// Client is the common client event metadata.
ClientMetadata Client = 9 [
(gogoproto.nullable) = false,
(gogoproto.embed) = true,
(gogoproto.jsontag) = ""
];
}

// DatabaseSessionQuery is emitted when a user executes a database query.
Expand Down
1,725 changes: 886 additions & 839 deletions api/types/events/events.pb.go

Large diffs are not rendered by default.

16 changes: 11 additions & 5 deletions lib/srv/db/access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1629,13 +1629,13 @@ func (c *testContext) startHandlingConnections() {

// postgresClient connects to test Postgres through database access as a
// specified Teleport user and database account.
func (c *testContext) postgresClient(ctx context.Context, teleportUser, dbService, dbUser, dbName string) (*pgconn.PgConn, error) {
return c.postgresClientWithAddr(ctx, c.mux.DB().Addr().String(), teleportUser, dbService, dbUser, dbName)
func (c *testContext) postgresClient(ctx context.Context, teleportUser, dbService, dbUser, dbName string, opts ...common.ClientOption) (*pgconn.PgConn, error) {
return c.postgresClientWithAddr(ctx, c.mux.DB().Addr().String(), teleportUser, dbService, dbUser, dbName, opts...)
}

// postgresClientWithAddr is like postgresClient but allows to override connection address.
func (c *testContext) postgresClientWithAddr(ctx context.Context, address, teleportUser, dbService, dbUser, dbName string) (*pgconn.PgConn, error) {
return postgres.MakeTestClient(ctx, common.TestClientConfig{
func (c *testContext) postgresClientWithAddr(ctx context.Context, address, teleportUser, dbService, dbUser, dbName string, opts ...common.ClientOption) (*pgconn.PgConn, error) {
cfg := common.TestClientConfig{
AuthClient: c.authClient,
AuthServer: c.authServer,
Address: address,
Expand All @@ -1647,7 +1647,13 @@ func (c *testContext) postgresClientWithAddr(ctx context.Context, address, telep
Username: dbUser,
Database: dbName,
},
})
}

for _, opt := range opts {
opt(&cfg)
}

return postgres.MakeTestClient(ctx, cfg)
}

// postgresClientLocalProxy connects to test Postgres through local ALPN proxy.
Expand Down
5 changes: 4 additions & 1 deletion lib/srv/db/audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (
"github.com/gravitational/teleport/lib/defaults"
libevents "github.com/gravitational/teleport/lib/events"
"github.com/gravitational/teleport/lib/events/eventstest"
"github.com/gravitational/teleport/lib/srv/db/common"
"github.com/gravitational/teleport/lib/srv/db/postgres"
"github.com/gravitational/teleport/lib/srv/db/redis"
)
Expand All @@ -59,12 +60,14 @@ func TestAuditPostgres(t *testing.T) {
requireEvent(t, testCtx, libevents.DatabaseSessionStartFailureCode)

// Connect should trigger successful session start event.
psql, err := testCtx.postgresClient(ctx, "alice", "postgres", "postgres", "postgres")
userAgent := "psql"
psql, err := testCtx.postgresClient(ctx, "alice", "postgres", "postgres", "postgres", common.WithParams(map[string]string{"application_name": userAgent}))
require.NoError(t, err)
startEvt, ok := requireEvent(t, testCtx, libevents.DatabaseSessionStartCode).(*events.DatabaseSessionStart)
require.True(t, ok)
require.NotNil(t, startEvt)
require.NotZero(t, startEvt.PostgresPID)
require.Equal(t, userAgent, startEvt.ClientMetadata.UserAgent)

// Simple query should trigger the query event.
_, err = psql.Exec(ctx, "select 1").ReadAll()
Expand Down
3 changes: 3 additions & 0 deletions lib/srv/db/common/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ func (a *audit) OnSessionStart(ctx context.Context, session *Session, sessionErr
Success: true,
},
PostgresPID: session.PostgresPID,
ClientMetadata: events.ClientMetadata{
UserAgent: session.UserAgent,
},
}
event.SetTime(session.StartTime)

Expand Down
2 changes: 2 additions & 0 deletions lib/srv/db/common/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ type Session struct {
StartTime time.Time
// PostgresPID is the Postgres backend PID for the session.
PostgresPID uint32
// UserAgent identifies the type of client used on the session.
UserAgent string
}

// String returns string representation of the session parameters.
Expand Down
13 changes: 13 additions & 0 deletions lib/srv/db/common/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,16 @@ func MakeTestServerTLSConfig(config TestServerConfig) (*tls.Config, error) {
}, nil
}

// ClientOption represents a database client config option.
type ClientOption func(config *TestClientConfig)

// WithParams set client config params.
func WithParams(params map[string]string) ClientOption {
return func(config *TestClientConfig) {
config.Params = params
}
}

// TestClientConfig combines parameters for a test Postgres/MySQL client.
type TestClientConfig struct {
// AuthClient will be used to retrieve trusted CA.
Expand All @@ -176,6 +186,9 @@ type TestClientConfig struct {
PinnedIP string
// RouteToDatabase contains database routing information.
RouteToDatabase tlsca.RouteToDatabase
// Params contains parameters used during the session. This can hold, for
// example, PostgreSQL runtime parameters.
Params map[string]string
}

// MakeTestClientTLSCert returns TLS certificate suitable for configuring test
Expand Down
3 changes: 3 additions & 0 deletions lib/srv/db/postgres/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ func (e *Engine) handleStartup(client *pgproto3.Backend, sessionCtx *common.Sess
sessionCtx.DatabaseName = value
case "user":
sessionCtx.DatabaseUser = value
// https://www.postgresql.org/docs/17/libpq-connect.html#LIBPQ-CONNECT-APPLICATION-NAME
case "application_name":
sessionCtx.UserAgent = value
default:
sessionCtx.StartupParameters[key] = value
}
Expand Down
3 changes: 3 additions & 0 deletions lib/srv/db/postgres/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ func MakeTestClient(ctx context.Context, config common.TestClientConfig) (*pgcon
pgconnConfig.User = config.RouteToDatabase.Username
pgconnConfig.Database = config.RouteToDatabase.Database
pgconnConfig.TLSConfig, err = common.MakeTestClientTLSConfig(config)
for name, value := range config.Params {
pgconnConfig.RuntimeParams[name] = value
}
if err != nil {
return nil, trace.Wrap(err)
}
Expand Down

0 comments on commit aaae0ed

Please sign in to comment.