From 811f0ba5b3c032dfbcd138db6e4c59a1c75550a5 Mon Sep 17 00:00:00 2001 From: Alex McGrath Date: Fri, 29 Mar 2024 19:19:58 +0000 Subject: [PATCH 1/2] Include system annotations in audit event entries --- lib/auth/auth.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 3358e9df1f53a..5ff34ef587307 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -4837,6 +4837,16 @@ func (a *Server) CreateAccessRequestV2(ctx context.Context, req types.AccessRequ if _, err := a.Services.CreateAccessRequestV2(ctx, req); err != nil { return nil, trace.Wrap(err) } + + var annotations *apievents.Struct + if len(req.GetSystemAnnotations()) > 0 { + var err error + annotations, err = apievents.EncodeMapStrings(req.GetSystemAnnotations()) + if err != nil { + log.WithError(err).Debugf("Failed to encode access request annotations.") + } + } + err := a.emitter.EmitAuditEvent(a.closeCtx, &apievents.AccessRequestCreate{ Metadata: apievents.Metadata{ Type: events.AccessRequestCreateEvent, @@ -4852,6 +4862,7 @@ func (a *Server) CreateAccessRequestV2(ctx context.Context, req types.AccessRequ RequestState: req.GetState().String(), Reason: req.GetRequestReason(), MaxDuration: req.GetMaxDuration(), + Annotations: annotations, }) if err != nil { log.WithError(err).Warn("Failed to emit access request create event.") @@ -4952,6 +4963,13 @@ func (a *Server) SetAccessRequestState(ctx context.Context, params types.AccessR Roles: params.Roles, AssumeStartTime: params.AssumeStartTime, } + if len(req.GetSystemAnnotations()) > 0 { + var err error + event.Annotations, err = apievents.EncodeMapStrings(req.GetSystemAnnotations()) + if err != nil { + log.WithError(err).Debugf("Failed to encode access request annotations.") + } + } if delegator := apiutils.GetDelegator(ctx); delegator != "" { event.Delegator = delegator From c6179d78083a92abfc8ec685da2e1ccfca038f9d Mon Sep 17 00:00:00 2001 From: Alex McGrath Date: Tue, 2 Apr 2024 13:54:39 +0100 Subject: [PATCH 2/2] resolve comments, add test --- lib/auth/auth.go | 12 ++++----- lib/auth/auth_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/lib/auth/auth.go b/lib/auth/auth.go index 5ff34ef587307..4961bdf43e016 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -4839,11 +4839,11 @@ func (a *Server) CreateAccessRequestV2(ctx context.Context, req types.AccessRequ } var annotations *apievents.Struct - if len(req.GetSystemAnnotations()) > 0 { + if sa := req.GetSystemAnnotations(); len(sa) > 0 { var err error - annotations, err = apievents.EncodeMapStrings(req.GetSystemAnnotations()) + annotations, err = apievents.EncodeMapStrings(sa) if err != nil { - log.WithError(err).Debugf("Failed to encode access request annotations.") + log.WithError(err).Debug("Failed to encode access request annotations.") } } @@ -4963,11 +4963,11 @@ func (a *Server) SetAccessRequestState(ctx context.Context, params types.AccessR Roles: params.Roles, AssumeStartTime: params.AssumeStartTime, } - if len(req.GetSystemAnnotations()) > 0 { + if sa := req.GetSystemAnnotations(); len(sa) > 0 { var err error - event.Annotations, err = apievents.EncodeMapStrings(req.GetSystemAnnotations()) + event.Annotations, err = apievents.EncodeMapStrings(sa) if err != nil { - log.WithError(err).Debugf("Failed to encode access request annotations.") + log.WithError(err).Debug("Failed to encode access request annotations.") } } diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go index beb3f210aafe5..54adab3c1f3eb 100644 --- a/lib/auth/auth_test.go +++ b/lib/auth/auth_test.go @@ -3810,3 +3810,61 @@ func TestGetTokens(t *testing.T) { _, err = s.a.GetTokens(ctx) require.NoError(t, err) } + +func TestAccessRequestAuditLog(t *testing.T) { + t.Parallel() + ctx := context.Background() + + p, err := newTestPack(ctx, t.TempDir()) + require.NoError(t, err) + + requester, _, _ := createSessionTestUsers(t, p.a) + + paymentsRole, err := types.NewRole("paymentsRole", types.RoleSpecV6{ + Allow: types.RoleConditions{ + Request: &types.AccessRequestConditions{ + Roles: []string{"requestRole"}, + Annotations: map[string][]string{ + "pagerduty_services": {"payments"}, + }, + }, + }, + }) + require.NoError(t, err) + + requestRole, err := types.NewRole("requestRole", types.RoleSpecV6{}) + require.NoError(t, err) + + p.a.CreateRole(ctx, requestRole) + p.a.CreateRole(ctx, paymentsRole) + + user, err := p.a.GetUser(ctx, requester, true) + require.NoError(t, err) + user.AddRole(paymentsRole.GetName()) + _, err = p.a.UpsertUser(ctx, user) + require.NoError(t, err) + + accessRequest, err := types.NewAccessRequest(uuid.NewString(), requester, "requestRole") + require.NoError(t, err) + req, err := p.a.CreateAccessRequestV2(ctx, accessRequest, TestUser(requester).I.GetIdentity()) + require.NoError(t, err) + + expectedAnnotations, err := apievents.EncodeMapStrings(paymentsRole.GetAccessRequestConditions(types.Allow).Annotations) + require.NoError(t, err) + + arc, ok := p.mockEmitter.LastEvent().(*apievents.AccessRequestCreate) + require.True(t, ok) + require.Equal(t, expectedAnnotations, arc.Annotations) + require.Equal(t, "PENDING", arc.RequestState) + + err = p.a.SetAccessRequestState(ctx, types.AccessRequestUpdate{ + RequestID: req.GetName(), + State: types.RequestState_APPROVED, + }) + require.NoError(t, err) + + arc, ok = p.mockEmitter.LastEvent().(*apievents.AccessRequestCreate) + require.True(t, ok) + require.Equal(t, expectedAnnotations, arc.Annotations) + require.Equal(t, "APPROVED", arc.RequestState) +}