Skip to content

Commit

Permalink
[sec_scan][13] add AccessGraphSettings gRPC implementation
Browse files Browse the repository at this point in the history
This PR introduces the gRPC implementation for the CRUD operations related to `AccessGraphSettings`.

This PR is part of gravitational/access-graph#637.

Signed-off-by: Tiago Silva <[email protected]>
  • Loading branch information
tigrato committed Jul 11, 2024
1 parent 15ad483 commit 9b8679c
Show file tree
Hide file tree
Showing 2 changed files with 671 additions and 30 deletions.
207 changes: 207 additions & 0 deletions lib/auth/clusterconfig/clusterconfigv1/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/gravitational/teleport/api/constants"
clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/clusterconfig"
apievents "github.com/gravitational/teleport/api/types/events"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/authz"
Expand Down Expand Up @@ -63,6 +64,10 @@ type Backend interface {
CreateSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error)
UpdateSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error)
UpsertSessionRecordingConfig(ctx context.Context, preference types.SessionRecordingConfig) (types.SessionRecordingConfig, error)

CreateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error)
UpdateAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error)
UpsertAccessGraphSettings(context.Context, *clusterconfigpb.AccessGraphSettings) (*clusterconfigpb.AccessGraphSettings, error)
}

// ServiceConfig contain dependencies required to create a [Service].
Expand Down Expand Up @@ -933,12 +938,214 @@ func (s *Service) GetClusterAccessGraphConfig(ctx context.Context, _ *clustercon
}, nil
}

var sshScanEnabled bool
switch obj, err := s.readOnlyCache.GetReadOnlyAccessGraphSettings(ctx); {
case err != nil && !trace.IsNotFound(err):
return nil, trace.Wrap(err)
case err == nil:
sshScanEnabled = obj.SecretsScanConfig() == clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_ENABLED
}

return &clusterconfigpb.GetClusterAccessGraphConfigResponse{
AccessGraph: &clusterconfigpb.AccessGraphConfig{
Enabled: s.accessGraph.Enabled,
Address: s.accessGraph.Address,
Ca: s.accessGraph.CA,
Insecure: s.accessGraph.Insecure,
SecretsScanConfig: &clusterconfigpb.AccessGraphSecretsScanConfiguration{
SshScanEnabled: sshScanEnabled,
},
},
}, nil
}

func (s *Service) GetAccessGraphSettings(ctx context.Context, _ *clusterconfigpb.GetAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) {
authzCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbRead); err != nil {
return nil, trace.Wrap(err)
}

cfg, err := s.readOnlyCache.GetReadOnlyAccessGraphSettings(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

return cfg.Clone(), nil
}

func (s *Service) CreateAccessGraphSettings(ctx context.Context, req *clusterconfigpb.CreateAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) {
authzCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbCreate); err != nil {
return nil, trace.Wrap(err)
}

if !authz.HasBuiltinRole(*authzCtx, string(types.RoleAuth)) {
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

cfg := req.GetAccessGraphSettings()
if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil {
return nil, trace.Wrap(err)
}

created, err := s.backend.CreateAccessGraphSettings(ctx, cfg)
if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{
Metadata: apievents.Metadata{
Type: events.AccessGraphSettingsUpdateEvent,
Code: events.AccessGraphSettingsUpdateCode,
},
UserMetadata: authzCtx.GetUserMetadata(),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
Status: eventStatus(err),
}); auditErr != nil {
slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr)
}

// don't handle the update error until after we emit an audit event
if err != nil {
return nil, trace.Wrap(err)
}

return created, nil
}

func (s *Service) UpdateAccessGraphSettings(ctx context.Context, req *clusterconfigpb.UpdateAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) {
authzCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil {
return nil, trace.Wrap(err)
}

if !modules.GetModules().Features().GetEntitlement(entitlements.Policy).Enabled && !modules.GetModules().Features().AccessGraph {
return nil, trace.AccessDenied("access graph is feature isn't enabled")
}

cfg := req.GetAccessGraphSettings()
if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil {
return nil, trace.Wrap(err)
}

rsp, err := s.backend.UpdateAccessGraphSettings(ctx, cfg)

if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{
Metadata: apievents.Metadata{
Type: events.AccessGraphSettingsUpdateEvent,
Code: events.AccessGraphSettingsUpdateCode,
},
UserMetadata: authzCtx.GetUserMetadata(),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
Status: eventStatus(err),
}); auditErr != nil {
slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr)
}

if err != nil {
return nil, trace.Wrap(err)
}

return rsp, nil
}

func (s *Service) UpsertAccessGraphSettings(ctx context.Context, req *clusterconfigpb.UpsertAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) {
authzCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbCreate, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil {
return nil, trace.Wrap(err)
}

if !modules.GetModules().Features().GetEntitlement(entitlements.Policy).Enabled && !modules.GetModules().Features().AccessGraph {
return nil, trace.AccessDenied("access graph is feature isn't enabled")
}

cfg := req.GetAccessGraphSettings()
if err := clusterconfig.ValidateAccessGraphSettings(cfg); err != nil {
return nil, trace.Wrap(err)
}

rsp, err := s.backend.UpsertAccessGraphSettings(ctx, cfg)

if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{
Metadata: apievents.Metadata{
Type: events.AccessGraphSettingsUpdateEvent,
Code: events.AccessGraphSettingsUpdateCode,
},
UserMetadata: authzCtx.GetUserMetadata(),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
Status: eventStatus(err),
}); auditErr != nil {
slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr)
}

if err != nil {
return nil, trace.Wrap(err)
}

return rsp, nil
}

func (s *Service) ResetAccessGraphSettings(ctx context.Context, _ *clusterconfigpb.ResetAccessGraphSettingsRequest) (*clusterconfigpb.AccessGraphSettings, error) {
authzCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.CheckAccessToKind(types.KindAccessGraphSettings, types.VerbUpdate); err != nil {
return nil, trace.Wrap(err)
}

if err := authzCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil {
return nil, trace.Wrap(err)
}

if !modules.GetModules().Features().GetEntitlement(entitlements.Policy).Enabled && !modules.GetModules().Features().AccessGraph {
return nil, trace.AccessDenied("access graph is feature isn't enabled")
}

obj, err := clusterconfig.NewAccessGraphSettings(&clusterconfigpb.AccessGraphSettingsSpec{
SecretsScanConfig: clusterconfigpb.AccessGraphSecretsScanConfig_ACCESS_GRAPH_SECRETS_SCAN_CONFIG_DISABLED,
})
if err != nil {
return nil, trace.Wrap(err)
}
rsp, err := s.backend.UpsertAccessGraphSettings(ctx, obj)

if auditErr := s.emitter.EmitAuditEvent(ctx, &apievents.AccessGraphSettingsUpdate{
Metadata: apievents.Metadata{
Type: events.AccessGraphSettingsUpdateEvent,
Code: events.AccessGraphSettingsUpdateCode,
},
UserMetadata: authzCtx.GetUserMetadata(),
ConnectionMetadata: authz.ConnectionMetadata(ctx),
Status: eventStatus(err),
}); auditErr != nil {
slog.WarnContext(ctx, "Failed to emit AccessGraphSettings update event.", "error", auditErr)
}

if err != nil {
return nil, trace.Wrap(err)
}

return rsp, nil
}
Loading

0 comments on commit 9b8679c

Please sign in to comment.