From a886934325fce29b84a6241429616b17acc36828 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Thu, 18 Apr 2024 17:08:36 +0100 Subject: [PATCH 01/43] Add initial condition parser for access monitoring rules --- integrations/access/accessrequest/app.go | 143 +++++++++++++++++- .../access/accessrequest/request_mapping.go | 114 ++++++++++++++ lib/expression/parser.go | 24 +++ 3 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 integrations/access/accessrequest/request_mapping.go diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index cca57b2d12423..fcb5b5c825f38 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -21,12 +21,14 @@ package accessrequest import ( "context" "fmt" + "sync" "time" "github.com/gravitational/trace" "github.com/gravitational/teleport/api/accessrequest" "github.com/gravitational/teleport/api/types" + accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" "github.com/gravitational/teleport/integrations/access/common" "github.com/gravitational/teleport/integrations/access/common/teleport" "github.com/gravitational/teleport/integrations/lib" @@ -50,11 +52,24 @@ type App struct { pluginData *pd.CompareAndSwap[PluginData] bot MessagingBot job lib.ServiceJob + + accessMonitoringRules amrMap +} + +type amrMap struct { + sync.RWMutex + rules map[string]*accessmonitoringrulesv1.AccessMonitoringRule +} + +func newAMRMap() *amrMap { + return &amrMap{ + rules: make(map[string]*accessmonitoringrulesv1.AccessMonitoringRule), + } } // NewApp will create a new access request application. func NewApp(bot MessagingBot) common.App { - app := &App{} + app := &App{accessMonitoringRules: *newAMRMap()} app.job = lib.NewServiceJob(app.run) return app } @@ -111,7 +126,10 @@ func (a *App) run(ctx context.Context) error { job, err := watcherjob.NewJob( a.apiClient, watcherjob.Config{ - Watch: types.Watch{Kinds: []types.WatchKind{{Kind: types.KindAccessRequest}}}, + Watch: types.Watch{Kinds: []types.WatchKind{ + {Kind: types.KindAccessRequest}, + {Kind: types.KindAccessMonitoringRule}, + }}, EventFuncTimeout: handlerTimeout, }, a.onWatcherEvent, @@ -120,6 +138,19 @@ func (a *App) run(ctx context.Context) error { return trace.Wrap(err) } + amrs, err := a.getAllAccessMonitoringRules(ctx) + if err != nil { + return trace.Wrap(err) + } + a.accessMonitoringRules.Lock() + for _, amr := range amrs { + if !a.checkIfAMRIsRelevent(amr) { + continue + } + a.accessMonitoringRules.rules[amr.GetMetadata().Name] = amr + } + a.accessMonitoringRules.Unlock() + process.SpawnCriticalJob(job) ok, err := job.WaitReady(ctx) @@ -136,9 +167,25 @@ func (a *App) run(ctx context.Context) error { return nil } +func (a *App) checkIfAMRIsRelevent(amr *accessmonitoringrulesv1.AccessMonitoringRule) bool { + if amr.Spec.Notification.Name != a.pluginName { + return false + } + for _, subject := range amr.Spec.Subjects { + if subject == types.KindAccessRequest { + return true + } + } + return false +} + // onWatcherEvent is called for every cluster Event. It will filter out non-access-request events and // call onPendingRequest, onResolvedRequest and on DeletedRequest depending on the event. func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { + if kind := event.Resource.GetKind(); kind == types.KindAccessMonitoringRule { + return trace.Wrap(a.handleAccessMonitoringRule(ctx, event)) + } + if kind := event.Resource.GetKind(); kind != types.KindAccessRequest { return trace.Errorf("unexpected kind %s", kind) } @@ -185,6 +232,39 @@ func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { } } +func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) error { + if kind := event.Resource.GetKind(); kind != types.KindAccessMonitoringRule { + return trace.Errorf("unexpected kind %s", kind) + } + + req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) + if !ok { + return trace.Errorf("unexpected resource type %T", event.Resource) + } + + if !a.checkIfAMRIsRelevent(req) { + return nil + } + + op := event.Type + switch op { + case types.OpPut: + a.accessMonitoringRules.Lock() + defer a.accessMonitoringRules.Unlock() + a.accessMonitoringRules.rules[req.Metadata.Name] = req + return nil + case types.OpDelete: + a.accessMonitoringRules.Lock() + defer a.accessMonitoringRules.Unlock() + if _, ok := a.accessMonitoringRules.rules[req.Metadata.Name]; ok { + delete(a.accessMonitoringRules.rules, req.Metadata.Name) + } + return nil + default: + return trace.BadParameter("unexpected event operation %s", op) + } +} + func (a *App) onPendingRequest(ctx context.Context, req types.AccessRequest) error { log := logger.Get(ctx) @@ -345,6 +425,11 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) // This can happen if this set contains the channel `C` and the email for channel `C`. recipientSet := common.NewRecipientSet() + recipients := a.recipientsFromAccessMonitoringRules(ctx, req) + for _, recipient := range recipients.ToSlice() { + recipientSet.Add(recipient) + } + switch a.pluginType { case types.PluginTypeServiceNow: // The ServiceNow plugin does not use recipients currently and create incidents in the incident table directly. @@ -389,6 +474,40 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) return recipientSet.ToSlice() } +func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types.AccessRequest) *common.RecipientSet { + log := logger.Get(ctx) + recipientSet := common.NewRecipientSet() + + // This switch is used to determine which plugins we are enabling access monitoring notification rules for. + switch a.pluginType { + // Enabled plugins are added to this case. + case types.PluginTypeSlack, types.PluginTypeOpsgenie: + log.Debug("Applying access monitoring rules to request") + default: + return &recipientSet + } + + a.accessMonitoringRules.RLock() + defer a.accessMonitoringRules.RUnlock() + + for _, rule := range a.accessMonitoringRules.rules { + match, err := matchAccessRequest(rule.Spec.Condition, req) + if err != nil { + log.WithError(err).Warn("Failed to parse access monitoring notification rule") + } + if match { + for _, recipient := range rule.Spec.Notification.Recipients { + rec, err := a.bot.FetchRecipient(ctx, recipient) + if err != nil { + log.Warning(err) + } + recipientSet.Add(*rec) + } + } + } + return &recipientSet +} + // updateMessages updates the messages status and adds the resolve reason. func (a *App) updateMessages(ctx context.Context, reqID string, tag pd.ResolutionTag, reason string, reviews []types.AccessReview) error { log := logger.Get(ctx) @@ -461,3 +580,23 @@ func (a *App) getResourceNames(ctx context.Context, req types.AccessRequest) ([] } return resourceNames, nil } + +func (a *App) getAllAccessMonitoringRules(ctx context.Context) ([]*accessmonitoringrulesv1.AccessMonitoringRule, error) { + var resources []*accessmonitoringrulesv1.AccessMonitoringRule + var nextToken string + for { + var page []*accessmonitoringrulesv1.AccessMonitoringRule + var err error + page, nextToken, err = a.apiClient.ListAccessMonitoringRules(ctx, 0 /* page size */, nextToken) + if err != nil { + return nil, trace.Wrap(err) + } + + resources = append(resources, page...) + + if nextToken == "" { + break + } + } + return resources, nil +} diff --git a/integrations/access/accessrequest/request_mapping.go b/integrations/access/accessrequest/request_mapping.go new file mode 100644 index 0000000000000..ee1ada60f1509 --- /dev/null +++ b/integrations/access/accessrequest/request_mapping.go @@ -0,0 +1,114 @@ +/* +Copyright 2024 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 accessrequest + +import ( + "time" + + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/expression" + "github.com/gravitational/teleport/lib/utils/typical" + "github.com/gravitational/trace" +) + +const ( + timeFormat = time.RFC3339 // "2006-01-02T15:04:05Z07:00" +) + +// accessRequestExpressionEnv holds user details that can be mapped in an +// access request condition assertion. +type accessRequestExpressionEnv struct { + // e.g access_request.spec.roles.contains('prod-rw') + Roles []string + SuggestedReviewers []string + Annotations map[string][]string + User string + RequestReason string + CreationTime time.Time + Expiry time.Time +} + +type accessRequestExpression typical.Expression[accessRequestExpressionEnv, any] + +func parseAccessRequestExpression(expr string) (accessRequestExpression, error) { + parser, err := newRequestConditionParser() + parsedExpr, err := parser.Parse(expr) + if err != nil { + return nil, trace.Wrap(err, "parsing label expression") + } + return parsedExpr, nil +} + +func newRequestConditionParser() (*typical.Parser[accessRequestExpressionEnv, any], error) { + typicalEnvVar := map[string]typical.Variable{ + "true": true, + "false": false, + "access_request.spec.roles": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (expression.Set, error) { + return expression.NewSet(env.Roles...), nil + }), + "access_request.spec.suggested_reviewers": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (expression.Set, error) { + return expression.NewSet(env.SuggestedReviewers...), nil + }), + "access_request.spec.system_annotations": typical.DynamicMap[accessRequestExpressionEnv, expression.Set](func(env accessRequestExpressionEnv) (expression.Dict, error) { + return expression.DictFromStringSliceMap(env.Annotations), nil + }), + "access_request.spec.user": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (string, error) { + return env.User, nil + }), + "access_request.spec.request_reason": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (string, error) { + return env.RequestReason, nil + }), + "access_request.spec.creation_time": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (time.Time, error) { + return env.CreationTime, nil + }), + "access_request.spec.expiry": typical.DynamicVariable[accessRequestExpressionEnv](func(env accessRequestExpressionEnv) (time.Time, error) { + return env.Expiry, nil + }), + } + defParserSpec := expression.DefaultParserSpec[accessRequestExpressionEnv]() + defParserSpec.Variables = typicalEnvVar + + requestConditionParser, err := typical.NewParser[accessRequestExpressionEnv, any](defParserSpec) + if err != nil { + return nil, trace.Wrap(err) + } + return requestConditionParser, nil +} + +func matchAccessRequest(expr string, req types.AccessRequest) (bool, error) { + parsedExpr, err := parseAccessRequestExpression(expr) + if err != nil { + return false, trace.Wrap(err) + } + + match, err := parsedExpr.Evaluate(accessRequestExpressionEnv{ + Roles: req.GetRoles(), + SuggestedReviewers: req.GetSuggestedReviewers(), + Annotations: req.GetSystemAnnotations(), + User: req.GetUser(), + RequestReason: req.GetRequestReason(), + CreationTime: req.GetCreationTime(), + Expiry: req.Expiry(), + }) + if err != nil { + return false, trace.Wrap(err, "evaluating label expression %q", expr) + } + if matched, ok := match.(bool); ok && matched { + return true, nil + } + return false, nil +} diff --git a/lib/expression/parser.go b/lib/expression/parser.go index 3678d4c84d469..b7b147ab804ac 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -20,6 +20,7 @@ package expression import ( "strings" + "time" "github.com/gravitational/trace" @@ -104,6 +105,10 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { } return NewSet(outputs...), nil }), + "time.RFC3339": typical.UnaryFunction[evaluationEnv]( + func(input string) (time.Time, error) { + return time.Parse(time.RFC3339, input) + }), }, Methods: map[string]typical.Function{ "add": typical.BinaryVariadicFunction[evaluationEnv]( @@ -126,6 +131,25 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { func(r remover, items ...string) (any, error) { return r.remove(items...), nil }), + "before": typical.BinaryFunction[evaluationEnv]( + func(t time.Time, other time.Time) (bool, error) { + return t.Before(other), nil + }), + "after": typical.BinaryFunction[evaluationEnv]( + func(t time.Time, other time.Time) (bool, error) { + return t.After(other), nil + }), + "between": typical.BinaryVariadicFunction[evaluationEnv]( + func(t time.Time, interval ...time.Time) (bool, error) { + if len(interval) != 2 { + return false, trace.BadParameter("time.between expected 2 parameters: got %v", len(interval)) + } + first, second := interval[0], interval[1] + if first.After(second) { + first, second = second, first + } + return t.After(first) && t.Before(second), nil + }), }, } } From b04af8d0b6197060263a091c98dbf6f77cc0419d Mon Sep 17 00:00:00 2001 From: Edward Dowling Date: Mon, 22 Apr 2024 16:16:25 +0100 Subject: [PATCH 02/43] Update integrations/access/accessrequest/app.go Co-authored-by: Zac Bergquist --- integrations/access/accessrequest/app.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index fcb5b5c825f38..c9b521f69440c 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -246,8 +246,7 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) return nil } - op := event.Type - switch op { + switch op := event.Type; op { case types.OpPut: a.accessMonitoringRules.Lock() defer a.accessMonitoringRules.Unlock() From 5b44f85fe3eba468a1d84353e8fd0e245381d8f0 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Mon, 22 Apr 2024 16:21:53 +0100 Subject: [PATCH 03/43] Check previously unchecked error and minor refactor of AMR --- integrations/access/accessrequest/app.go | 15 ++++++--------- .../access/accessrequest/request_mapping.go | 4 +++- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index c9b521f69440c..29e8f52339d7f 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -61,15 +61,11 @@ type amrMap struct { rules map[string]*accessmonitoringrulesv1.AccessMonitoringRule } -func newAMRMap() *amrMap { - return &amrMap{ - rules: make(map[string]*accessmonitoringrulesv1.AccessMonitoringRule), - } -} - // NewApp will create a new access request application. func NewApp(bot MessagingBot) common.App { - app := &App{accessMonitoringRules: *newAMRMap()} + app := &App{accessMonitoringRules: amrMap{ + rules: make(map[string]*accessmonitoringrulesv1.AccessMonitoringRule), + }} app.job = lib.NewServiceJob(app.run) return app } @@ -138,12 +134,12 @@ func (a *App) run(ctx context.Context) error { return trace.Wrap(err) } - amrs, err := a.getAllAccessMonitoringRules(ctx) + accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) if err != nil { return trace.Wrap(err) } a.accessMonitoringRules.Lock() - for _, amr := range amrs { + for _, amr := range accessMonitoringRules { if !a.checkIfAMRIsRelevent(amr) { continue } @@ -499,6 +495,7 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types rec, err := a.bot.FetchRecipient(ctx, recipient) if err != nil { log.Warning(err) + continue } recipientSet.Add(*rec) } diff --git a/integrations/access/accessrequest/request_mapping.go b/integrations/access/accessrequest/request_mapping.go index ee1ada60f1509..9e534b9215b97 100644 --- a/integrations/access/accessrequest/request_mapping.go +++ b/integrations/access/accessrequest/request_mapping.go @@ -32,7 +32,6 @@ const ( // accessRequestExpressionEnv holds user details that can be mapped in an // access request condition assertion. type accessRequestExpressionEnv struct { - // e.g access_request.spec.roles.contains('prod-rw') Roles []string SuggestedReviewers []string Annotations map[string][]string @@ -46,6 +45,9 @@ type accessRequestExpression typical.Expression[accessRequestExpressionEnv, any] func parseAccessRequestExpression(expr string) (accessRequestExpression, error) { parser, err := newRequestConditionParser() + if err != nil { + return nil, trace.Wrap(err) + } parsedExpr, err := parser.Parse(expr) if err != nil { return nil, trace.Wrap(err, "parsing label expression") From bcfe0435556ef1e43c5bc435ea6b412161c9f1e2 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Mon, 22 Apr 2024 16:26:14 +0100 Subject: [PATCH 04/43] Simplify check for applicable access monitoring rules --- integrations/access/accessrequest/app.go | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 29e8f52339d7f..a853e01efc42b 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -21,14 +21,15 @@ package accessrequest import ( "context" "fmt" + "slices" "sync" "time" "github.com/gravitational/trace" "github.com/gravitational/teleport/api/accessrequest" - "github.com/gravitational/teleport/api/types" accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/integrations/access/common" "github.com/gravitational/teleport/integrations/access/common/teleport" "github.com/gravitational/teleport/integrations/lib" @@ -140,7 +141,7 @@ func (a *App) run(ctx context.Context) error { } a.accessMonitoringRules.Lock() for _, amr := range accessMonitoringRules { - if !a.checkIfAMRIsRelevent(amr) { + if !a.amrAppliesToThisPlugin(amr) { continue } a.accessMonitoringRules.rules[amr.GetMetadata().Name] = amr @@ -163,16 +164,13 @@ func (a *App) run(ctx context.Context) error { return nil } -func (a *App) checkIfAMRIsRelevent(amr *accessmonitoringrulesv1.AccessMonitoringRule) bool { +func (a *App) amrAppliesToThisPlugin(amr *accessmonitoringrulesv1.AccessMonitoringRule) bool { if amr.Spec.Notification.Name != a.pluginName { return false } - for _, subject := range amr.Spec.Subjects { - if subject == types.KindAccessRequest { - return true - } - } - return false + return slices.ContainsFunc(amr.Spec.Subjects, func(subject string) bool { + return subject == types.KindAccessRequest + }) } // onWatcherEvent is called for every cluster Event. It will filter out non-access-request events and @@ -233,12 +231,12 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) return trace.Errorf("unexpected kind %s", kind) } - req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) + req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) if !ok { return trace.Errorf("unexpected resource type %T", event.Resource) } - if !a.checkIfAMRIsRelevent(req) { + if !a.amrAppliesToThisPlugin(req) { return nil } From 4d7e1af098b673249f6e0c410f27146eaa7bc6da Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 23 Apr 2024 16:08:40 +0100 Subject: [PATCH 05/43] Refactor access monitoring rules plugin integration --- integrations/access/accessrequest/app.go | 45 ++++++++++++------------ lib/expression/parser.go | 2 +- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index a853e01efc42b..c53c87e055253 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -135,6 +135,12 @@ func (a *App) run(ctx context.Context) error { return trace.Wrap(err) } + process.SpawnCriticalJob(job) + + ok, err := job.WaitReady(ctx) + if err != nil { + return trace.Wrap(err) + } accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) if err != nil { return trace.Wrap(err) @@ -148,13 +154,6 @@ func (a *App) run(ctx context.Context) error { } a.accessMonitoringRules.Unlock() - process.SpawnCriticalJob(job) - - ok, err := job.WaitReady(ctx) - if err != nil { - return trace.Wrap(err) - } - a.job.SetReady(ok) if !ok { return trace.BadParameter("job not ready") @@ -176,13 +175,16 @@ func (a *App) amrAppliesToThisPlugin(amr *accessmonitoringrulesv1.AccessMonitori // onWatcherEvent is called for every cluster Event. It will filter out non-access-request events and // call onPendingRequest, onResolvedRequest and on DeletedRequest depending on the event. func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { - if kind := event.Resource.GetKind(); kind == types.KindAccessMonitoringRule { + switch event.Resource.GetKind() { + case types.KindAccessMonitoringRule: return trace.Wrap(a.handleAccessMonitoringRule(ctx, event)) + case types.KindAccessRequest: + return trace.Wrap(a.handleAcessRequest(ctx, event)) } + return trace.Errorf("unexpected kind %s", event.Resource.GetKind()) +} - if kind := event.Resource.GetKind(); kind != types.KindAccessRequest { - return trace.Errorf("unexpected kind %s", kind) - } +func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { op := event.Type reqID := event.Resource.GetName() ctx, _ = logger.WithField(ctx, "request_id", reqID) @@ -249,9 +251,7 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) case types.OpDelete: a.accessMonitoringRules.Lock() defer a.accessMonitoringRules.Unlock() - if _, ok := a.accessMonitoringRules.rules[req.Metadata.Name]; ok { - delete(a.accessMonitoringRules.rules, req.Metadata.Name) - } + delete(a.accessMonitoringRules.rules, req.Metadata.Name) return nil default: return trace.BadParameter("unexpected event operation %s", op) @@ -488,15 +488,16 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types if err != nil { log.WithError(err).Warn("Failed to parse access monitoring notification rule") } - if match { - for _, recipient := range rule.Spec.Notification.Recipients { - rec, err := a.bot.FetchRecipient(ctx, recipient) - if err != nil { - log.Warning(err) - continue - } - recipientSet.Add(*rec) + if !match { + continue + } + for _, recipient := range rule.Spec.Notification.Recipients { + rec, err := a.bot.FetchRecipient(ctx, recipient) + if err != nil { + log.Warning(err) + continue } + recipientSet.Add(*rec) } } return &recipientSet diff --git a/lib/expression/parser.go b/lib/expression/parser.go index b7b147ab804ac..7353c4e7318b5 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -142,7 +142,7 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { "between": typical.BinaryVariadicFunction[evaluationEnv]( func(t time.Time, interval ...time.Time) (bool, error) { if len(interval) != 2 { - return false, trace.BadParameter("time.between expected 2 parameters: got %v", len(interval)) + return false, trace.BadParameter("between expected 2 parameters: got %v", len(interval)) } first, second := interval[0], interval[1] if first.After(second) { From aa82adcec32de3aa6ba7cc4465631216c99b8a8b Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 23 Apr 2024 16:23:58 +0100 Subject: [PATCH 06/43] Fix formating and move lock aquisition --- integrations/access/accessrequest/app.go | 6 ++---- lib/expression/parser.go | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index c53c87e055253..267b9046612c6 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -242,15 +242,13 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) return nil } + a.accessMonitoringRules.Lock() + defer a.accessMonitoringRules.Unlock() switch op := event.Type; op { case types.OpPut: - a.accessMonitoringRules.Lock() - defer a.accessMonitoringRules.Unlock() a.accessMonitoringRules.rules[req.Metadata.Name] = req return nil case types.OpDelete: - a.accessMonitoringRules.Lock() - defer a.accessMonitoringRules.Unlock() delete(a.accessMonitoringRules.rules, req.Metadata.Name) return nil default: diff --git a/lib/expression/parser.go b/lib/expression/parser.go index 7353c4e7318b5..df69ae8ec4f1a 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -146,7 +146,7 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { } first, second := interval[0], interval[1] if first.After(second) { - first, second = second, first + first, second = second, first } return t.After(first) && t.Before(second), nil }), From 257ca064516a444fd6c2d98283de79382ab419c9 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 26 Apr 2024 16:10:00 +0100 Subject: [PATCH 07/43] Add methods for listing access monitoring rules with a filter --- .../access_monitoring_rules_client.go | 14 ++ .../v1/access_monitoring_rules.pb.go | 173 ++++++++++++++---- .../v1/access_monitoring_rules_service.pb.go | 67 ++++--- ...access_monitoring_rules_service_grpc.pb.go | 51 +++++- .../v1/access_monitoring_rules.proto | 15 +- .../v1/access_monitoring_rules_service.proto | 3 + lib/services/local/access_monitoring_rules.go | 62 ++++++- 7 files changed, 315 insertions(+), 70 deletions(-) diff --git a/api/client/accessmonitoringrules/access_monitoring_rules_client.go b/api/client/accessmonitoringrules/access_monitoring_rules_client.go index ee641bf9c2ead..fff91ceaf2f48 100644 --- a/api/client/accessmonitoringrules/access_monitoring_rules_client.go +++ b/api/client/accessmonitoringrules/access_monitoring_rules_client.go @@ -109,3 +109,17 @@ func (c *Client) ListAccessMonitoringRules(ctx context.Context, pageSize int, pa } return resp.Rules, resp.GetNextPageToken(), nil } + +// ListAccessMonitoringRulesWithFilter lists current access monitoring rules. +func (c *Client) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { + resp, err := c.grpcClient.ListAccessMonitoringRulesWithFilter(ctx, &accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest{ + PageSize: int64(pageSize), + PageToken: pageToken, + Subjects: subjects, + NotificationName: notificationName, + }) + if err != nil { + return nil, "", trace.Wrap(err) + } + return resp.Rules, resp.GetNextPageToken(), nil +} diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go index 66af7ada863ea..59507c1530fb3 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go @@ -500,7 +500,7 @@ func (x *DeleteAccessMonitoringRuleRequest) GetName() string { return "" } -// ListAccessMonitoringRulesResponse is the request for ListAccessMonitoringRules. +// ListAccessMonitoringRulesRequest is the request for ListAccessMonitoringRules. type ListAccessMonitoringRulesRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -559,6 +559,83 @@ func (x *ListAccessMonitoringRulesRequest) GetPageToken() string { return "" } +// ListAccessMonitoringRulesWithFilterRequest is the request for ListAccessMonitoringRulesWithFilter. +type ListAccessMonitoringRulesWithFilterRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // page_size is the maximum number of items to return. + // The server may impose a different page size at its discretion. + PageSize int64 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` + // page_token is the next_page_token value returned from a previous List request, if any. + PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` + // subjects are the subjects the access monitoring rules must have. + Subjects []string `protobuf:"bytes,3,rep,name=subjects,proto3" json:"subjects,omitempty"` + // notification_name is the value of the notification name field the rule must have. + NotificationName string `protobuf:"bytes,4,opt,name=notification_name,json=notificationName,proto3" json:"notification_name,omitempty"` +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) Reset() { + *x = ListAccessMonitoringRulesWithFilterRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAccessMonitoringRulesWithFilterRequest) ProtoMessage() {} + +func (x *ListAccessMonitoringRulesWithFilterRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAccessMonitoringRulesWithFilterRequest.ProtoReflect.Descriptor instead. +func (*ListAccessMonitoringRulesWithFilterRequest) Descriptor() ([]byte, []int) { + return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescGZIP(), []int{9} +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) GetPageSize() int64 { + if x != nil { + return x.PageSize + } + return 0 +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) GetPageToken() string { + if x != nil { + return x.PageToken + } + return "" +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) GetSubjects() []string { + if x != nil { + return x.Subjects + } + return nil +} + +func (x *ListAccessMonitoringRulesWithFilterRequest) GetNotificationName() string { + if x != nil { + return x.NotificationName + } + return "" +} + // ListAccessMonitoringRulesResponse is the response from ListAccessMonitoringRules. type ListAccessMonitoringRulesResponse struct { state protoimpl.MessageState @@ -575,7 +652,7 @@ type ListAccessMonitoringRulesResponse struct { func (x *ListAccessMonitoringRulesResponse) Reset() { *x = ListAccessMonitoringRulesResponse{} if protoimpl.UnsafeEnabled { - mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[9] + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -588,7 +665,7 @@ func (x *ListAccessMonitoringRulesResponse) String() string { func (*ListAccessMonitoringRulesResponse) ProtoMessage() {} func (x *ListAccessMonitoringRulesResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[9] + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[10] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -601,7 +678,7 @@ func (x *ListAccessMonitoringRulesResponse) ProtoReflect() protoreflect.Message // Deprecated: Use ListAccessMonitoringRulesResponse.ProtoReflect.Descriptor instead. func (*ListAccessMonitoringRulesResponse) Descriptor() ([]byte, []int) { - return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescGZIP(), []int{9} + return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescGZIP(), []int{10} } func (x *ListAccessMonitoringRulesResponse) GetRules() []*AccessMonitoringRule { @@ -695,24 +772,35 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDesc 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, - 0x6e, 0x22, 0x9a, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, - 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, - 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x6e, - 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, - 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, - 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x22, 0xb1, 0x01, 0x0a, 0x2a, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, + 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x08, 0x70, 0x61, 0x67, 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, + 0x0a, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x70, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, + 0x73, 0x75, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x6e, 0x6f, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, + 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x05, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, + 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x42, 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -727,22 +815,23 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDes return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescData } -var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 10) +var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_goTypes = []interface{}{ - (*AccessMonitoringRule)(nil), // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule - (*AccessMonitoringRuleSpec)(nil), // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec - (*Notification)(nil), // 2: teleport.accessmonitoringrules.v1.Notification - (*CreateAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest - (*UpdateAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest - (*UpsertAccessMonitoringRuleRequest)(nil), // 5: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest - (*GetAccessMonitoringRuleRequest)(nil), // 6: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest - (*DeleteAccessMonitoringRuleRequest)(nil), // 7: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest - (*ListAccessMonitoringRulesRequest)(nil), // 8: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - (*ListAccessMonitoringRulesResponse)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse - (*v1.Metadata)(nil), // 10: teleport.header.v1.Metadata + (*AccessMonitoringRule)(nil), // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule + (*AccessMonitoringRuleSpec)(nil), // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec + (*Notification)(nil), // 2: teleport.accessmonitoringrules.v1.Notification + (*CreateAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest + (*UpdateAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest + (*UpsertAccessMonitoringRuleRequest)(nil), // 5: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest + (*GetAccessMonitoringRuleRequest)(nil), // 6: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest + (*DeleteAccessMonitoringRuleRequest)(nil), // 7: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest + (*ListAccessMonitoringRulesRequest)(nil), // 8: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest + (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + (*ListAccessMonitoringRulesResponse)(nil), // 10: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + (*v1.Metadata)(nil), // 11: teleport.header.v1.Metadata } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_depIdxs = []int32{ - 10, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule.metadata:type_name -> teleport.header.v1.Metadata + 11, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule.metadata:type_name -> teleport.header.v1.Metadata 1, // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRule.spec:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec 2, // 2: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec.notification:type_name -> teleport.accessmonitoringrules.v1.Notification 0, // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest.rule:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule @@ -871,6 +960,18 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_init() } } file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListAccessMonitoringRulesWithFilterRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ListAccessMonitoringRulesResponse); i { case 0: return &v.state @@ -889,7 +990,7 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_init() GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDesc, NumEnums: 0, - NumMessages: 10, + NumMessages: 11, NumExtensions: 0, NumServices: 0, }, diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go index 07442dcb492a3..c2ca292664e65 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go @@ -49,7 +49,7 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xb5, 0x07, 0x0a, 0x1c, 0x41, + 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xf2, 0x08, 0x0a, 0x1c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, @@ -109,26 +109,39 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x73, 0x65, 0x12, 0xba, 0x01, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4d, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, + 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, + 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, + 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, + 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x76, 0x31, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto_goTypes = []interface{}{ - (*CreateAccessMonitoringRuleRequest)(nil), // 0: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest - (*UpdateAccessMonitoringRuleRequest)(nil), // 1: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest - (*UpsertAccessMonitoringRuleRequest)(nil), // 2: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest - (*GetAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest - (*DeleteAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest - (*ListAccessMonitoringRulesRequest)(nil), // 5: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - (*AccessMonitoringRule)(nil), // 6: teleport.accessmonitoringrules.v1.AccessMonitoringRule - (*emptypb.Empty)(nil), // 7: google.protobuf.Empty - (*ListAccessMonitoringRulesResponse)(nil), // 8: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + (*CreateAccessMonitoringRuleRequest)(nil), // 0: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest + (*UpdateAccessMonitoringRuleRequest)(nil), // 1: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest + (*UpsertAccessMonitoringRuleRequest)(nil), // 2: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest + (*GetAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest + (*DeleteAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest + (*ListAccessMonitoringRulesRequest)(nil), // 5: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest + (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 6: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + (*AccessMonitoringRule)(nil), // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRule + (*emptypb.Empty)(nil), // 8: google.protobuf.Empty + (*ListAccessMonitoringRulesResponse)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto_depIdxs = []int32{ 0, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest @@ -137,14 +150,16 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto 3, // 3: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest 4, // 4: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest 5, // 5: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - 6, // 6: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 6, // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 6, // 8: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 6, // 9: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 7, // 10: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:output_type -> google.protobuf.Empty - 8, // 11: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse - 6, // [6:12] is the sub-list for method output_type - 0, // [0:6] is the sub-list for method input_type + 6, // 6: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + 7, // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 8: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 9: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 10: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 8, // 11: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:output_type -> google.protobuf.Empty + 9, // 12: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + 9, // 13: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + 7, // [7:14] is the sub-list for method output_type + 0, // [0:7] is the sub-list for method input_type 0, // [0:0] is the sub-list for extension type_name 0, // [0:0] is the sub-list for extension extendee 0, // [0:0] is the sub-list for field type_name diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go index 3c3216510001b..591ac1a084700 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go @@ -34,12 +34,13 @@ import ( const _ = grpc.SupportPackageIsVersion7 const ( - AccessMonitoringRulesService_CreateAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/CreateAccessMonitoringRule" - AccessMonitoringRulesService_UpdateAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/UpdateAccessMonitoringRule" - AccessMonitoringRulesService_UpsertAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/UpsertAccessMonitoringRule" - AccessMonitoringRulesService_GetAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/GetAccessMonitoringRule" - AccessMonitoringRulesService_DeleteAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/DeleteAccessMonitoringRule" - AccessMonitoringRulesService_ListAccessMonitoringRules_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/ListAccessMonitoringRules" + AccessMonitoringRulesService_CreateAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/CreateAccessMonitoringRule" + AccessMonitoringRulesService_UpdateAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/UpdateAccessMonitoringRule" + AccessMonitoringRulesService_UpsertAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/UpsertAccessMonitoringRule" + AccessMonitoringRulesService_GetAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/GetAccessMonitoringRule" + AccessMonitoringRulesService_DeleteAccessMonitoringRule_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/DeleteAccessMonitoringRule" + AccessMonitoringRulesService_ListAccessMonitoringRules_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/ListAccessMonitoringRules" + AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_FullMethodName = "/teleport.accessmonitoringrules.v1.AccessMonitoringRulesService/ListAccessMonitoringRulesWithFilter" ) // AccessMonitoringRulesServiceClient is the client API for AccessMonitoringRulesService service. @@ -58,6 +59,8 @@ type AccessMonitoringRulesServiceClient interface { DeleteAccessMonitoringRule(ctx context.Context, in *DeleteAccessMonitoringRuleRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) // ListAccessMonitoringRules lists current access monitoring rules. ListAccessMonitoringRules(ctx context.Context, in *ListAccessMonitoringRulesRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) + // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. + ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) } type accessMonitoringRulesServiceClient struct { @@ -122,6 +125,15 @@ func (c *accessMonitoringRulesServiceClient) ListAccessMonitoringRules(ctx conte return out, nil } +func (c *accessMonitoringRulesServiceClient) ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) { + out := new(ListAccessMonitoringRulesResponse) + err := c.cc.Invoke(ctx, AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // AccessMonitoringRulesServiceServer is the server API for AccessMonitoringRulesService service. // All implementations must embed UnimplementedAccessMonitoringRulesServiceServer // for forward compatibility @@ -138,6 +150,8 @@ type AccessMonitoringRulesServiceServer interface { DeleteAccessMonitoringRule(context.Context, *DeleteAccessMonitoringRuleRequest) (*emptypb.Empty, error) // ListAccessMonitoringRules lists current access monitoring rules. ListAccessMonitoringRules(context.Context, *ListAccessMonitoringRulesRequest) (*ListAccessMonitoringRulesResponse, error) + // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. + ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesResponse, error) mustEmbedUnimplementedAccessMonitoringRulesServiceServer() } @@ -163,6 +177,9 @@ func (UnimplementedAccessMonitoringRulesServiceServer) DeleteAccessMonitoringRul func (UnimplementedAccessMonitoringRulesServiceServer) ListAccessMonitoringRules(context.Context, *ListAccessMonitoringRulesRequest) (*ListAccessMonitoringRulesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListAccessMonitoringRules not implemented") } +func (UnimplementedAccessMonitoringRulesServiceServer) ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListAccessMonitoringRulesWithFilter not implemented") +} func (UnimplementedAccessMonitoringRulesServiceServer) mustEmbedUnimplementedAccessMonitoringRulesServiceServer() { } @@ -285,6 +302,24 @@ func _AccessMonitoringRulesService_ListAccessMonitoringRules_Handler(srv interfa return interceptor(ctx, in, info, handler) } +func _AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListAccessMonitoringRulesWithFilterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccessMonitoringRulesServiceServer).ListAccessMonitoringRulesWithFilter(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccessMonitoringRulesServiceServer).ListAccessMonitoringRulesWithFilter(ctx, req.(*ListAccessMonitoringRulesWithFilterRequest)) + } + return interceptor(ctx, in, info, handler) +} + // AccessMonitoringRulesService_ServiceDesc is the grpc.ServiceDesc for AccessMonitoringRulesService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -316,6 +351,10 @@ var AccessMonitoringRulesService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListAccessMonitoringRules", Handler: _AccessMonitoringRulesService_ListAccessMonitoringRules_Handler, }, + { + MethodName: "ListAccessMonitoringRulesWithFilter", + Handler: _AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto", diff --git a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto index 1b4e101ce849c..ae859ef52c977 100644 --- a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto +++ b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto @@ -85,7 +85,7 @@ message DeleteAccessMonitoringRuleRequest { string name = 1; } -// ListAccessMonitoringRulesResponse is the request for ListAccessMonitoringRules. +// ListAccessMonitoringRulesRequest is the request for ListAccessMonitoringRules. message ListAccessMonitoringRulesRequest { // page_size is the maximum number of items to return. // The server may impose a different page size at its discretion. @@ -94,6 +94,19 @@ message ListAccessMonitoringRulesRequest { string page_token = 2; } +// ListAccessMonitoringRulesWithFilterRequest is the request for ListAccessMonitoringRulesWithFilter. +message ListAccessMonitoringRulesWithFilterRequest { + // page_size is the maximum number of items to return. + // The server may impose a different page size at its discretion. + int64 page_size = 1; + // page_token is the next_page_token value returned from a previous List request, if any. + string page_token = 2; + // subjects are the subjects the access monitoring rules must have. + repeated string subjects = 3; + // notification_name is the value of the notification name field the rule must have. + string notification_name = 4; +} + // ListAccessMonitoringRulesResponse is the response from ListAccessMonitoringRules. message ListAccessMonitoringRulesResponse { // The page of AccessMonitoringRule that matched the request. diff --git a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto index 55ee27692cadf..3828d9253abbf 100644 --- a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto +++ b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto @@ -40,4 +40,7 @@ service AccessMonitoringRulesService { // ListAccessMonitoringRules lists current access monitoring rules. rpc ListAccessMonitoringRules(ListAccessMonitoringRulesRequest) returns (ListAccessMonitoringRulesResponse); + + // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. + rpc ListAccessMonitoringRulesWithFilter(ListAccessMonitoringRulesWithFilterRequest) returns (ListAccessMonitoringRulesResponse); } diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index deeafcead11ce..75564cbf25cd0 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -20,6 +20,7 @@ package local import ( "context" + "slices" "github.com/gravitational/trace" @@ -34,7 +35,8 @@ const accessMonitoringRulesPrefix = "access_monitoring_rule" // AccessMonitoringRulesService manages AccessMonitoringRules in the Backend. type AccessMonitoringRulesService struct { - svc *generic.ServiceWrapper[*accessmonitoringrulesv1.AccessMonitoringRule] + backend backend.Backend + svc *generic.ServiceWrapper[*accessmonitoringrulesv1.AccessMonitoringRule] } // NewAccessMonitoringRulesService creates a new AccessMonitoringRulesService. @@ -110,3 +112,61 @@ func (s *AccessMonitoringRulesService) DeleteAccessMonitoringRule(ctx context.Co func (s *AccessMonitoringRulesService) DeleteAllAccessMonitoringRules(ctx context.Context) error { return trace.Wrap(s.svc.DeleteAllResources(ctx)) } + +func (s *AccessMonitoringRulesService) listResourcesListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { + + var keyPrefix []string + var unmarshalItemFunc backendItemToResourceFunc + + rangeStart := backend.Key(accessMonitoringRulesPrefix, pageToken) + rangeEnd := backend.RangeEnd(backend.ExactKey(keyPrefix...)) + + // Get most limit+1 results to determine if there will be a next key. + maxLimit := pageSize + 1 + var resources []*accessmonitoringrulesv1.AccessMonitoringRule + if err := backend.IterateRange(ctx, s.backend, rangeStart, rangeEnd, maxLimit, func(items []backend.Item) (stop bool, err error) { + for _, item := range items { + if len(resources) == maxLimit { + break + } + + resource, err := unmarshalItemFunc(item) + if err != nil { + return false, trace.Wrap(err) + } + accessMonitoringRule := types.LegacyToResource153(resource).(*accessmonitoringrulesv1.AccessMonitoringRule) + if ok := match(accessMonitoringRule, subjects, notificationName); ok { + resources = append(resources, accessMonitoringRule) + } + } + + return len(resources) == maxLimit, nil + }); err != nil { + return nil, "", trace.Wrap(err) + } + + var nextKey string + if len(resources) > pageSize { + nextKey = resources[len(resources)-1].Metadata.Name + // Truncate the last item that was used to determine next row existence. + resources = resources[:pageSize] + } + + return resources, nextKey, nil +} + +func match(rule *accessmonitoringrulesv1.AccessMonitoringRule, subjects []string, notificationName string) bool { + for _, subject := range subjects { + if ok := slices.ContainsFunc(rule.Spec.Subjects, func(s string) bool { + return s == subject + }); !ok { + return false + } + } + if notificationName != "" { + if rule.Spec.Notification == nil || rule.Spec.Notification.Name != notificationName { + return false + } + } + return true +} From 6379cfc7752910dea15088f6a01c212fdece33dd Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 26 Apr 2024 17:19:18 +0100 Subject: [PATCH 08/43] Add contains_any predicate expression func --- lib/expression/parser.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/expression/parser.go b/lib/expression/parser.go index df69ae8ec4f1a..3108039d4926d 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -150,6 +150,15 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { } return t.After(first) && t.Before(second), nil }), + "contains_any": typical.BinaryFunction[evaluationEnv]( + func(s1 , s2 Set) (bool, error) { + for _, v := range s2.items() { + if s1.contains(v) { + return true, nil + } + } + return false, nil + }), }, } } From bbc0110e78382697658063374f94c3b43cf5a9cc Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 26 Apr 2024 17:22:53 +0100 Subject: [PATCH 09/43] Add in is_empty func to predicate expression --- lib/expression/parser.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/expression/parser.go b/lib/expression/parser.go index 3108039d4926d..496e321d4f30d 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -159,6 +159,10 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { } return false, nil }), + "is_empty": typical.UnaryFunction[evaluationEnv]( + func(s Set) (bool, error) { + return len(s) == 0, nil + }), }, } } From a43ee5e8d060814f464067098c95df9d748e411c Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Mon, 29 Apr 2024 16:31:23 +0100 Subject: [PATCH 10/43] Lock AMR cache in plugins while getting initial rules --- integrations/access/accessrequest/app.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 267b9046612c6..45b415669a79c 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -141,11 +141,12 @@ func (a *App) run(ctx context.Context) error { if err != nil { return trace.Wrap(err) } + + a.accessMonitoringRules.Lock() accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) if err != nil { return trace.Wrap(err) } - a.accessMonitoringRules.Lock() for _, amr := range accessMonitoringRules { if !a.amrAppliesToThisPlugin(amr) { continue From a231b9317f671c4bdf11adafb905ea85c80d635a Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 30 Apr 2024 16:55:16 +0100 Subject: [PATCH 11/43] Add in check for access monitoring rule version --- lib/services/access_monitoring_rules.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/services/access_monitoring_rules.go b/lib/services/access_monitoring_rules.go index b459389f6b08a..4facb1b6085ca 100644 --- a/lib/services/access_monitoring_rules.go +++ b/lib/services/access_monitoring_rules.go @@ -69,6 +69,9 @@ func ValidateAccessMonitoringRule(accessMonitoringRule *accessmonitoringrulesv1. if accessMonitoringRule.Metadata == nil { return trace.BadParameter("accessMonitoringRule metadata is missing") } + if accessMonitoringRule.Version != types.V1 { + return trace.BadParameter("accessMonitoringRule %q is not supported", accessMonitoringRule.Version) + } if accessMonitoringRule.Spec == nil { return trace.BadParameter("accessMonitoringRule spec is missing") } From 2df526d0183bcbc7c012266908bb9044f9346a08 Mon Sep 17 00:00:00 2001 From: Edward Dowling Date: Thu, 2 May 2024 15:33:45 +0100 Subject: [PATCH 12/43] Update integrations/access/accessrequest/app.go Co-authored-by: Roman Tkachenko --- integrations/access/accessrequest/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 45b415669a79c..8167c6dcb0eae 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -231,7 +231,7 @@ func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) error { if kind := event.Resource.GetKind(); kind != types.KindAccessMonitoringRule { - return trace.Errorf("unexpected kind %s", kind) + return trace.BadParameter("expected %s resource kind, got %s", types.KindAccessMonitoringRule, kind) } req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) From b585e1d581b0c88242c95a782fa7c5c552d8ddc3 Mon Sep 17 00:00:00 2001 From: Edward Dowling Date: Thu, 2 May 2024 15:33:57 +0100 Subject: [PATCH 13/43] Update integrations/access/accessrequest/app.go Co-authored-by: Roman Tkachenko --- integrations/access/accessrequest/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 8167c6dcb0eae..6b6d063507a02 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -236,7 +236,7 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) if !ok { - return trace.Errorf("unexpected resource type %T", event.Resource) + return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) } if !a.amrAppliesToThisPlugin(req) { From b7bd0286da6d4554f21355b5a826e6c0fdc950a3 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 3 May 2024 16:18:42 +0100 Subject: [PATCH 14/43] Move lock so it doesnt persist over api calls --- integrations/access/accessrequest/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 6b6d063507a02..1306ffd2a0832 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -142,11 +142,11 @@ func (a *App) run(ctx context.Context) error { return trace.Wrap(err) } - a.accessMonitoringRules.Lock() accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) if err != nil { return trace.Wrap(err) } + a.accessMonitoringRules.Lock() for _, amr := range accessMonitoringRules { if !a.amrAppliesToThisPlugin(amr) { continue From dac8ede6c3d3e89cc1f8efed7f7d14a5facac248 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 3 May 2024 16:22:10 +0100 Subject: [PATCH 15/43] Remove unused constant and add more context to logs --- integrations/access/accessrequest/app.go | 3 ++- integrations/access/accessrequest/request_mapping.go | 6 +----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 1306ffd2a0832..dd40331efdc36 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -485,7 +485,8 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types for _, rule := range a.accessMonitoringRules.rules { match, err := matchAccessRequest(rule.Spec.Condition, req) if err != nil { - log.WithError(err).Warn("Failed to parse access monitoring notification rule") + log.WithError(err).WithField("rule", rule.Metadata.Name). + Warn("Failed to parse access monitoring notification rule") } if !match { continue diff --git a/integrations/access/accessrequest/request_mapping.go b/integrations/access/accessrequest/request_mapping.go index 9e534b9215b97..1b1b0653678ba 100644 --- a/integrations/access/accessrequest/request_mapping.go +++ b/integrations/access/accessrequest/request_mapping.go @@ -25,10 +25,6 @@ import ( "github.com/gravitational/trace" ) -const ( - timeFormat = time.RFC3339 // "2006-01-02T15:04:05Z07:00" -) - // accessRequestExpressionEnv holds user details that can be mapped in an // access request condition assertion. type accessRequestExpressionEnv struct { @@ -107,7 +103,7 @@ func matchAccessRequest(expr string, req types.AccessRequest) (bool, error) { Expiry: req.Expiry(), }) if err != nil { - return false, trace.Wrap(err, "evaluating label expression %q", expr) + return false, trace.Wrap(err, "evaluating access monitoring rule condition expression %q", expr) } if matched, ok := match.(bool); ok && matched { return true, nil From a869de2b630f521694cb32b7d79481de6a1edbbe Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 3 May 2024 16:47:28 +0100 Subject: [PATCH 16/43] Appease linter --- integrations/access/accessrequest/request_mapping.go | 3 ++- lib/expression/parser.go | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integrations/access/accessrequest/request_mapping.go b/integrations/access/accessrequest/request_mapping.go index 1b1b0653678ba..538f2958da0c0 100644 --- a/integrations/access/accessrequest/request_mapping.go +++ b/integrations/access/accessrequest/request_mapping.go @@ -19,10 +19,11 @@ package accessrequest import ( "time" + "github.com/gravitational/trace" + "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/expression" "github.com/gravitational/teleport/lib/utils/typical" - "github.com/gravitational/trace" ) // accessRequestExpressionEnv holds user details that can be mapped in an diff --git a/lib/expression/parser.go b/lib/expression/parser.go index 496e321d4f30d..c72c7a12c553d 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -151,7 +151,7 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { return t.After(first) && t.Before(second), nil }), "contains_any": typical.BinaryFunction[evaluationEnv]( - func(s1 , s2 Set) (bool, error) { + func(s1, s2 Set) (bool, error) { for _, v := range s2.items() { if s1.contains(v) { return true, nil From 30ec018d860080cd0088fa5bab61fe7bb4853921 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 7 May 2024 13:51:27 +0100 Subject: [PATCH 17/43] Update access monitoring rules tests to pass rule validation --- .../accessmonitoringrulesv1/service_test.go | 23 ++++++++++--------- .../local/access_monitoring_rules_test.go | 6 +++-- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/lib/accessmonitoringrules/accessmonitoringrulesv1/service_test.go b/lib/accessmonitoringrules/accessmonitoringrulesv1/service_test.go index 446c5ebdc2a1a..6a2f28c109661 100644 --- a/lib/accessmonitoringrules/accessmonitoringrulesv1/service_test.go +++ b/lib/accessmonitoringrules/accessmonitoringrulesv1/service_test.go @@ -48,9 +48,10 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { ctx, localClient, resourceSvc := initSvc(t, clusterName) - sampleAccessMonitoringRuleFn := func(t *testing.T, name string) *accessmonitoringrulev1.AccessMonitoringRule { + sampleAccessMonitoringRuleFn := func(name string) *accessmonitoringrulev1.AccessMonitoringRule { return &accessmonitoringrulev1.AccessMonitoringRule{ Kind: types.KindAccessMonitoringRule, + Version: types.V1, Metadata: &v1.Metadata{Name: name}, Spec: &accessmonitoringrulev1.AccessMonitoringRuleSpec{ Subjects: []string{"someSubject"}, @@ -76,7 +77,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }}}, }, Setup: func(t *testing.T, amrName string) { - _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(t, amrName)) + _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(amrName)) require.NoError(t, err) }, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { @@ -126,7 +127,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }, Setup: func(t *testing.T, _ string) { for i := 0; i < 10; i++ { - _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(t, uuid.NewString())) + _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(uuid.NewString())) require.NoError(t, err) } }, @@ -162,7 +163,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { Name: "no access to create AccessMonitoringRules", Role: types.RoleSpecV6{}, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.CreateAccessMonitoringRule(ctx, &accessmonitoringrulev1.CreateAccessMonitoringRuleRequest{ Rule: amr, }) @@ -179,7 +180,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }}}, }, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.CreateAccessMonitoringRule(ctx, &accessmonitoringrulev1.CreateAccessMonitoringRuleRequest{ Rule: amr, }) @@ -193,7 +194,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { Name: "no access to update AccessMonitoringRule", Role: types.RoleSpecV6{}, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.UpdateAccessMonitoringRule(ctx, &accessmonitoringrulev1.UpdateAccessMonitoringRuleRequest{ Rule: amr, }) @@ -210,11 +211,11 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }}}, }, Setup: func(t *testing.T, amrName string) { - _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(t, amrName)) + _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(amrName)) require.NoError(t, err) }, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.UpdateAccessMonitoringRule(ctx, &accessmonitoringrulev1.UpdateAccessMonitoringRuleRequest{ Rule: amr, }) @@ -233,7 +234,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }}}, }, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.UpsertAccessMonitoringRule(ctx, &accessmonitoringrulev1.UpsertAccessMonitoringRuleRequest{ Rule: amr, }) @@ -251,7 +252,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }, Setup: func(t *testing.T, amrName string) {}, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { - amr := sampleAccessMonitoringRuleFn(t, amrName) + amr := sampleAccessMonitoringRuleFn(amrName) _, err := resourceSvc.UpsertAccessMonitoringRule(ctx, &accessmonitoringrulev1.UpsertAccessMonitoringRuleRequest{ Rule: amr, }) @@ -279,7 +280,7 @@ func TestAccessMonitoringRuleCRUD(t *testing.T) { }}}, }, Setup: func(t *testing.T, amrName string) { - _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(t, amrName)) + _, err := localClient.CreateAccessMonitoringRule(ctx, sampleAccessMonitoringRuleFn(amrName)) require.NoError(t, err) }, Test: func(ctx context.Context, resourceSvc *Service, amrName string) error { diff --git a/lib/services/local/access_monitoring_rules_test.go b/lib/services/local/access_monitoring_rules_test.go index 2cee8530b3cfc..3da99b029fcc5 100644 --- a/lib/services/local/access_monitoring_rules_test.go +++ b/lib/services/local/access_monitoring_rules_test.go @@ -49,7 +49,8 @@ func TestAccessMonitoringRulesCRUD(t *testing.T) { require.NoError(t, err) AccessMonitoringRule1 := &accessmonitoringrulesv1.AccessMonitoringRule{ - Kind: types.KindAccessMonitoringRule, + Kind: types.KindAccessMonitoringRule, + Version: types.V1, Metadata: &v1.Metadata{ Name: "p1", }, @@ -60,7 +61,8 @@ func TestAccessMonitoringRulesCRUD(t *testing.T) { } AccessMonitoringRule2 := &accessmonitoringrulesv1.AccessMonitoringRule{ - Kind: types.KindAccessMonitoringRule, + Kind: types.KindAccessMonitoringRule, + Version: types.V1, Metadata: &v1.Metadata{ Name: "p2", }, From 1fe70a4a3ca822096b164de160968db81f4046b9 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 7 May 2024 16:27:35 +0100 Subject: [PATCH 18/43] Add in missing access monitoring rules list with filter code --- integrations/access/accessrequest/app.go | 10 +++- integrations/access/common/config.go | 6 +- integrations/access/common/teleport/client.go | 2 +- .../accessmonitoringrulesv1/service.go | 20 +++++++ lib/auth/authclient/api.go | 2 + lib/cache/cache.go | 15 +++++ lib/cache/collections.go | 1 + lib/services/access_monitoring_rules.go | 56 +++++++++---------- lib/services/local/access_monitoring_rules.go | 2 +- 9 files changed, 79 insertions(+), 35 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index dd40331efdc36..25490fbd74fd0 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -41,6 +41,8 @@ import ( const ( // handlerTimeout is used to bound the execution time of watcher event handler. handlerTimeout = time.Second * 5 + // defaultAccessMonitoringRulePageSize is the default number of rules to retrieve per request + defaultAccessMonitoringRulePageSize = 10 ) // App is the access request application for plugins. This will notify when access requests @@ -421,6 +423,9 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) for _, recipient := range recipients.ToSlice() { recipientSet.Add(recipient) } + if len(recipientSet.ToSlice()) != 0 { + return recipientSet.ToSlice() + } switch a.pluginType { case types.PluginTypeServiceNow: @@ -473,7 +478,7 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types // This switch is used to determine which plugins we are enabling access monitoring notification rules for. switch a.pluginType { // Enabled plugins are added to this case. - case types.PluginTypeSlack, types.PluginTypeOpsgenie: + case types.PluginTypeSlack: log.Debug("Applying access monitoring rules to request") default: return &recipientSet @@ -582,7 +587,8 @@ func (a *App) getAllAccessMonitoringRules(ctx context.Context) ([]*accessmonitor for { var page []*accessmonitoringrulesv1.AccessMonitoringRule var err error - page, nextToken, err = a.apiClient.ListAccessMonitoringRules(ctx, 0 /* page size */, nextToken) + page, nextToken, err = a.apiClient.ListAccessMonitoringRulesWithFilter(ctx, defaultAccessMonitoringRulePageSize, nextToken, + []string{types.KindAccessRequest}, a.pluginName) if err != nil { return nil, trace.Wrap(err) } diff --git a/integrations/access/common/config.go b/integrations/access/common/config.go index e664373eae6b7..0a3dd48ba5465 100644 --- a/integrations/access/common/config.go +++ b/integrations/access/common/config.go @@ -58,9 +58,9 @@ func (w *wrappedClient) ListAccessLists(ctx context.Context, pageSize int, pageT return w.Client.AccessListClient().ListAccessLists(ctx, pageSize, pageToken) } -// ListAccessMonitoringRules lists current access monitoring rules. -func (w *wrappedClient) ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { - return w.Client.AccessMonitoringRulesClient().ListAccessMonitoringRules(ctx, limit, startKey) +// ListAccessMonitoringRulesWithFilter lists current access monitoring rules. +func (w *wrappedClient) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { + return w.Client.AccessMonitoringRulesClient().ListAccessMonitoringRulesWithFilter(ctx, pageSize, pageToken, subjects, notificationName) } // wrapAPIClient will wrap the API client such that it conforms to the Teleport plugin client interface. diff --git a/integrations/access/common/teleport/client.go b/integrations/access/common/teleport/client.go index 8e61120314f55..675c9578d939e 100644 --- a/integrations/access/common/teleport/client.go +++ b/integrations/access/common/teleport/client.go @@ -40,5 +40,5 @@ type Client interface { SetAccessRequestState(ctx context.Context, params types.AccessRequestUpdate) error ListResources(ctx context.Context, req proto.ListResourcesRequest) (*types.ListResourcesResponse, error) ListAccessLists(context.Context, int, string) ([]*accesslist.AccessList, string, error) - ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) + ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) } diff --git a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go index c7db512ab2c7a..ccd5874239f24 100644 --- a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go +++ b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go @@ -40,6 +40,7 @@ type ServiceConfig struct { // Cache is the subset of the cached resources that the service queries. type Cache interface { ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) + ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) GetAccessMonitoringRule(ctx context.Context, name string) (*accessmonitoringrulesv1.AccessMonitoringRule, error) } @@ -168,3 +169,22 @@ func (s *Service) ListAccessMonitoringRules(ctx context.Context, req *accessmoni NextPageToken: nextToken, }, nil } + +// ListAccessMonitoringRuleWithFilter lists current access monitoring rules. +func (s *Service) ListAccessMonitoringRuleWithFilter(ctx context.Context, req *accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest) (*accessmonitoringrulesv1.ListAccessMonitoringRulesResponse, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.CheckAccessToKind(types.KindAccessMonitoringRule, types.VerbRead, types.VerbList); err != nil { + return nil, trace.Wrap(err) + } + results, nextToken, err := s.cache.ListAccessMonitoringRulesWithFilter(ctx, int(req.PageSize), req.PageToken, req.Subjects,req.NotificationName) + if err != nil { + return nil, trace.Wrap(err) + } + return &accessmonitoringrulesv1.ListAccessMonitoringRulesResponse{ + Rules: results, + NextPageToken: nextToken, + }, nil +} diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index b724de9d3cdd8..87482c7e84d6c 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -1167,6 +1167,8 @@ type Cache interface { ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrules.AccessMonitoringRule, string, error) // GetAccessMonitoringRule returns the specified access monitoring rule. GetAccessMonitoringRule(ctx context.Context, name string) (*accessmonitoringrules.AccessMonitoringRule, error) + // ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules. + ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrules.AccessMonitoringRule, string, error) } type NodeWrapper struct { diff --git a/lib/cache/cache.go b/lib/cache/cache.go index a74bf553b0405..2bab09f0d5643 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -3125,6 +3125,21 @@ func (c *Cache) ListAccessMonitoringRules(ctx context.Context, pageSize int, nex return out, nextKey, trace.Wrap(err) } +// ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules. +func (c *Cache) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { + ctx, span := c.Tracer.Start(ctx, "cache/ListAccessMonitoringRules") + defer span.End() + + rg, err := readCollectionCache(c, c.collections.accessMonitoringRules) + + if err != nil { + return nil, "", trace.Wrap(err) + } + defer rg.Release() + out, nextKey, err := rg.reader.ListAccessMonitoringRulesWithFilter(ctx, pageSize, nextToken, subjects, notificationName) + return out, nextKey, trace.Wrap(err) +} + // GetAccessMonitoringRule returns the specified AccessMonitoringRule resources. func (c *Cache) GetAccessMonitoringRule(ctx context.Context, name string) (*accessmonitoringrulesv1.AccessMonitoringRule, error) { ctx, span := c.Tracer.Start(ctx, "cache/GetAccessMonitoringRule") diff --git a/lib/cache/collections.go b/lib/cache/collections.go index 339a014cdf4fe..289fca897723c 100644 --- a/lib/cache/collections.go +++ b/lib/cache/collections.go @@ -3170,4 +3170,5 @@ func (accessMonitoringRulesExecutor) getReader(cache *Cache, cacheOK bool) acces type accessMonitoringRuleGetter interface { GetAccessMonitoringRule(ctx context.Context, name string) (*accessmonitoringrulesv1.AccessMonitoringRule, error) ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) + ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) } diff --git a/lib/services/access_monitoring_rules.go b/lib/services/access_monitoring_rules.go index 4facb1b6085ca..c2369e71d48d3 100644 --- a/lib/services/access_monitoring_rules.go +++ b/lib/services/access_monitoring_rules.go @@ -20,7 +20,6 @@ package services import ( "context" - "slices" "github.com/gravitational/trace" @@ -39,6 +38,7 @@ type AccessMonitoringRules interface { DeleteAccessMonitoringRule(ctx context.Context, name string) error DeleteAllAccessMonitoringRules(ctx context.Context) error ListAccessMonitoringRules(ctx context.Context, limit int, startKey string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) + ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, nextToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) } // NewAccessMonitoringRuleWithLabels creates a new AccessMonitoringRule with the given spec and labels. @@ -63,36 +63,36 @@ func NewAccessMonitoringRuleWithLabels(name string, labels map[string]string, sp // ValidateAccessMonitoringRule checks that the provided access monitoring rule is valid. func ValidateAccessMonitoringRule(accessMonitoringRule *accessmonitoringrulesv1.AccessMonitoringRule) error { - if accessMonitoringRule.Kind != types.KindAccessMonitoringRule { - return trace.BadParameter("invalid kind for access monitoring rule: %q", accessMonitoringRule.Kind) - } - if accessMonitoringRule.Metadata == nil { - return trace.BadParameter("accessMonitoringRule metadata is missing") - } - if accessMonitoringRule.Version != types.V1 { - return trace.BadParameter("accessMonitoringRule %q is not supported", accessMonitoringRule.Version) - } - if accessMonitoringRule.Spec == nil { - return trace.BadParameter("accessMonitoringRule spec is missing") - } + // if accessMonitoringRule.Kind != types.KindAccessMonitoringRule { + // return trace.BadParameter("invalid kind for access monitoring rule: %q", accessMonitoringRule.Kind) + // } + // if accessMonitoringRule.Metadata == nil { + // return trace.BadParameter("accessMonitoringRule metadata is missing") + // } + // if accessMonitoringRule.Version != types.V1 { + // return trace.BadParameter("accessMonitoringRule %q is not supported", accessMonitoringRule.Version) + // } + // if accessMonitoringRule.Spec == nil { + // return trace.BadParameter("accessMonitoringRule spec is missing") + // } - if len(accessMonitoringRule.Spec.Subjects) == 0 { - return trace.BadParameter("accessMonitoringRule subject is missing") - } + // if len(accessMonitoringRule.Spec.Subjects) == 0 { + // return trace.BadParameter("accessMonitoringRule subject is missing") + // } - if accessMonitoringRule.Spec.Condition == "" { - return trace.BadParameter("accessMonitoringRule condition is missing") - } + // if accessMonitoringRule.Spec.Condition == "" { + // return trace.BadParameter("accessMonitoringRule condition is missing") + // } - if accessMonitoringRule.Spec.Notification != nil && accessMonitoringRule.Spec.Notification.Name == "" { - return trace.BadParameter("accessMonitoringRule notification plugin name is missing") - } - if hasAccessRequestAsSubject := slices.ContainsFunc(accessMonitoringRule.Spec.Subjects, func(subject string) bool { - return subject == types.KindAccessRequest - }); hasAccessRequestAsSubject && accessMonitoringRule.Spec.Notification == nil { - return trace.BadParameter("accessMonitoringRule notification configuration must be set if subjects contain %q", - types.KindAccessRequest) - } + // if accessMonitoringRule.Spec.Notification != nil && accessMonitoringRule.Spec.Notification.Name == "" { + // return trace.BadParameter("accessMonitoringRule notification plugin name is missing") + // } + // if hasAccessRequestAsSubject := slices.ContainsFunc(accessMonitoringRule.Spec.Subjects, func(subject string) bool { + // return subject == types.KindAccessRequest + // }); hasAccessRequestAsSubject && accessMonitoringRule.Spec.Notification == nil { + // return trace.BadParameter("accessMonitoringRule notification configuration must be set if subjects contain %q", + // types.KindAccessRequest) + // } return nil } diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index 75564cbf25cd0..a0734c2743a4b 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -113,7 +113,7 @@ func (s *AccessMonitoringRulesService) DeleteAllAccessMonitoringRules(ctx contex return trace.Wrap(s.svc.DeleteAllResources(ctx)) } -func (s *AccessMonitoringRulesService) listResourcesListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { +func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { var keyPrefix []string var unmarshalItemFunc backendItemToResourceFunc From a2f8dcc21a6e44a74114e386ecdac1927f738282 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 8 May 2024 13:54:49 +0100 Subject: [PATCH 19/43] Appease linter --- lib/accessmonitoringrules/accessmonitoringrulesv1/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go index ccd5874239f24..82be6865943d0 100644 --- a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go +++ b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go @@ -179,7 +179,7 @@ func (s *Service) ListAccessMonitoringRuleWithFilter(ctx context.Context, req *a if err := authCtx.CheckAccessToKind(types.KindAccessMonitoringRule, types.VerbRead, types.VerbList); err != nil { return nil, trace.Wrap(err) } - results, nextToken, err := s.cache.ListAccessMonitoringRulesWithFilter(ctx, int(req.PageSize), req.PageToken, req.Subjects,req.NotificationName) + results, nextToken, err := s.cache.ListAccessMonitoringRulesWithFilter(ctx, int(req.PageSize), req.PageToken, req.Subjects, req.NotificationName) if err != nil { return nil, trace.Wrap(err) } From 230fbfa44f48c62e71e6faec69a78aaf3b35c85e Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 8 May 2024 16:36:21 +0100 Subject: [PATCH 20/43] Add back validation code for AMRs --- lib/services/access_monitoring_rules.go | 55 +++++++++++++------------ 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/lib/services/access_monitoring_rules.go b/lib/services/access_monitoring_rules.go index c2369e71d48d3..e091353d1dfa8 100644 --- a/lib/services/access_monitoring_rules.go +++ b/lib/services/access_monitoring_rules.go @@ -20,6 +20,7 @@ package services import ( "context" + "slices" "github.com/gravitational/trace" @@ -63,36 +64,36 @@ func NewAccessMonitoringRuleWithLabels(name string, labels map[string]string, sp // ValidateAccessMonitoringRule checks that the provided access monitoring rule is valid. func ValidateAccessMonitoringRule(accessMonitoringRule *accessmonitoringrulesv1.AccessMonitoringRule) error { - // if accessMonitoringRule.Kind != types.KindAccessMonitoringRule { - // return trace.BadParameter("invalid kind for access monitoring rule: %q", accessMonitoringRule.Kind) - // } - // if accessMonitoringRule.Metadata == nil { - // return trace.BadParameter("accessMonitoringRule metadata is missing") - // } - // if accessMonitoringRule.Version != types.V1 { - // return trace.BadParameter("accessMonitoringRule %q is not supported", accessMonitoringRule.Version) - // } - // if accessMonitoringRule.Spec == nil { - // return trace.BadParameter("accessMonitoringRule spec is missing") - // } + if accessMonitoringRule.Kind != types.KindAccessMonitoringRule { + return trace.BadParameter("invalid kind for access monitoring rule: %q", accessMonitoringRule.Kind) + } + if accessMonitoringRule.Metadata == nil { + return trace.BadParameter("accessMonitoringRule metadata is missing") + } + if accessMonitoringRule.Version != types.V1 { + return trace.BadParameter("accessMonitoringRule %q is not supported", accessMonitoringRule.Version) + } + if accessMonitoringRule.Spec == nil { + return trace.BadParameter("accessMonitoringRule spec is missing") + } - // if len(accessMonitoringRule.Spec.Subjects) == 0 { - // return trace.BadParameter("accessMonitoringRule subject is missing") - // } + if len(accessMonitoringRule.Spec.Subjects) == 0 { + return trace.BadParameter("accessMonitoringRule subject is missing") + } - // if accessMonitoringRule.Spec.Condition == "" { - // return trace.BadParameter("accessMonitoringRule condition is missing") - // } + if accessMonitoringRule.Spec.Condition == "" { + return trace.BadParameter("accessMonitoringRule condition is missing") + } - // if accessMonitoringRule.Spec.Notification != nil && accessMonitoringRule.Spec.Notification.Name == "" { - // return trace.BadParameter("accessMonitoringRule notification plugin name is missing") - // } - // if hasAccessRequestAsSubject := slices.ContainsFunc(accessMonitoringRule.Spec.Subjects, func(subject string) bool { - // return subject == types.KindAccessRequest - // }); hasAccessRequestAsSubject && accessMonitoringRule.Spec.Notification == nil { - // return trace.BadParameter("accessMonitoringRule notification configuration must be set if subjects contain %q", - // types.KindAccessRequest) - // } + if accessMonitoringRule.Spec.Notification != nil && accessMonitoringRule.Spec.Notification.Name == "" { + return trace.BadParameter("accessMonitoringRule notification plugin name is missing") + } + if hasAccessRequestAsSubject := slices.ContainsFunc(accessMonitoringRule.Spec.Subjects, func(subject string) bool { + return subject == types.KindAccessRequest + }); hasAccessRequestAsSubject && accessMonitoringRule.Spec.Notification == nil { + return trace.BadParameter("accessMonitoringRule notification configuration must be set if subjects contain %q", + types.KindAccessRequest) + } return nil } From 1b593a3746cf737c25d89c428d312471e7dd2d1b Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Thu, 9 May 2024 16:14:45 +0100 Subject: [PATCH 21/43] Fix test plugin role and rename listaccessmonitoringrulewithfilter --- .../lib/testing/integration/accessrequestsuite.go | 1 + .../accessmonitoringrulesv1/service.go | 4 ++-- lib/services/local/access_monitoring_rules.go | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/integrations/lib/testing/integration/accessrequestsuite.go b/integrations/lib/testing/integration/accessrequestsuite.go index a257e80b04907..3be8578f23088 100644 --- a/integrations/lib/testing/integration/accessrequestsuite.go +++ b/integrations/lib/testing/integration/accessrequestsuite.go @@ -205,6 +205,7 @@ func (s *AccessRequestSuite) SetupSuite() { // submit positive reviews. types.NewRule("access_request", []string{"list", "read", "update"}), types.NewRule("access_plugin_data", []string{"update"}), + types.NewRule(types.KindAccessMonitoringRule, []string{"update", "read", "list"}), }, }, }) diff --git a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go index 82be6865943d0..567e130fca389 100644 --- a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go +++ b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go @@ -170,8 +170,8 @@ func (s *Service) ListAccessMonitoringRules(ctx context.Context, req *accessmoni }, nil } -// ListAccessMonitoringRuleWithFilter lists current access monitoring rules. -func (s *Service) ListAccessMonitoringRuleWithFilter(ctx context.Context, req *accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest) (*accessmonitoringrulesv1.ListAccessMonitoringRulesResponse, error) { +// ListAccessMonitoringRulesWithFilter lists current access monitoring rules. +func (s *Service) ListAccessMonitoringRulesWithFilter(ctx context.Context, req *accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest) (*accessmonitoringrulesv1.ListAccessMonitoringRulesResponse, error) { authCtx, err := s.authorizer.Authorize(ctx) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index a0734c2743a4b..ef2495927424f 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -50,7 +50,8 @@ func NewAccessMonitoringRulesService(backend backend.Backend) (*AccessMonitoring return nil, trace.Wrap(err) } return &AccessMonitoringRulesService{ - svc: service, + svc: service, + backend: backend, }, nil } @@ -113,10 +114,10 @@ func (s *AccessMonitoringRulesService) DeleteAllAccessMonitoringRules(ctx contex return trace.Wrap(s.svc.DeleteAllResources(ctx)) } +// ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules that match the given filter. func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { var keyPrefix []string - var unmarshalItemFunc backendItemToResourceFunc rangeStart := backend.Key(accessMonitoringRulesPrefix, pageToken) rangeEnd := backend.RangeEnd(backend.ExactKey(keyPrefix...)) @@ -130,11 +131,10 @@ func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx c break } - resource, err := unmarshalItemFunc(item) + accessMonitoringRule, err := services.UnmarshalAccessMonitoringRule(item.Value) if err != nil { return false, trace.Wrap(err) } - accessMonitoringRule := types.LegacyToResource153(resource).(*accessmonitoringrulesv1.AccessMonitoringRule) if ok := match(accessMonitoringRule, subjects, notificationName); ok { resources = append(resources, accessMonitoringRule) } From 6a45566d408f518733f0fd9c8691c9352912b88e Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Thu, 9 May 2024 16:31:59 +0100 Subject: [PATCH 22/43] Fix local test for AMR crud operations --- lib/services/local/access_monitoring_rules_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/services/local/access_monitoring_rules_test.go b/lib/services/local/access_monitoring_rules_test.go index 3da99b029fcc5..b3ce35e878152 100644 --- a/lib/services/local/access_monitoring_rules_test.go +++ b/lib/services/local/access_monitoring_rules_test.go @@ -131,7 +131,8 @@ func TestListAccessMonitoringRules(t *testing.T) { var insertedAccessMonitoringRules []*accessmonitoringrulesv1.AccessMonitoringRule for i := 0; i < numAccessMonitoringRules; i++ { AccessMonitoringRule := &accessmonitoringrulesv1.AccessMonitoringRule{ - Kind: types.KindAccessMonitoringRule, + Kind: types.KindAccessMonitoringRule, + Version: types.V1, Metadata: &v1.Metadata{ Name: fmt.Sprintf("p%02d", i+1), }, From 1fb6a7227ffbaa4387957b2aad866df4ebd9c8dc Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 10 May 2024 16:36:47 +0100 Subject: [PATCH 23/43] Fix end range for listing rules --- lib/services/local/access_monitoring_rules.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index ef2495927424f..9f8c618950dc3 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -117,10 +117,8 @@ func (s *AccessMonitoringRulesService) DeleteAllAccessMonitoringRules(ctx contex // ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules that match the given filter. func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { - var keyPrefix []string - rangeStart := backend.Key(accessMonitoringRulesPrefix, pageToken) - rangeEnd := backend.RangeEnd(backend.ExactKey(keyPrefix...)) + rangeEnd := backend.RangeEnd(backend.ExactKey(accessMonitoringRulesPrefix)) // Get most limit+1 results to determine if there will be a next key. maxLimit := pageSize + 1 From c5c47cff9ee6a3c2fa8e0319b4f819a850cad21c Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Mon, 13 May 2024 17:34:16 +0100 Subject: [PATCH 24/43] Fix unwrapping of resource153 event for monitoring rules --- integrations/access/accessrequest/app.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 25490fbd74fd0..a9c6f0c8cefc2 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -236,7 +236,11 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) return trace.BadParameter("expected %s resource kind, got %s", types.KindAccessMonitoringRule, kind) } - req, ok := types.LegacyToResource153(event.Resource).(*accessmonitoringrulesv1.AccessMonitoringRule) + e, ok := event.Resource.(types.Resource153Unwrapper) + if !ok { + return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) + } + req, ok := e.Unwrap().(*accessmonitoringrulesv1.AccessMonitoringRule) if !ok { return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) } @@ -587,8 +591,7 @@ func (a *App) getAllAccessMonitoringRules(ctx context.Context) ([]*accessmonitor for { var page []*accessmonitoringrulesv1.AccessMonitoringRule var err error - page, nextToken, err = a.apiClient.ListAccessMonitoringRulesWithFilter(ctx, defaultAccessMonitoringRulePageSize, nextToken, - []string{types.KindAccessRequest}, a.pluginName) + page, nextToken, err = a.apiClient.ListAccessMonitoringRulesWithFilter(ctx, defaultAccessMonitoringRulePageSize, nextToken, []string{types.KindAccessRequest}, a.pluginName) if err != nil { return nil, trace.Wrap(err) } From f178aadb8b1b651f75186ffb1b2a00885b2f8642 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 14 May 2024 15:59:29 +0100 Subject: [PATCH 25/43] Refactor AMR cache init into helper function in plugin app --- integrations/access/accessrequest/app.go | 27 +++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index a9c6f0c8cefc2..dada8d7a3cfcf 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -144,18 +144,9 @@ func (a *App) run(ctx context.Context) error { return trace.Wrap(err) } - accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) - if err != nil { + if err := a.initAccessMonitoringRulesCache(ctx); err != nil { return trace.Wrap(err) } - a.accessMonitoringRules.Lock() - for _, amr := range accessMonitoringRules { - if !a.amrAppliesToThisPlugin(amr) { - continue - } - a.accessMonitoringRules.rules[amr.GetMetadata().Name] = amr - } - a.accessMonitoringRules.Unlock() a.job.SetReady(ok) if !ok { @@ -585,6 +576,22 @@ func (a *App) getResourceNames(ctx context.Context, req types.AccessRequest) ([] return resourceNames, nil } +func (a *App) initAccessMonitoringRulesCache(ctx context.Context) error { + accessMonitoringRules, err := a.getAllAccessMonitoringRules(ctx) + if err != nil { + return trace.Wrap(err) + } + a.accessMonitoringRules.Lock() + defer a.accessMonitoringRules.Unlock() + for _, amr := range accessMonitoringRules { + if !a.amrAppliesToThisPlugin(amr) { + continue + } + a.accessMonitoringRules.rules[amr.GetMetadata().Name] = amr + } + return nil +} + func (a *App) getAllAccessMonitoringRules(ctx context.Context) ([]*accessmonitoringrulesv1.AccessMonitoringRule, error) { var resources []*accessmonitoringrulesv1.AccessMonitoringRule var nextToken string From 49d56841fbaa5608e2442d34538d5a94565336f4 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 15 May 2024 16:10:34 +0100 Subject: [PATCH 26/43] Add seperate response type for listAccessMonitoringRulesWithfilter --- .../v1/access_monitoring_rules.pb.go | 140 ++++++++++++++---- .../v1/access_monitoring_rules_service.pb.go | 84 ++++++----- ...access_monitoring_rules_service_grpc.pb.go | 10 +- .../v1/access_monitoring_rules.proto | 9 ++ .../v1/access_monitoring_rules_service.proto | 2 +- .../accessmonitoringrulesv1/service.go | 4 +- 6 files changed, 172 insertions(+), 77 deletions(-) diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go index 59507c1530fb3..8e7ea66343d56 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go @@ -695,6 +695,65 @@ func (x *ListAccessMonitoringRulesResponse) GetNextPageToken() string { return "" } +// ListAccessMonitoringRulesWithFilterResponse is the response from ListAccessMonitoringRulesWithFilter. +type ListAccessMonitoringRulesWithFilterResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The page of AccessMonitoringRule that matched the request. + Rules []*AccessMonitoringRule `protobuf:"bytes,1,rep,name=rules,proto3" json:"rules,omitempty"` + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` +} + +func (x *ListAccessMonitoringRulesWithFilterResponse) Reset() { + *x = ListAccessMonitoringRulesWithFilterResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListAccessMonitoringRulesWithFilterResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListAccessMonitoringRulesWithFilterResponse) ProtoMessage() {} + +func (x *ListAccessMonitoringRulesWithFilterResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListAccessMonitoringRulesWithFilterResponse.ProtoReflect.Descriptor instead. +func (*ListAccessMonitoringRulesWithFilterResponse) Descriptor() ([]byte, []int) { + return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescGZIP(), []int{11} +} + +func (x *ListAccessMonitoringRulesWithFilterResponse) GetRules() []*AccessMonitoringRule { + if x != nil { + return x.Rules + } + return nil +} + +func (x *ListAccessMonitoringRulesWithFilterResponse) GetNextPageToken() string { + if x != nil { + return x.NextPageToken + } + return "" +} + var File_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto protoreflect.FileDescriptor var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDesc = []byte{ @@ -793,14 +852,25 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDesc 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x42, 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, - 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x6e, 0x22, 0xa4, 0x01, 0x0a, 0x2b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, + 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x37, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, + 0x73, 0x12, 0x26, 0x0a, 0x0f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6e, 0x65, 0x78, 0x74, + 0x50, 0x61, 0x67, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x42, 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, + 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -815,34 +885,36 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDes return file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDescData } -var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes = make([]protoimpl.MessageInfo, 12) var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_goTypes = []interface{}{ - (*AccessMonitoringRule)(nil), // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule - (*AccessMonitoringRuleSpec)(nil), // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec - (*Notification)(nil), // 2: teleport.accessmonitoringrules.v1.Notification - (*CreateAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest - (*UpdateAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest - (*UpsertAccessMonitoringRuleRequest)(nil), // 5: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest - (*GetAccessMonitoringRuleRequest)(nil), // 6: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest - (*DeleteAccessMonitoringRuleRequest)(nil), // 7: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest - (*ListAccessMonitoringRulesRequest)(nil), // 8: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest - (*ListAccessMonitoringRulesResponse)(nil), // 10: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse - (*v1.Metadata)(nil), // 11: teleport.header.v1.Metadata + (*AccessMonitoringRule)(nil), // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule + (*AccessMonitoringRuleSpec)(nil), // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec + (*Notification)(nil), // 2: teleport.accessmonitoringrules.v1.Notification + (*CreateAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest + (*UpdateAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest + (*UpsertAccessMonitoringRuleRequest)(nil), // 5: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest + (*GetAccessMonitoringRuleRequest)(nil), // 6: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest + (*DeleteAccessMonitoringRuleRequest)(nil), // 7: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest + (*ListAccessMonitoringRulesRequest)(nil), // 8: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest + (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + (*ListAccessMonitoringRulesResponse)(nil), // 10: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + (*ListAccessMonitoringRulesWithFilterResponse)(nil), // 11: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterResponse + (*v1.Metadata)(nil), // 12: teleport.header.v1.Metadata } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_depIdxs = []int32{ - 11, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule.metadata:type_name -> teleport.header.v1.Metadata + 12, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRule.metadata:type_name -> teleport.header.v1.Metadata 1, // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRule.spec:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec 2, // 2: teleport.accessmonitoringrules.v1.AccessMonitoringRuleSpec.notification:type_name -> teleport.accessmonitoringrules.v1.Notification 0, // 3: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest.rule:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule 0, // 4: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest.rule:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule 0, // 5: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest.rule:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule 0, // 6: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse.rules:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 7, // [7:7] is the sub-list for method output_type - 7, // [7:7] is the sub-list for method input_type - 7, // [7:7] is the sub-list for extension type_name - 7, // [7:7] is the sub-list for extension extendee - 0, // [0:7] is the sub-list for field type_name + 0, // 7: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterResponse.rules:type_name -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 8, // [8:8] is the sub-list for method output_type + 8, // [8:8] is the sub-list for method input_type + 8, // [8:8] is the sub-list for extension type_name + 8, // [8:8] is the sub-list for extension extendee + 0, // [0:8] is the sub-list for field type_name } func init() { file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_init() } @@ -983,6 +1055,18 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_init() return nil } } + file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListAccessMonitoringRulesWithFilterResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -990,7 +1074,7 @@ func file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_init() GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_accessmonitoringrules_v1_access_monitoring_rules_proto_rawDesc, NumEnums: 0, - NumMessages: 11, + NumMessages: 12, NumExtensions: 0, NumServices: 0, }, diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go index c2ca292664e65..636b1cf7059e0 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.pb.go @@ -49,7 +49,7 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xf2, 0x08, 0x0a, 0x1c, 0x41, + 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0xfc, 0x08, 0x0a, 0x1c, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x9b, 0x01, 0x0a, 0x1a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, @@ -109,60 +109,62 @@ var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0xba, 0x01, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x65, 0x12, 0xc4, 0x01, 0x0a, 0x23, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x44, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x4e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, - 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, - 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, - 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x76, 0x31, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x73, 0x57, 0x69, 0x74, 0x68, 0x46, 0x69, 0x6c, 0x74, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x6e, 0x5a, 0x6c, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, + 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2f, 0x76, + 0x31, 0x3b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto_goTypes = []interface{}{ - (*CreateAccessMonitoringRuleRequest)(nil), // 0: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest - (*UpdateAccessMonitoringRuleRequest)(nil), // 1: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest - (*UpsertAccessMonitoringRuleRequest)(nil), // 2: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest - (*GetAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest - (*DeleteAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest - (*ListAccessMonitoringRulesRequest)(nil), // 5: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 6: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest - (*AccessMonitoringRule)(nil), // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRule - (*emptypb.Empty)(nil), // 8: google.protobuf.Empty - (*ListAccessMonitoringRulesResponse)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + (*CreateAccessMonitoringRuleRequest)(nil), // 0: teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest + (*UpdateAccessMonitoringRuleRequest)(nil), // 1: teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest + (*UpsertAccessMonitoringRuleRequest)(nil), // 2: teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest + (*GetAccessMonitoringRuleRequest)(nil), // 3: teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest + (*DeleteAccessMonitoringRuleRequest)(nil), // 4: teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest + (*ListAccessMonitoringRulesRequest)(nil), // 5: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest + (*ListAccessMonitoringRulesWithFilterRequest)(nil), // 6: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + (*AccessMonitoringRule)(nil), // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRule + (*emptypb.Empty)(nil), // 8: google.protobuf.Empty + (*ListAccessMonitoringRulesResponse)(nil), // 9: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + (*ListAccessMonitoringRulesWithFilterResponse)(nil), // 10: teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterResponse } var file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto_depIdxs = []int32{ - 0, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest - 1, // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest - 2, // 2: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest - 3, // 3: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest - 4, // 4: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest - 5, // 5: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest - 6, // 6: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest - 7, // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 7, // 8: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 7, // 9: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 7, // 10: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule - 8, // 11: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:output_type -> google.protobuf.Empty - 9, // 12: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse - 9, // 13: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse - 7, // [7:14] is the sub-list for method output_type - 0, // [0:7] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 0, // 0: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.CreateAccessMonitoringRuleRequest + 1, // 1: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.UpdateAccessMonitoringRuleRequest + 2, // 2: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.UpsertAccessMonitoringRuleRequest + 3, // 3: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.GetAccessMonitoringRuleRequest + 4, // 4: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:input_type -> teleport.accessmonitoringrules.v1.DeleteAccessMonitoringRuleRequest + 5, // 5: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesRequest + 6, // 6: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:input_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterRequest + 7, // 7: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.CreateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 8: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpdateAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 9: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.UpsertAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 7, // 10: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.GetAccessMonitoringRule:output_type -> teleport.accessmonitoringrules.v1.AccessMonitoringRule + 8, // 11: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.DeleteAccessMonitoringRule:output_type -> google.protobuf.Empty + 9, // 12: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRules:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesResponse + 10, // 13: teleport.accessmonitoringrules.v1.AccessMonitoringRulesService.ListAccessMonitoringRulesWithFilter:output_type -> teleport.accessmonitoringrules.v1.ListAccessMonitoringRulesWithFilterResponse + 7, // [7:14] is the sub-list for method output_type + 0, // [0:7] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name } func init() { file_teleport_accessmonitoringrules_v1_access_monitoring_rules_service_proto_init() } diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go index 591ac1a084700..896483a6e85b1 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules_service_grpc.pb.go @@ -60,7 +60,7 @@ type AccessMonitoringRulesServiceClient interface { // ListAccessMonitoringRules lists current access monitoring rules. ListAccessMonitoringRules(ctx context.Context, in *ListAccessMonitoringRulesRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. - ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) + ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesWithFilterResponse, error) } type accessMonitoringRulesServiceClient struct { @@ -125,8 +125,8 @@ func (c *accessMonitoringRulesServiceClient) ListAccessMonitoringRules(ctx conte return out, nil } -func (c *accessMonitoringRulesServiceClient) ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesResponse, error) { - out := new(ListAccessMonitoringRulesResponse) +func (c *accessMonitoringRulesServiceClient) ListAccessMonitoringRulesWithFilter(ctx context.Context, in *ListAccessMonitoringRulesWithFilterRequest, opts ...grpc.CallOption) (*ListAccessMonitoringRulesWithFilterResponse, error) { + out := new(ListAccessMonitoringRulesWithFilterResponse) err := c.cc.Invoke(ctx, AccessMonitoringRulesService_ListAccessMonitoringRulesWithFilter_FullMethodName, in, out, opts...) if err != nil { return nil, err @@ -151,7 +151,7 @@ type AccessMonitoringRulesServiceServer interface { // ListAccessMonitoringRules lists current access monitoring rules. ListAccessMonitoringRules(context.Context, *ListAccessMonitoringRulesRequest) (*ListAccessMonitoringRulesResponse, error) // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. - ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesResponse, error) + ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesWithFilterResponse, error) mustEmbedUnimplementedAccessMonitoringRulesServiceServer() } @@ -177,7 +177,7 @@ func (UnimplementedAccessMonitoringRulesServiceServer) DeleteAccessMonitoringRul func (UnimplementedAccessMonitoringRulesServiceServer) ListAccessMonitoringRules(context.Context, *ListAccessMonitoringRulesRequest) (*ListAccessMonitoringRulesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListAccessMonitoringRules not implemented") } -func (UnimplementedAccessMonitoringRulesServiceServer) ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesResponse, error) { +func (UnimplementedAccessMonitoringRulesServiceServer) ListAccessMonitoringRulesWithFilter(context.Context, *ListAccessMonitoringRulesWithFilterRequest) (*ListAccessMonitoringRulesWithFilterResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListAccessMonitoringRulesWithFilter not implemented") } func (UnimplementedAccessMonitoringRulesServiceServer) mustEmbedUnimplementedAccessMonitoringRulesServiceServer() { diff --git a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto index ae859ef52c977..88d42fb13a7b4 100644 --- a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto +++ b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto @@ -115,3 +115,12 @@ message ListAccessMonitoringRulesResponse { // more results in the list. string next_page_token = 2; } + +// ListAccessMonitoringRulesWithFilterResponse is the response from ListAccessMonitoringRulesWithFilter. +message ListAccessMonitoringRulesWithFilterResponse { + // The page of AccessMonitoringRule that matched the request. + repeated AccessMonitoringRule rules = 1; + // Token to retrieve the next page of results, or empty if there are no + // more results in the list. + string next_page_token = 2; +} diff --git a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto index 3828d9253abbf..6025d31796ccb 100644 --- a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto +++ b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules_service.proto @@ -42,5 +42,5 @@ service AccessMonitoringRulesService { rpc ListAccessMonitoringRules(ListAccessMonitoringRulesRequest) returns (ListAccessMonitoringRulesResponse); // ListAccessMonitoringRulesWithFilter lists current access monitoring rules that match the provided filter. - rpc ListAccessMonitoringRulesWithFilter(ListAccessMonitoringRulesWithFilterRequest) returns (ListAccessMonitoringRulesResponse); + rpc ListAccessMonitoringRulesWithFilter(ListAccessMonitoringRulesWithFilterRequest) returns (ListAccessMonitoringRulesWithFilterResponse); } diff --git a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go index 567e130fca389..eb53f499c3452 100644 --- a/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go +++ b/lib/accessmonitoringrules/accessmonitoringrulesv1/service.go @@ -171,7 +171,7 @@ func (s *Service) ListAccessMonitoringRules(ctx context.Context, req *accessmoni } // ListAccessMonitoringRulesWithFilter lists current access monitoring rules. -func (s *Service) ListAccessMonitoringRulesWithFilter(ctx context.Context, req *accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest) (*accessmonitoringrulesv1.ListAccessMonitoringRulesResponse, error) { +func (s *Service) ListAccessMonitoringRulesWithFilter(ctx context.Context, req *accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterRequest) (*accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterResponse, error) { authCtx, err := s.authorizer.Authorize(ctx) if err != nil { return nil, trace.Wrap(err) @@ -183,7 +183,7 @@ func (s *Service) ListAccessMonitoringRulesWithFilter(ctx context.Context, req * if err != nil { return nil, trace.Wrap(err) } - return &accessmonitoringrulesv1.ListAccessMonitoringRulesResponse{ + return &accessmonitoringrulesv1.ListAccessMonitoringRulesWithFilterResponse{ Rules: results, NextPageToken: nextToken, }, nil From 2254706bef5cb245187b8c5dd055e7bebe3a248b Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 15 May 2024 16:14:03 +0100 Subject: [PATCH 27/43] Add context to log for plugins failing to fetch recipients --- integrations/access/accessrequest/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index dada8d7a3cfcf..a8e17d18dd18a 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -494,7 +494,7 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types for _, recipient := range rule.Spec.Notification.Recipients { rec, err := a.bot.FetchRecipient(ctx, recipient) if err != nil { - log.Warning(err) + log.WithError(err).Warn("Failed to fetch plugin recipients based on Access moniotring rule recipients") continue } recipientSet.Add(*rec) From c95d6684525b7b1d7c5ea9a4c5655bef8eb23f2b Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 15 May 2024 16:17:30 +0100 Subject: [PATCH 28/43] Grab access monitoring rules cache under lock all at once --- integrations/access/accessrequest/app.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index a8e17d18dd18a..767b1e623b17e 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -21,6 +21,7 @@ package accessrequest import ( "context" "fmt" + "maps" "slices" "sync" "time" @@ -479,10 +480,7 @@ func (a *App) recipientsFromAccessMonitoringRules(ctx context.Context, req types return &recipientSet } - a.accessMonitoringRules.RLock() - defer a.accessMonitoringRules.RUnlock() - - for _, rule := range a.accessMonitoringRules.rules { + for _, rule := range a.getAccessMonitoringRules() { match, err := matchAccessRequest(rule.Spec.Condition, req) if err != nil { log.WithError(err).WithField("rule", rule.Metadata.Name). @@ -611,3 +609,9 @@ func (a *App) getAllAccessMonitoringRules(ctx context.Context) ([]*accessmonitor } return resources, nil } + +func (a *App) getAccessMonitoringRules() map[string]*accessmonitoringrulesv1.AccessMonitoringRule { + a.accessMonitoringRules.RLock() + defer a.accessMonitoringRules.RUnlock() + return maps.Clone(a.accessMonitoringRules.rules) +} From 3aabbaa7353567468af7b559700a40c270c9be6d Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Wed, 15 May 2024 16:24:22 +0100 Subject: [PATCH 29/43] Add clarification for which fields are optional in listAMRfilter req --- .../accessmonitoringrules/v1/access_monitoring_rules.pb.go | 4 ++-- .../accessmonitoringrules/v1/access_monitoring_rules.proto | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go index 8e7ea66343d56..52e4d59e32fe2 100644 --- a/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go +++ b/api/gen/proto/go/teleport/accessmonitoringrules/v1/access_monitoring_rules.pb.go @@ -570,9 +570,9 @@ type ListAccessMonitoringRulesWithFilterRequest struct { PageSize int64 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"` // page_token is the next_page_token value returned from a previous List request, if any. PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"` - // subjects are the subjects the access monitoring rules must have. + // subjects are the subjects the access monitoring rules must have. This field is optional. Subjects []string `protobuf:"bytes,3,rep,name=subjects,proto3" json:"subjects,omitempty"` - // notification_name is the value of the notification name field the rule must have. + // notification_name is the value of the notification name field the rule must have. This field is optional. NotificationName string `protobuf:"bytes,4,opt,name=notification_name,json=notificationName,proto3" json:"notification_name,omitempty"` } diff --git a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto index 88d42fb13a7b4..6b385a9f42eaf 100644 --- a/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto +++ b/api/proto/teleport/accessmonitoringrules/v1/access_monitoring_rules.proto @@ -101,9 +101,9 @@ message ListAccessMonitoringRulesWithFilterRequest { int64 page_size = 1; // page_token is the next_page_token value returned from a previous List request, if any. string page_token = 2; - // subjects are the subjects the access monitoring rules must have. + // subjects are the subjects the access monitoring rules must have. This field is optional. repeated string subjects = 3; - // notification_name is the value of the notification name field the rule must have. + // notification_name is the value of the notification name field the rule must have. This field is optional. string notification_name = 4; } From 7c97f4007aef977085cab0fac625ce26d3bcefe4 Mon Sep 17 00:00:00 2001 From: Edward Dowling Date: Thu, 16 May 2024 16:54:18 +0100 Subject: [PATCH 30/43] Update integrations/access/accessrequest/app.go Co-authored-by: Zac Bergquist --- integrations/access/accessrequest/app.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 767b1e623b17e..c024dc8c6eec1 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -419,8 +419,8 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) for _, recipient := range recipients.ToSlice() { recipientSet.Add(recipient) } - if len(recipientSet.ToSlice()) != 0 { - return recipientSet.ToSlice() + if s := recipientSet.ToSlice(); len(s) != 0 { + return s } switch a.pluginType { From bb28720710fc7079e985fb1acb712c0785874260 Mon Sep 17 00:00:00 2001 From: Edward Dowling Date: Thu, 16 May 2024 16:54:30 +0100 Subject: [PATCH 31/43] Update integrations/access/accessrequest/app.go Co-authored-by: Zac Bergquist --- integrations/access/accessrequest/app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index c024dc8c6eec1..c8320881c4ff3 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -176,7 +176,7 @@ func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { case types.KindAccessRequest: return trace.Wrap(a.handleAcessRequest(ctx, event)) } - return trace.Errorf("unexpected kind %s", event.Resource.GetKind()) + return trace.BadParameter("unexpected kind %s", event.Resource.GetKind()) } func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { From 7145082f8f7cdc5da07e510907d7f31cfb8c7a17 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 17 May 2024 10:54:13 +0100 Subject: [PATCH 32/43] Add forEach to common recipient set --- integrations/access/accessrequest/app.go | 14 +++++++------- integrations/access/common/recipient.go | 7 +++++++ lib/services/local/access_monitoring_rules.go | 10 +++++----- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index c8320881c4ff3..3a5d6d3bcf7f7 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -176,7 +176,7 @@ func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { case types.KindAccessRequest: return trace.Wrap(a.handleAcessRequest(ctx, event)) } - return trace.BadParameter("unexpected kind %s", event.Resource.GetKind()) + return trace.Errorf("unexpected kind %s", event.Resource.GetKind()) } func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { @@ -230,7 +230,7 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) e, ok := event.Resource.(types.Resource153Unwrapper) if !ok { - return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) + return trace.BadParameter("expected Resource153Unwrapper resource type, got %T", event.Resource) } req, ok := e.Unwrap().(*accessmonitoringrulesv1.AccessMonitoringRule) if !ok { @@ -416,11 +416,11 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) recipientSet := common.NewRecipientSet() recipients := a.recipientsFromAccessMonitoringRules(ctx, req) - for _, recipient := range recipients.ToSlice() { - recipientSet.Add(recipient) - } - if s := recipientSet.ToSlice(); len(s) != 0 { - return s + recipients.ForEach(func(r common.Recipient){ + recipientSet.Add(r) + }) + if len(recipientSet.ToSlice()) != 0 { + return recipientSet.ToSlice() } switch a.pluginType { diff --git a/integrations/access/common/recipient.go b/integrations/access/common/recipient.go index f352cd579812c..fb3e967cab781 100644 --- a/integrations/access/common/recipient.go +++ b/integrations/access/common/recipient.go @@ -145,3 +145,10 @@ func (s *RecipientSet) ToSlice() []Recipient { } return recipientSlice } + +// ForEach applies run the given func with each recipient in the set as the argument. +func (s *RecipientSet) ForEach(f func(r Recipient)) { + for _, v := range s.recipients { + f(v) + } +} diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index 9f8c618950dc3..5c137bb1b065b 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -154,6 +154,11 @@ func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx c } func match(rule *accessmonitoringrulesv1.AccessMonitoringRule, subjects []string, notificationName string) bool { + if notificationName != "" { + if rule.Spec.Notification == nil || rule.Spec.Notification.Name != notificationName { + return false + } + } for _, subject := range subjects { if ok := slices.ContainsFunc(rule.Spec.Subjects, func(s string) bool { return s == subject @@ -161,10 +166,5 @@ func match(rule *accessmonitoringrulesv1.AccessMonitoringRule, subjects []string return false } } - if notificationName != "" { - if rule.Spec.Notification == nil || rule.Spec.Notification.Name != notificationName { - return false - } - } return true } From cf53bf430aab17208a7b0e1abb00ae359b1c2f1c Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 17 May 2024 11:17:41 +0100 Subject: [PATCH 33/43] Move type check to after AMR event op switch --- integrations/access/accessrequest/app.go | 28 +++++++++++------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 3a5d6d3bcf7f7..e0534ae470b5d 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -228,27 +228,25 @@ func (a *App) handleAccessMonitoringRule(ctx context.Context, event types.Event) return trace.BadParameter("expected %s resource kind, got %s", types.KindAccessMonitoringRule, kind) } - e, ok := event.Resource.(types.Resource153Unwrapper) - if !ok { - return trace.BadParameter("expected Resource153Unwrapper resource type, got %T", event.Resource) - } - req, ok := e.Unwrap().(*accessmonitoringrulesv1.AccessMonitoringRule) - if !ok { - return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) - } - - if !a.amrAppliesToThisPlugin(req) { - return nil - } - a.accessMonitoringRules.Lock() defer a.accessMonitoringRules.Unlock() switch op := event.Type; op { case types.OpPut: + e, ok := event.Resource.(types.Resource153Unwrapper) + if !ok { + return trace.BadParameter("expected Resource153Unwrapper resource type, got %T", event.Resource) + } + req, ok := e.Unwrap().(*accessmonitoringrulesv1.AccessMonitoringRule) + if !ok { + return trace.BadParameter("expected AccessMonitoringRule resource type, got %T", event.Resource) + } + if !a.amrAppliesToThisPlugin(req) { + return nil + } a.accessMonitoringRules.rules[req.Metadata.Name] = req return nil case types.OpDelete: - delete(a.accessMonitoringRules.rules, req.Metadata.Name) + delete(a.accessMonitoringRules.rules, event.Resource.GetName()) return nil default: return trace.BadParameter("unexpected event operation %s", op) @@ -416,7 +414,7 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) recipientSet := common.NewRecipientSet() recipients := a.recipientsFromAccessMonitoringRules(ctx, req) - recipients.ForEach(func(r common.Recipient){ + recipients.ForEach(func(r common.Recipient) { recipientSet.Add(r) }) if len(recipientSet.ToSlice()) != 0 { From 399f67fe3dbd701ff11602aa509567d4f48f1857 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 17 May 2024 13:22:38 +0100 Subject: [PATCH 34/43] Move turn some default parser spec methods to funcs --- lib/expression/parser.go | 44 ++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/expression/parser.go b/lib/expression/parser.go index c72c7a12c553d..a4d27ee9091df 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -109,28 +109,6 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { func(input string) (time.Time, error) { return time.Parse(time.RFC3339, input) }), - }, - Methods: map[string]typical.Function{ - "add": typical.BinaryVariadicFunction[evaluationEnv]( - func(s Set, values ...string) (Set, error) { - return s.add(values...), nil - }), - "contains": typical.BinaryFunction[evaluationEnv]( - func(s Set, str string) (bool, error) { - return s.contains(str), nil - }), - "put": typical.TernaryFunction[evaluationEnv]( - func(d Dict, key string, value Set) (Dict, error) { - return d.put(key, value), nil - }), - "add_values": typical.TernaryVariadicFunction[evaluationEnv]( - func(d Dict, key string, values ...string) (Dict, error) { - return d.addValues(key, values...), nil - }), - "remove": typical.BinaryVariadicFunction[evaluationEnv]( - func(r remover, items ...string) (any, error) { - return r.remove(items...), nil - }), "before": typical.BinaryFunction[evaluationEnv]( func(t time.Time, other time.Time) (bool, error) { return t.Before(other), nil @@ -164,6 +142,28 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { return len(s) == 0, nil }), }, + Methods: map[string]typical.Function{ + "add": typical.BinaryVariadicFunction[evaluationEnv]( + func(s Set, values ...string) (Set, error) { + return s.add(values...), nil + }), + "contains": typical.BinaryFunction[evaluationEnv]( + func(s Set, str string) (bool, error) { + return s.contains(str), nil + }), + "put": typical.TernaryFunction[evaluationEnv]( + func(d Dict, key string, value Set) (Dict, error) { + return d.put(key, value), nil + }), + "add_values": typical.TernaryVariadicFunction[evaluationEnv]( + func(d Dict, key string, values ...string) (Dict, error) { + return d.addValues(key, values...), nil + }), + "remove": typical.BinaryVariadicFunction[evaluationEnv]( + func(r remover, items ...string) (any, error) { + return r.remove(items...), nil + }), + }, } } From 3aceeaa4736c97604246f9ba163e633bf8381df3 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 17 May 2024 13:33:07 +0100 Subject: [PATCH 35/43] Make some predicate func usable as methods as well --- lib/expression/parser.go | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/expression/parser.go b/lib/expression/parser.go index a4d27ee9091df..7055d065bc837 100644 --- a/lib/expression/parser.go +++ b/lib/expression/parser.go @@ -163,6 +163,38 @@ func DefaultParserSpec[evaluationEnv any]() typical.ParserSpec[evaluationEnv] { func(r remover, items ...string) (any, error) { return r.remove(items...), nil }), + "before": typical.BinaryFunction[evaluationEnv]( + func(t time.Time, other time.Time) (bool, error) { + return t.Before(other), nil + }), + "after": typical.BinaryFunction[evaluationEnv]( + func(t time.Time, other time.Time) (bool, error) { + return t.After(other), nil + }), + "between": typical.BinaryVariadicFunction[evaluationEnv]( + func(t time.Time, interval ...time.Time) (bool, error) { + if len(interval) != 2 { + return false, trace.BadParameter("between expected 2 parameters: got %v", len(interval)) + } + first, second := interval[0], interval[1] + if first.After(second) { + first, second = second, first + } + return t.After(first) && t.Before(second), nil + }), + "contains_any": typical.BinaryFunction[evaluationEnv]( + func(s1, s2 Set) (bool, error) { + for _, v := range s2.items() { + if s1.contains(v) { + return true, nil + } + } + return false, nil + }), + "isempty": typical.UnaryFunction[evaluationEnv]( + func(s Set) (bool, error) { + return len(s) == 0, nil + }), }, } } From 951c422582f454c30077a0a841a31b4264865c45 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 17 May 2024 15:57:38 +0100 Subject: [PATCH 36/43] Add len func to common recipient sets --- integrations/access/accessrequest/app.go | 2 +- integrations/access/common/recipient.go | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index e0534ae470b5d..1118026a37e12 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -417,7 +417,7 @@ func (a *App) getMessageRecipients(ctx context.Context, req types.AccessRequest) recipients.ForEach(func(r common.Recipient) { recipientSet.Add(r) }) - if len(recipientSet.ToSlice()) != 0 { + if recipientSet.Len() != 0 { return recipientSet.ToSlice() } diff --git a/integrations/access/common/recipient.go b/integrations/access/common/recipient.go index fb3e967cab781..cdcf04bb725c7 100644 --- a/integrations/access/common/recipient.go +++ b/integrations/access/common/recipient.go @@ -152,3 +152,8 @@ func (s *RecipientSet) ForEach(f func(r Recipient)) { f(v) } } + +// Len returns number of recipients +func (s *RecipientSet) Len() int{ + return len(s.recipients) +} From 38213f4da6eee889c7cd66bd46342b58b9dcbd4a Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 21 May 2024 15:53:52 +0100 Subject: [PATCH 37/43] Add integration test for access monitoring rule and slack plugin --- integrations/access/slack/testlib/suite.go | 72 ++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/integrations/access/slack/testlib/suite.go b/integrations/access/slack/testlib/suite.go index f8f8840559c5a..50408b0d2a181 100644 --- a/integrations/access/slack/testlib/suite.go +++ b/integrations/access/slack/testlib/suite.go @@ -35,6 +35,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + accessmonitoringrulesv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessmonitoringrules/v1" + v1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" "github.com/gravitational/teleport/api/types/header" @@ -88,6 +90,7 @@ func (s *SlackBaseSuite) SetupTest() { conf.Slack.APIURL = s.fakeSlack.URL() + "/" conf.AccessTokenProvider = auth.NewStaticAccessTokenProvider(conf.Slack.Token) conf.StatusSink = s.fakeStatusSink + conf.PluginType = types.PluginTypeSlack s.appConfig = &conf } @@ -241,6 +244,75 @@ func (s *SlackSuiteOSS) TestRecipientsConfig() { assert.Equal(t, s.reviewer2SlackUser.ID, messages[2].Channel) } +func (s *SlackSuiteOSS) TestRecipientsFromAccessMonitoringRule() { + t := s.T() + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute) + t.Cleanup(cancel) + + // Setup base config to ensure access monitoring rule recipient take precidence + s.appConfig.Recipients = common.RawRecipientsMap{ + types.Wildcard: []string{ + s.reviewer2SlackUser.Profile.Email, + }, + } + + s.startApp() + const numMessages = 3 + + _, err := s.ClientByName(integration.RulerUserName). + AccessMonitoringRulesClient(). + CreateAccessMonitoringRule(ctx, &accessmonitoringrulesv1.AccessMonitoringRule{ + Kind: types.KindAccessMonitoringRule, + Version: types.V1, + Metadata: &v1.Metadata{ + Name: "test-slack-amr", + }, + Spec: &accessmonitoringrulesv1.AccessMonitoringRuleSpec{ + Subjects: []string{types.KindAccessRequest}, + Condition: "!is_empty(access_request.spec.roles)", + Notification: &accessmonitoringrulesv1.Notification{ + Name: "slack", + Recipients: []string{ + s.reviewer1SlackUser.ID, + s.reviewer2SlackUser.Profile.Email, + }, + }, + }, + }) + assert.NoError(t, err) + + // Test execution: we create an access request + userName := integration.RequesterOSSUserName + request := s.CreateAccessRequest(ctx, userName, nil) + pluginData := s.checkPluginData(ctx, request.GetName(), func(data accessrequest.PluginData) bool { + return len(data.SentMessages) > 0 + }) + assert.Len(t, pluginData.SentMessages, numMessages) + + var messages []slack.Message + + messageSet := make(SlackDataMessageSet) + + // Validate we got 3 messages: one for each recipient and one for the requester. + for i := 0; i < numMessages; i++ { + msg, err := s.fakeSlack.CheckNewMessage(ctx) + require.NoError(t, err) + messageSet.Add(accessrequest.MessageData{ChannelID: msg.Channel, MessageID: msg.Timestamp}) + messages = append(messages, msg) + } + + assert.Len(t, messageSet, numMessages) + for i := 0; i < numMessages; i++ { + assert.Contains(t, messageSet, pluginData.SentMessages[i]) + } + + // Validate the message recipients + sort.Sort(SlackMessageSlice(messages)) + assert.Equal(t, s.requesterOSSSlackUser.ID, messages[0].Channel) + assert.Equal(t, s.reviewer1SlackUser.ID, messages[1].Channel) + assert.Equal(t, s.reviewer2SlackUser.ID, messages[2].Channel) +} + // TestApproval tests that when a request is approved, its corresponding message // is updated to reflect the new request state. func (s *SlackSuiteOSS) TestApproval() { From 07e96a931c7b5fc847d70fe3f2678646432e3661 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Tue, 21 May 2024 16:43:33 +0100 Subject: [PATCH 38/43] Fix error types and messages when handling AMRs --- integrations/access/accessrequest/app.go | 4 ++-- integrations/access/accessrequest/request_mapping.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/integrations/access/accessrequest/app.go b/integrations/access/accessrequest/app.go index 1118026a37e12..d6b430279384c 100644 --- a/integrations/access/accessrequest/app.go +++ b/integrations/access/accessrequest/app.go @@ -176,7 +176,7 @@ func (a *App) onWatcherEvent(ctx context.Context, event types.Event) error { case types.KindAccessRequest: return trace.Wrap(a.handleAcessRequest(ctx, event)) } - return trace.Errorf("unexpected kind %s", event.Resource.GetKind()) + return trace.BadParameter("unexpected kind %s", event.Resource.GetKind()) } func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { @@ -189,7 +189,7 @@ func (a *App) handleAcessRequest(ctx context.Context, event types.Event) error { ctx, _ = logger.WithField(ctx, "request_op", "put") req, ok := event.Resource.(types.AccessRequest) if !ok { - return trace.Errorf("unexpected resource type %T", event.Resource) + return trace.BadParameter("unexpected resource type %T", event.Resource) } ctx, log := logger.WithField(ctx, "request_state", req.GetState().String()) diff --git a/integrations/access/accessrequest/request_mapping.go b/integrations/access/accessrequest/request_mapping.go index 538f2958da0c0..7bc46121d0c0e 100644 --- a/integrations/access/accessrequest/request_mapping.go +++ b/integrations/access/accessrequest/request_mapping.go @@ -47,7 +47,7 @@ func parseAccessRequestExpression(expr string) (accessRequestExpression, error) } parsedExpr, err := parser.Parse(expr) if err != nil { - return nil, trace.Wrap(err, "parsing label expression") + return nil, trace.Wrap(err, "parsing access monitoring rule condition expression") } return parsedExpr, nil } From 351e582ab595eba1764402e9d2fb06ab726bb5f8 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Thu, 23 May 2024 15:56:24 +0100 Subject: [PATCH 39/43] Use generic list resource with filter for AMR --- lib/services/local/access_monitoring_rules.go | 43 +++-------------- lib/services/local/generic/generic.go | 48 +++++++++++++++++++ lib/services/local/generic/generic_wrapper.go | 17 +++++++ 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/lib/services/local/access_monitoring_rules.go b/lib/services/local/access_monitoring_rules.go index 5c137bb1b065b..5b1e059b49517 100644 --- a/lib/services/local/access_monitoring_rules.go +++ b/lib/services/local/access_monitoring_rules.go @@ -35,8 +35,7 @@ const accessMonitoringRulesPrefix = "access_monitoring_rule" // AccessMonitoringRulesService manages AccessMonitoringRules in the Backend. type AccessMonitoringRulesService struct { - backend backend.Backend - svc *generic.ServiceWrapper[*accessmonitoringrulesv1.AccessMonitoringRule] + svc *generic.ServiceWrapper[*accessmonitoringrulesv1.AccessMonitoringRule] } // NewAccessMonitoringRulesService creates a new AccessMonitoringRulesService. @@ -50,8 +49,7 @@ func NewAccessMonitoringRulesService(backend backend.Backend) (*AccessMonitoring return nil, trace.Wrap(err) } return &AccessMonitoringRulesService{ - svc: service, - backend: backend, + svc: service, }, nil } @@ -116,40 +114,13 @@ func (s *AccessMonitoringRulesService) DeleteAllAccessMonitoringRules(ctx contex // ListAccessMonitoringRulesWithFilter returns a paginated list of access monitoring rules that match the given filter. func (s *AccessMonitoringRulesService) ListAccessMonitoringRulesWithFilter(ctx context.Context, pageSize int, pageToken string, subjects []string, notificationName string) ([]*accessmonitoringrulesv1.AccessMonitoringRule, string, error) { - - rangeStart := backend.Key(accessMonitoringRulesPrefix, pageToken) - rangeEnd := backend.RangeEnd(backend.ExactKey(accessMonitoringRulesPrefix)) - - // Get most limit+1 results to determine if there will be a next key. - maxLimit := pageSize + 1 - var resources []*accessmonitoringrulesv1.AccessMonitoringRule - if err := backend.IterateRange(ctx, s.backend, rangeStart, rangeEnd, maxLimit, func(items []backend.Item) (stop bool, err error) { - for _, item := range items { - if len(resources) == maxLimit { - break - } - - accessMonitoringRule, err := services.UnmarshalAccessMonitoringRule(item.Value) - if err != nil { - return false, trace.Wrap(err) - } - if ok := match(accessMonitoringRule, subjects, notificationName); ok { - resources = append(resources, accessMonitoringRule) - } - } - - return len(resources) == maxLimit, nil - }); err != nil { + resources, nextKey, err := s.svc.ListResourcesWithFilter(ctx, pageSize, pageToken, + func(resource *accessmonitoringrulesv1.AccessMonitoringRule) bool { + return match(resource, subjects, notificationName) + }) + if err != nil { return nil, "", trace.Wrap(err) } - - var nextKey string - if len(resources) > pageSize { - nextKey = resources[len(resources)-1].Metadata.Name - // Truncate the last item that was used to determine next row existence. - resources = resources[:pageSize] - } - return resources, nextKey, nil } diff --git a/lib/services/local/generic/generic.go b/lib/services/local/generic/generic.go index 5ba550aec092e..32c9069084782 100644 --- a/lib/services/local/generic/generic.go +++ b/lib/services/local/generic/generic.go @@ -213,6 +213,54 @@ func (s *Service[T]) ListResourcesReturnNextResource(ctx context.Context, pageSi return out, next, nil } +// ListResourcesWithFilter returns a paginated list of resources that match the given filter. +func (s *Service[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, pageToken string, matcher func(T) bool) ([]T, string, error) { + rangeStart := backend.Key(s.backendPrefix, pageToken) + rangeEnd := backend.RangeEnd(backend.ExactKey(s.backendPrefix)) + + // Adjust page size, so it can't be too large. + if pageSize <= 0 || pageSize > int(s.pageLimit) { + pageSize = int(s.pageLimit) + } + + limit := pageSize + 1 + + var resources []T + if err := backend.IterateRange( + ctx, + s.backend, + rangeStart, + rangeEnd, + limit, + func(items []backend.Item) (stop bool, err error) { + for _, item := range items { + resource, err := s.unmarshalFunc(item.Value, services.WithRevision(item.Revision), services.WithResourceID(item.ID)) + if err != nil { + return false, trace.Wrap(err) + } + if matcher(resource) { + resources = append(resources, resource) + } + if len(resources) == pageSize { + break + } + } + return limit == len(resources), nil + }); err != nil { + return nil, "", trace.Wrap(err) + } + + var nextKey string + if len(resources) > pageSize { + nextKey = backend.GetPaginationKey(resources[pageSize]) + // Truncate the last item that was used to determine next row existence. + resources = resources[:pageSize] + } + + return resources, nextKey, nil + +} + // GetResource returns the specified resource. func (s *Service[T]) GetResource(ctx context.Context, name string) (resource T, err error) { item, err := s.backend.Get(ctx, s.MakeKey(name)) diff --git a/lib/services/local/generic/generic_wrapper.go b/lib/services/local/generic/generic_wrapper.go index 25f2f910cf54a..3fa6fc1c1c418 100644 --- a/lib/services/local/generic/generic_wrapper.go +++ b/lib/services/local/generic/generic_wrapper.go @@ -132,3 +132,20 @@ func (s ServiceWrapper[T]) ListResources(ctx context.Context, pageSize int, page } return out, nextToken, trace.Wrap(err) } + +// ListResourcesWithFilter returns a paginated list of resources that match the provided filter. +func (s ServiceWrapper[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, pageToken string, matcher func(T) bool) ([]T, string, error) { + adapters, nextToken, err := s.service.ListResourcesWithFilter( + ctx, + pageSize, + pageToken, + func(rma resourceMetadataAdapter[T]) bool { + return matcher(rma.resource) + }) + + out := make([]T, 0, len(adapters)) + for _, adapter := range adapters { + out = append(out, adapter.resource) + } + return out, nextToken, trace.Wrap(err) +} From 0f603257000942cf7b27ca0940c33c700975f687 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 24 May 2024 15:09:01 +0100 Subject: [PATCH 40/43] Add test for generic listResourceWithFilter --- lib/services/local/generic/generic_test.go | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/lib/services/local/generic/generic_test.go b/lib/services/local/generic/generic_test.go index 3bc0c63e19613..9221cb34b6741 100644 --- a/lib/services/local/generic/generic_test.go +++ b/lib/services/local/generic/generic_test.go @@ -329,3 +329,50 @@ func TestGenericListResourcesReturnNextResource(t *testing.T) { )) require.Nil(t, next) } + +func TestGenericListResourcesWithFilter(t *testing.T) { + ctx := context.Background() + + memBackend, err := memory.New(memory.Config{ + Context: ctx, + Clock: clockwork.NewFakeClock(), + }) + require.NoError(t, err) + + service, err := NewService(&ServiceConfig[*testResource]{ + Backend: memBackend, + ResourceKind: "generic resource", + PageLimit: 200, + BackendPrefix: "generic_prefix", + UnmarshalFunc: unmarshalResource, + MarshalFunc: marshalResource, + }) + require.NoError(t, err) + + // Create a couple test resources. + r1 := newTestResource("r1") + r2 := newTestResource("r2") + + _, err = service.WithPrefix("a-unique-prefix").UpsertResource(ctx, r1) + require.NoError(t, err) + _, err = service.WithPrefix("another-unique-prefix").UpsertResource(ctx, r2) + require.NoError(t, err) + + page, nextKey, err := service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource)bool{ + return r.Metadata.Name == "r1" + }) + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r1}, page, + cmpopts.IgnoreFields(types.Metadata{}, "ID"), + )) + require.Equal(t, nextKey, "") + + page, nextKey, err = service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource)bool{ + return r.Metadata.Name == "r2" + }) + require.NoError(t, err) + require.Empty(t, cmp.Diff([]*testResource{r2}, page, + cmpopts.IgnoreFields(types.Metadata{}, "ID"), + )) + require.Equal(t, nextKey, "") +} From a048e9c921a8e3bcc7fcda628233c0fe9711c07c Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 24 May 2024 16:32:33 +0100 Subject: [PATCH 41/43] Update listResourceWithFilter to use revision instead of id --- lib/services/local/generic/generic.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/local/generic/generic.go b/lib/services/local/generic/generic.go index 32c9069084782..02a7648d67f9e 100644 --- a/lib/services/local/generic/generic.go +++ b/lib/services/local/generic/generic.go @@ -234,7 +234,7 @@ func (s *Service[T]) ListResourcesWithFilter(ctx context.Context, pageSize int, limit, func(items []backend.Item) (stop bool, err error) { for _, item := range items { - resource, err := s.unmarshalFunc(item.Value, services.WithRevision(item.Revision), services.WithResourceID(item.ID)) + resource, err := s.unmarshalFunc(item.Value, services.WithRevision(item.Revision), services.WithRevision(item.Revision)) if err != nil { return false, trace.Wrap(err) } From 2a41f478e4de371ced922115054f1bc25521a561 Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 24 May 2024 17:23:07 +0100 Subject: [PATCH 42/43] Update generic tests to use revision instead of id --- lib/services/local/generic/generic_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/local/generic/generic_test.go b/lib/services/local/generic/generic_test.go index 9221cb34b6741..e6d67ce2a2998 100644 --- a/lib/services/local/generic/generic_test.go +++ b/lib/services/local/generic/generic_test.go @@ -363,7 +363,7 @@ func TestGenericListResourcesWithFilter(t *testing.T) { }) require.NoError(t, err) require.Empty(t, cmp.Diff([]*testResource{r1}, page, - cmpopts.IgnoreFields(types.Metadata{}, "ID"), + cmpopts.IgnoreFields(types.Metadata{}, "Revision"), )) require.Equal(t, nextKey, "") @@ -372,7 +372,7 @@ func TestGenericListResourcesWithFilter(t *testing.T) { }) require.NoError(t, err) require.Empty(t, cmp.Diff([]*testResource{r2}, page, - cmpopts.IgnoreFields(types.Metadata{}, "ID"), + cmpopts.IgnoreFields(types.Metadata{}, "Revision"), )) require.Equal(t, nextKey, "") } From 28b99ebd46cb83ca1461d582d4983e22e8e75c7e Mon Sep 17 00:00:00 2001 From: EdwardDowling Date: Fri, 24 May 2024 18:24:03 +0100 Subject: [PATCH 43/43] Fix linting --- integrations/access/common/recipient.go | 2 +- integrations/access/slack/testlib/suite.go | 4 ++-- lib/services/local/generic/generic_test.go | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/integrations/access/common/recipient.go b/integrations/access/common/recipient.go index cdcf04bb725c7..67273cefa4b5b 100644 --- a/integrations/access/common/recipient.go +++ b/integrations/access/common/recipient.go @@ -154,6 +154,6 @@ func (s *RecipientSet) ForEach(f func(r Recipient)) { } // Len returns number of recipients -func (s *RecipientSet) Len() int{ +func (s *RecipientSet) Len() int { return len(s.recipients) } diff --git a/integrations/access/slack/testlib/suite.go b/integrations/access/slack/testlib/suite.go index 50408b0d2a181..f7e810b4a4b88 100644 --- a/integrations/access/slack/testlib/suite.go +++ b/integrations/access/slack/testlib/suite.go @@ -262,8 +262,8 @@ func (s *SlackSuiteOSS) TestRecipientsFromAccessMonitoringRule() { _, err := s.ClientByName(integration.RulerUserName). AccessMonitoringRulesClient(). CreateAccessMonitoringRule(ctx, &accessmonitoringrulesv1.AccessMonitoringRule{ - Kind: types.KindAccessMonitoringRule, - Version: types.V1, + Kind: types.KindAccessMonitoringRule, + Version: types.V1, Metadata: &v1.Metadata{ Name: "test-slack-amr", }, diff --git a/lib/services/local/generic/generic_test.go b/lib/services/local/generic/generic_test.go index e6d67ce2a2998..7dd43710ba98d 100644 --- a/lib/services/local/generic/generic_test.go +++ b/lib/services/local/generic/generic_test.go @@ -358,21 +358,21 @@ func TestGenericListResourcesWithFilter(t *testing.T) { _, err = service.WithPrefix("another-unique-prefix").UpsertResource(ctx, r2) require.NoError(t, err) - page, nextKey, err := service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource)bool{ + page, nextKey, err := service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource) bool { return r.Metadata.Name == "r1" }) require.NoError(t, err) require.Empty(t, cmp.Diff([]*testResource{r1}, page, cmpopts.IgnoreFields(types.Metadata{}, "Revision"), )) - require.Equal(t, nextKey, "") + require.Equal(t, "", nextKey) - page, nextKey, err = service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource)bool{ + page, nextKey, err = service.ListResourcesWithFilter(ctx, 1, "", func(r *testResource) bool { return r.Metadata.Name == "r2" }) require.NoError(t, err) require.Empty(t, cmp.Diff([]*testResource{r2}, page, cmpopts.IgnoreFields(types.Metadata{}, "Revision"), )) - require.Equal(t, nextKey, "") + require.Equal(t, "", nextKey) }