Skip to content

Commit

Permalink
Add AutoUpdateAgentRollout service and cache (#47833)
Browse files Browse the repository at this point in the history
  • Loading branch information
hugoShaka authored Oct 23, 2024
1 parent b1bc41f commit b9a5a8f
Show file tree
Hide file tree
Showing 13 changed files with 507 additions and 19 deletions.
53 changes: 53 additions & 0 deletions api/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,59 @@ func (c *Client) DeleteAutoUpdateVersion(ctx context.Context) error {
return trace.Wrap(err)
}

// CreateAutoUpdateAgentRollout creates AutoUpdateAgentRollout resource.
func (c *Client) CreateAutoUpdateAgentRollout(ctx context.Context, rollout *autoupdatev1pb.AutoUpdateAgentRollout) (*autoupdatev1pb.AutoUpdateAgentRollout, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.CreateAutoUpdateAgentRollout(ctx, &autoupdatev1pb.CreateAutoUpdateAgentRolloutRequest{
Rollout: rollout,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// GetAutoUpdateAgentRollout gets AutoUpdateAgentRollout resource.
func (c *Client) GetAutoUpdateAgentRollout(ctx context.Context) (*autoupdatev1pb.AutoUpdateAgentRollout, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.GetAutoUpdateAgentRollout(ctx, &autoupdatev1pb.GetAutoUpdateAgentRolloutRequest{})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// UpdateAutoUpdateAgentRollout updates AutoUpdateAgentRollout resource.
func (c *Client) UpdateAutoUpdateAgentRollout(ctx context.Context, rollout *autoupdatev1pb.AutoUpdateAgentRollout) (*autoupdatev1pb.AutoUpdateAgentRollout, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpdateAutoUpdateAgentRollout(ctx, &autoupdatev1pb.UpdateAutoUpdateAgentRolloutRequest{
Rollout: rollout,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// UpsertAutoUpdateAgentRollout updates or creates AutoUpdateAgentRollout resource.
func (c *Client) UpsertAutoUpdateAgentRollout(ctx context.Context, rollout *autoupdatev1pb.AutoUpdateAgentRollout) (*autoupdatev1pb.AutoUpdateAgentRollout, error) {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
resp, err := client.UpsertAutoUpdateAgentRollout(ctx, &autoupdatev1pb.UpsertAutoUpdateAgentRolloutRequest{
Rollout: rollout,
})
if err != nil {
return nil, trace.Wrap(err)
}
return resp, nil
}

// DeleteAutoUpdateAgentRollout deletes AutoUpdateAgentRollout resource.
func (c *Client) DeleteAutoUpdateAgentRollout(ctx context.Context) error {
client := autoupdatev1pb.NewAutoUpdateServiceClient(c.conn)
_, err := client.DeleteAutoUpdateAgentRollout(ctx, &autoupdatev1pb.DeleteAutoUpdateAgentRolloutRequest{})
return trace.Wrap(err)
}

// GetClusterAccessGraphConfig retrieves the Cluster Access Graph configuration from Auth server.
func (c *Client) GetClusterAccessGraphConfig(ctx context.Context) (*clusterconfigpb.AccessGraphConfig, error) {
rsp, err := c.ClusterConfigClient().GetClusterAccessGraphConfig(ctx, &clusterconfigpb.GetClusterAccessGraphConfigRequest{})
Expand Down
8 changes: 8 additions & 0 deletions api/client/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ func EventToGRPC(in types.Event) (*proto.Event, error) {
out.Resource = &proto.Event_ProvisioningPrincipalState{
ProvisioningPrincipalState: r,
}
case *autoupdate.AutoUpdateAgentRollout:
out.Resource = &proto.Event_AutoUpdateAgentRollout{
AutoUpdateAgentRollout: r,
}

default:
return nil, trace.BadParameter("resource type %T is not supported", r)
}
Expand Down Expand Up @@ -574,6 +579,9 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) {
} else if r := in.GetAutoUpdateVersion(); r != nil {
out.Resource = types.Resource153ToLegacy(r)
return &out, nil
} else if r := in.GetAutoUpdateAgentRollout(); r != nil {
out.Resource = types.Resource153ToLegacy(r)
return &out, nil
} else if r := in.GetUserTask(); r != nil {
out.Resource = types.Resource153ToLegacy(r)
return &out, nil
Expand Down
6 changes: 6 additions & 0 deletions lib/auth/authclient/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@ type ReadProxyAccessPoint interface {

// GetAutoUpdateVersion gets the AutoUpdateVersion from the backend.
GetAutoUpdateVersion(ctx context.Context) (*autoupdate.AutoUpdateVersion, error)

// GetAutoUpdateAgentRollout gets the AutoUpdateAgentRollout from the backend.
GetAutoUpdateAgentRollout(ctx context.Context) (*autoupdate.AutoUpdateAgentRollout, error)
}

// SnowflakeSessionWatcher is watcher interface used by Snowflake web session watcher.
Expand Down Expand Up @@ -1212,6 +1215,9 @@ type Cache interface {
// GetAutoUpdateVersion gets the AutoUpdateVersion from the backend.
GetAutoUpdateVersion(ctx context.Context) (*autoupdate.AutoUpdateVersion, error)

// GetAutoUpdateAgentRollout gets the AutoUpdateAgentRollout from the backend.
GetAutoUpdateAgentRollout(ctx context.Context) (*autoupdate.AutoUpdateAgentRollout, error)

// GetAccessGraphSettings returns the access graph settings.
GetAccessGraphSettings(context.Context) (*clusterconfigpb.AccessGraphSettings, error)

Expand Down
136 changes: 136 additions & 0 deletions lib/auth/autoupdate/autoupdatev1/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ type Cache interface {

// GetAutoUpdateVersion gets the AutoUpdateVersion from the backend.
GetAutoUpdateVersion(ctx context.Context) (*autoupdate.AutoUpdateVersion, error)

// GetAutoUpdateAgentRollout gets the AutoUpdateAgentRollout from the backend.
GetAutoUpdateAgentRollout(ctx context.Context) (*autoupdate.AutoUpdateAgentRollout, error)
}

// ServiceConfig holds configuration options for the auto update gRPC service.
Expand Down Expand Up @@ -268,3 +271,136 @@ func (s *Service) DeleteAutoUpdateVersion(ctx context.Context, req *autoupdate.D
}
return &emptypb.Empty{}, nil
}

// GetAutoUpdateAgentRollout gets the current AutoUpdateAgentRollout singleton.
func (s *Service) GetAutoUpdateAgentRollout(ctx context.Context, req *autoupdate.GetAutoUpdateAgentRolloutRequest) (*autoupdate.AutoUpdateAgentRollout, error) {
authCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

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

plan, err := s.cache.GetAutoUpdateAgentRollout(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

return plan, nil
}

// CreateAutoUpdateAgentRollout creates AutoUpdateAgentRollout singleton.
func (s *Service) CreateAutoUpdateAgentRollout(ctx context.Context, req *autoupdate.CreateAutoUpdateAgentRolloutRequest) (*autoupdate.AutoUpdateAgentRollout, error) {
authCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

// Editing the AU agent plan is restricted to cluster administrators. As of today we don't have any way of having
// resources that can only be edited by Teleport Cloud (when running cloud-hosted).
// The workaround is to check if the caller has the auth system role.
// This is not ideal as it forces local tctl usage. In the future, if we expand the permission system and make cloud
// a first class citizen, we'll want to update this permission check.
if !authz.HasBuiltinRole(*authCtx, string(types.RoleAuth)) {
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

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

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

autoUpdateAgentRollout, err := s.backend.CreateAutoUpdateAgentRollout(ctx, req.Rollout)
return autoUpdateAgentRollout, trace.Wrap(err)
}

// UpdateAutoUpdateAgentRollout updates AutoUpdateAgentRollout singleton.
func (s *Service) UpdateAutoUpdateAgentRollout(ctx context.Context, req *autoupdate.UpdateAutoUpdateAgentRolloutRequest) (*autoupdate.AutoUpdateAgentRollout, error) {
authCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

// Editing the AU agent plan is restricted to cluster administrators. As of today we don't have any way of having
// resources that can only be edited by Teleport Cloud (when running cloud-hosted).
// The workaround is to check if the caller has the auth system role.
// This is not ideal as it forces local tctl usage. In the future, if we expand the permission system and make cloud
// a first class citizen, we'll want to update this permission check.
if !authz.HasBuiltinRole(*authCtx, string(types.RoleAuth)) {
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

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

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

autoUpdateAgentRollout, err := s.backend.UpdateAutoUpdateAgentRollout(ctx, req.Rollout)
return autoUpdateAgentRollout, trace.Wrap(err)
}

// UpsertAutoUpdateAgentRollout updates or creates AutoUpdateAgentRollout singleton.
func (s *Service) UpsertAutoUpdateAgentRollout(ctx context.Context, req *autoupdate.UpsertAutoUpdateAgentRolloutRequest) (*autoupdate.AutoUpdateAgentRollout, error) {
authCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

// Editing the AU agent plan is restricted to cluster administrators. As of today we don't have any way of having
// resources that can only be edited by Teleport Cloud (when running cloud-hosted).
// The workaround is to check if the caller has the auth system role.
// This is not ideal as it forces local tctl usage. In the future, if we expand the permission system and make cloud
// a first class citizen, we'll want to update this permission check.
if !authz.HasBuiltinRole(*authCtx, string(types.RoleAuth)) {
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

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

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

autoUpdateAgentRollout, err := s.backend.UpsertAutoUpdateAgentRollout(ctx, req.Rollout)
return autoUpdateAgentRollout, trace.Wrap(err)
}

// DeleteAutoUpdateAgentRollout deletes AutoUpdateAgentRollout singleton.
func (s *Service) DeleteAutoUpdateAgentRollout(ctx context.Context, req *autoupdate.DeleteAutoUpdateAgentRolloutRequest) (*emptypb.Empty, error) {
authCtx, err := s.authorizer.Authorize(ctx)
if err != nil {
return nil, trace.Wrap(err)
}

// Editing the AU agent plan is restricted to cluster administrators. As of today we don't have any way of having
// resources that can only be edited by Teleport Cloud (when running cloud-hosted).
// The workaround is to check if the caller has the auth system role.
// This is not ideal as it forces local tctl usage. In the future, if we expand the permission system and make cloud
// a first class citizen, we'll want to update this permission check.
if !authz.HasBuiltinRole(*authCtx, string(types.RoleAuth)) {
return nil, trace.AccessDenied("this request can be only executed by an auth server")
}

if err := authCtx.CheckAccessToKind(types.KindAutoUpdateAgentRollout, types.VerbDelete); err != nil {
return nil, trace.Wrap(err)
}

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

if err := s.backend.DeleteAutoUpdateAgentRollout(ctx); err != nil {
return nil, trace.Wrap(err)
}
return &emptypb.Empty{}, nil
}
Loading

0 comments on commit b9a5a8f

Please sign in to comment.