Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AutoUpdateAgentRollout service and cache #47833

Open
wants to merge 1 commit into from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading