From 83228d6c5a16cbbfda0020d35fa3f0bc4c63b017 Mon Sep 17 00:00:00 2001 From: Marco Dinis Date: Wed, 18 Sep 2024 08:16:52 +0100 Subject: [PATCH] rename from user integration task to user task --- api/client/client.go | 12 +- api/client/events.go | 10 +- .../userintegrationtask.go | 106 --------- api/client/usertask/usertask.go | 106 +++++++++ api/types/constants.go | 4 +- .../object.go | 32 +-- .../object_test.go | 24 +- lib/auth/accesspoint/accesspoint.go | 4 +- lib/auth/auth.go | 8 +- lib/auth/authclient/api.go | 20 +- lib/auth/authclient/clt.go | 12 +- lib/auth/grpcserver.go | 8 +- lib/auth/helpers.go | 2 +- lib/auth/init.go | 4 +- .../userintegrationtasksv1/service.go | 219 ------------------ lib/auth/usertasks/usertasksv1/service.go | 219 ++++++++++++++++++ .../usertasksv1}/service_test.go | 26 +-- lib/authz/permissions.go | 4 +- lib/cache/cache.go | 38 +-- lib/cache/cache_test.go | 48 ++-- lib/cache/collections.go | 52 ++--- lib/service/service.go | 8 +- lib/services/local/events.go | 18 +- lib/services/local/user_integration_task.go | 88 ------- lib/services/local/user_task.go | 88 +++++++ ...gration_task_test.go => user_task_test.go} | 104 ++++----- lib/services/presets.go | 2 +- lib/services/resource.go | 4 +- lib/services/user_integration_task.go | 53 ----- lib/services/user_task.go | 53 +++++ ...gration_task_test.go => user_task_test.go} | 42 ++-- lib/services/useracl.go | 8 +- tool/tctl/common/collection.go | 22 +- tool/tctl/common/resource_command.go | 48 ++-- 34 files changed, 746 insertions(+), 750 deletions(-) delete mode 100644 api/client/userintegrationtask/userintegrationtask.go create mode 100644 api/client/usertask/usertask.go rename api/types/{userintegrationtasks => usertasks}/object.go (63%) rename api/types/{userintegrationtasks => usertasks}/object_test.go (67%) delete mode 100644 lib/auth/userintegrationtasks/userintegrationtasksv1/service.go create mode 100644 lib/auth/usertasks/usertasksv1/service.go rename lib/auth/{userintegrationtasks/userintegrationtasksv1 => usertasks/usertasksv1}/service_test.go (83%) delete mode 100644 lib/services/local/user_integration_task.go create mode 100644 lib/services/local/user_task.go rename lib/services/local/{user_integration_task_test.go => user_task_test.go} (60%) delete mode 100644 lib/services/user_integration_task.go create mode 100644 lib/services/user_task.go rename lib/services/{user_integration_task_test.go => user_task_test.go} (68%) diff --git a/api/client/client.go b/api/client/client.go index 66f1de1792d30..a9f81264114ab 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -60,8 +60,8 @@ import ( "github.com/gravitational/teleport/api/client/scim" "github.com/gravitational/teleport/api/client/secreport" statichostuserclient "github.com/gravitational/teleport/api/client/statichostuser" - userintegrationtaskapi "github.com/gravitational/teleport/api/client/userintegrationtask" "github.com/gravitational/teleport/api/client/userloginstate" + usertaskapi "github.com/gravitational/teleport/api/client/usertask" "github.com/gravitational/teleport/api/constants" "github.com/gravitational/teleport/api/defaults" accesslistv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/accesslist/v1" @@ -87,10 +87,10 @@ import ( samlidppb "github.com/gravitational/teleport/api/gen/proto/go/teleport/samlidp/v1" secreportsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/secreports/v1" trustpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/trust/v1" - userintegrationtaskv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userloginstatev1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userloginstate/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" + usertaskv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/gen/proto/go/teleport/vnet/v1" userpreferencespb "github.com/gravitational/teleport/api/gen/proto/go/userpreferences/v1" "github.com/gravitational/teleport/api/internalutils/stream" @@ -4669,12 +4669,12 @@ func (c *Client) UserLoginStateClient() *userloginstate.Client { return userloginstate.NewClient(userloginstatev1.NewUserLoginStateServiceClient(c.conn)) } -// UserIntegrationTasksServiceClient returns a UserIntegrationTask client. -// Clients connecting to older Teleport versions, still get a UserIntegrationTask client +// UserTasksServiceClient returns a UserTask client. +// Clients connecting to older Teleport versions, still get a UserTask client // when calling this method, but all RPCs will return "not implemented" errors // (as per the default gRPC behavior). -func (c *Client) UserIntegrationTasksServiceClient() *userintegrationtaskapi.Client { - return userintegrationtaskapi.NewClient(userintegrationtaskv1.NewUserIntegrationTaskServiceClient(c.conn)) +func (c *Client) UserTasksServiceClient() *usertaskapi.Client { + return usertaskapi.NewClient(usertaskv1.NewUserTaskServiceClient(c.conn)) } // GetCertAuthority retrieves a CA by type and domain. diff --git a/api/client/events.go b/api/client/events.go index 1563a7dc7bc2e..7d7feb28bb013 100644 --- a/api/client/events.go +++ b/api/client/events.go @@ -25,8 +25,8 @@ import ( kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" accesslistv1conv "github.com/gravitational/teleport/api/types/accesslist/convert/v1" @@ -100,9 +100,9 @@ func EventToGRPC(in types.Event) (*proto.Event, error) { out.Resource = &proto.Event_StaticHostUserV2{ StaticHostUserV2: r, } - case *userintegrationtasksv1.UserIntegrationTask: - out.Resource = &proto.Event_UserIntegrationTask{ - UserIntegrationTask: r, + case *usertasksv1.UserTask: + out.Resource = &proto.Event_UserTask{ + UserTask: r, } default: return nil, trace.BadParameter("resource type %T is not supported", r) @@ -547,7 +547,7 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) { } else if r := in.GetStaticHostUserV2(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil - } else if r := in.GetUserIntegrationTask(); r != nil { + } else if r := in.GetUserTask(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil } else { diff --git a/api/client/userintegrationtask/userintegrationtask.go b/api/client/userintegrationtask/userintegrationtask.go deleted file mode 100644 index f5129a56d2027..0000000000000 --- a/api/client/userintegrationtask/userintegrationtask.go +++ /dev/null @@ -1,106 +0,0 @@ -// 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 userintegrationtask - -import ( - "context" - - "github.com/gravitational/trace" - - userintegrationtaskv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" -) - -// Client is a client for the User Integration Task API. -type Client struct { - grpcClient userintegrationtaskv1.UserIntegrationTaskServiceClient -} - -// NewClient creates a new User Integration Task client. -func NewClient(grpcClient userintegrationtaskv1.UserIntegrationTaskServiceClient) *Client { - return &Client{ - grpcClient: grpcClient, - } -} - -// ListUserIntegrationTasks returns a list of User Integration Tasks. -func (c *Client) ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextToken string) ([]*userintegrationtaskv1.UserIntegrationTask, string, error) { - resp, err := c.grpcClient.ListUserIntegrationTasks(ctx, &userintegrationtaskv1.ListUserIntegrationTasksRequest{ - PageSize: pageSize, - PageToken: nextToken, - }) - if err != nil { - return nil, "", trace.Wrap(err) - } - - return resp.UserIntegrationTasks, resp.NextPageToken, nil -} - -// CreateUserIntegrationTask creates a new User Integration Task. -func (c *Client) CreateUserIntegrationTask(ctx context.Context, req *userintegrationtaskv1.UserIntegrationTask) (*userintegrationtaskv1.UserIntegrationTask, error) { - rsp, err := c.grpcClient.CreateUserIntegrationTask(ctx, &userintegrationtaskv1.CreateUserIntegrationTaskRequest{ - UserIntegrationTask: req, - }) - if err != nil { - return nil, trace.Wrap(err) - } - return rsp, nil -} - -// GetUserIntegrationTask returns a User Integration Task by name. -func (c *Client) GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtaskv1.UserIntegrationTask, error) { - rsp, err := c.grpcClient.GetUserIntegrationTask(ctx, &userintegrationtaskv1.GetUserIntegrationTaskRequest{ - Name: name, - }) - if err != nil { - return nil, trace.Wrap(err) - } - return rsp, nil -} - -// UpdateUserIntegrationTask updates an existing User Integration Task. -func (c *Client) UpdateUserIntegrationTask(ctx context.Context, req *userintegrationtaskv1.UserIntegrationTask) (*userintegrationtaskv1.UserIntegrationTask, error) { - rsp, err := c.grpcClient.UpdateUserIntegrationTask(ctx, &userintegrationtaskv1.UpdateUserIntegrationTaskRequest{ - UserIntegrationTask: req, - }) - if err != nil { - return nil, trace.Wrap(err) - } - return rsp, nil -} - -// UpsertUserIntegrationTask upserts a User Integration Task. -func (c *Client) UpsertUserIntegrationTask(ctx context.Context, req *userintegrationtaskv1.UserIntegrationTask) (*userintegrationtaskv1.UserIntegrationTask, error) { - rsp, err := c.grpcClient.UpsertUserIntegrationTask(ctx, &userintegrationtaskv1.UpsertUserIntegrationTaskRequest{ - UserIntegrationTask: req, - }) - if err != nil { - return nil, trace.Wrap(err) - } - return rsp, nil -} - -// DeleteUserIntegrationTask deletes a User Integration Task. -func (c *Client) DeleteUserIntegrationTask(ctx context.Context, name string) error { - _, err := c.grpcClient.DeleteUserIntegrationTask(ctx, &userintegrationtaskv1.DeleteUserIntegrationTaskRequest{ - Name: name, - }) - return trace.Wrap(err) -} - -// DeleteAllUserIntegrationTasks deletes all User Integration Tasks. -// Not implemented. Added to satisfy the interface. -func (c *Client) DeleteAllUserIntegrationTasks(_ context.Context) error { - return trace.NotImplemented("DeleteAllUserIntegrationTasks is not implemented") -} diff --git a/api/client/usertask/usertask.go b/api/client/usertask/usertask.go new file mode 100644 index 0000000000000..5cb92983c3b8e --- /dev/null +++ b/api/client/usertask/usertask.go @@ -0,0 +1,106 @@ +// 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 usertask + +import ( + "context" + + "github.com/gravitational/trace" + + usertaskv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" +) + +// Client is a client for the User Task API. +type Client struct { + grpcClient usertaskv1.UserTaskServiceClient +} + +// NewClient creates a new User Task client. +func NewClient(grpcClient usertaskv1.UserTaskServiceClient) *Client { + return &Client{ + grpcClient: grpcClient, + } +} + +// ListUserTasks returns a list of User Tasks. +func (c *Client) ListUserTasks(ctx context.Context, pageSize int64, nextToken string) ([]*usertaskv1.UserTask, string, error) { + resp, err := c.grpcClient.ListUserTasks(ctx, &usertaskv1.ListUserTasksRequest{ + PageSize: pageSize, + PageToken: nextToken, + }) + if err != nil { + return nil, "", trace.Wrap(err) + } + + return resp.UserTasks, resp.NextPageToken, nil +} + +// CreateUserTask creates a new User Task. +func (c *Client) CreateUserTask(ctx context.Context, req *usertaskv1.UserTask) (*usertaskv1.UserTask, error) { + rsp, err := c.grpcClient.CreateUserTask(ctx, &usertaskv1.CreateUserTaskRequest{ + UserTask: req, + }) + if err != nil { + return nil, trace.Wrap(err) + } + return rsp, nil +} + +// GetUserTask returns a User Task by name. +func (c *Client) GetUserTask(ctx context.Context, name string) (*usertaskv1.UserTask, error) { + rsp, err := c.grpcClient.GetUserTask(ctx, &usertaskv1.GetUserTaskRequest{ + Name: name, + }) + if err != nil { + return nil, trace.Wrap(err) + } + return rsp, nil +} + +// UpdateUserTask updates an existing User Task. +func (c *Client) UpdateUserTask(ctx context.Context, req *usertaskv1.UserTask) (*usertaskv1.UserTask, error) { + rsp, err := c.grpcClient.UpdateUserTask(ctx, &usertaskv1.UpdateUserTaskRequest{ + UserTask: req, + }) + if err != nil { + return nil, trace.Wrap(err) + } + return rsp, nil +} + +// UpsertUserTask upserts a User Task. +func (c *Client) UpsertUserTask(ctx context.Context, req *usertaskv1.UserTask) (*usertaskv1.UserTask, error) { + rsp, err := c.grpcClient.UpsertUserTask(ctx, &usertaskv1.UpsertUserTaskRequest{ + UserTask: req, + }) + if err != nil { + return nil, trace.Wrap(err) + } + return rsp, nil +} + +// DeleteUserTask deletes a User Task. +func (c *Client) DeleteUserTask(ctx context.Context, name string) error { + _, err := c.grpcClient.DeleteUserTask(ctx, &usertaskv1.DeleteUserTaskRequest{ + Name: name, + }) + return trace.Wrap(err) +} + +// DeleteAllUserTasks deletes all User Tasks. +// Not implemented. Added to satisfy the interface. +func (c *Client) DeleteAllUserTasks(_ context.Context) error { + return trace.NotImplemented("DeleteAllUserTasks is not implemented") +} diff --git a/api/types/constants.go b/api/types/constants.go index bcfd38aad280e..88930e05bb568 100644 --- a/api/types/constants.go +++ b/api/types/constants.go @@ -485,8 +485,8 @@ const ( // KindIntegration is a connection to a 3rd party system API. KindIntegration = "integration" - // KindUserIntegrationTask is a task representing an issue with an integration. - KindUserIntegrationTask = "user_integration_task" + // KindUserTask is a task representing an issue with some other resource. + KindUserTask = "user_task" // KindClusterMaintenanceConfig determines maintenance times for the cluster. KindClusterMaintenanceConfig = "cluster_maintenance_config" diff --git a/api/types/userintegrationtasks/object.go b/api/types/usertasks/object.go similarity index 63% rename from api/types/userintegrationtasks/object.go rename to api/types/usertasks/object.go index 9de02d1c175ae..978d10c3d1121 100644 --- a/api/types/userintegrationtasks/object.go +++ b/api/types/usertasks/object.go @@ -16,21 +16,21 @@ * along with this program. If not, see . */ -package userintegrationtasks +package usertasks import ( "github.com/gravitational/trace" headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" ) -// NewUserIntegrationTask creates a new UserIntegrationTask object. +// NewUserTask creates a new UserTask object. // It validates the object before returning it. -func NewUserIntegrationTask(name string, spec *userintegrationtasksv1.UserIntegrationTaskSpec) (*userintegrationtasksv1.UserIntegrationTask, error) { - cj := &userintegrationtasksv1.UserIntegrationTask{ - Kind: types.KindUserIntegrationTask, +func NewUserTask(name string, spec *usertasksv1.UserTaskSpec) (*usertasksv1.UserTask, error) { + cj := &usertasksv1.UserTask{ + Kind: types.KindUserTask, Version: types.V1, Metadata: &headerv1.Metadata{ Name: name, @@ -38,7 +38,7 @@ func NewUserIntegrationTask(name string, spec *userintegrationtasksv1.UserIntegr Spec: spec, } - if err := ValidateUserIntegrationTask(cj); err != nil { + if err := ValidateUserTask(cj); err != nil { return nil, trace.Wrap(err) } @@ -46,27 +46,27 @@ func NewUserIntegrationTask(name string, spec *userintegrationtasksv1.UserIntegr } const ( - // TaskTypeDiscoverEC2 identifies a User Integration Tasks that is created + // TaskTypeDiscoverEC2 identifies a User Tasks that is created // when an auto-enrollment of an EC2 instance fails. - // UserIntegrationTasks that have this Task Type must include the DiscoverEC2 field. + // UserTasks that have this Task Type must include the DiscoverEC2 field. TaskTypeDiscoverEC2 = "discover-ec2" ) -// ValidateUserIntegrationTask validates the UserIntegrationTask object without modifying it. -func ValidateUserIntegrationTask(uit *userintegrationtasksv1.UserIntegrationTask) error { +// ValidateUserTask validates the UserTask object without modifying it. +func ValidateUserTask(uit *usertasksv1.UserTask) error { switch { - case uit.GetKind() != types.KindUserIntegrationTask: + case uit.GetKind() != types.KindUserTask: return trace.BadParameter("invalid kind") case uit.GetVersion() != types.V1: return trace.BadParameter("invalid version") case uit.GetSubKind() != "": return trace.BadParameter("invalid sub kind, must be empty") case uit.GetMetadata() == nil: - return trace.BadParameter("user integration task metadata is nil") + return trace.BadParameter("user task metadata is nil") case uit.Metadata.GetName() == "": - return trace.BadParameter("user integration task name is empty") + return trace.BadParameter("user task name is empty") case uit.GetSpec() == nil: - return trace.BadParameter("user integration task spec is nil") + return trace.BadParameter("user task spec is nil") case uit.GetSpec().Integration == "": return trace.BadParameter("integration is required") } @@ -83,7 +83,7 @@ func ValidateUserIntegrationTask(uit *userintegrationtasksv1.UserIntegrationTask return nil } -func validateDiscoverEC2TaskType(uit *userintegrationtasksv1.UserIntegrationTask) error { +func validateDiscoverEC2TaskType(uit *usertasksv1.UserTask) error { if uit.Spec.DiscoverEc2 == nil { return trace.BadParameter("%s requires the discover_ec2 field", TaskTypeDiscoverEC2) } diff --git a/api/types/userintegrationtasks/object_test.go b/api/types/usertasks/object_test.go similarity index 67% rename from api/types/userintegrationtasks/object_test.go rename to api/types/usertasks/object_test.go index 6c76f1a0ce25b..a8f4c6769ca82 100644 --- a/api/types/userintegrationtasks/object_test.go +++ b/api/types/usertasks/object_test.go @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package userintegrationtasks_test +package usertasks_test import ( "testing" @@ -24,36 +24,36 @@ import ( "github.com/stretchr/testify/require" headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" - "github.com/gravitational/teleport/api/types/userintegrationtasks" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" + "github.com/gravitational/teleport/api/types/usertasks" ) -func TestValidateUserIntegrationTask(t *testing.T) { +func TestValidateUserTask(t *testing.T) { t.Parallel() tests := []struct { name string - task *userintegrationtasksv1.UserIntegrationTask + task *usertasksv1.UserTask wantErr require.ErrorAssertionFunc }{ { - name: "NilUserIntegrationTask", + name: "NilUserTask", task: nil, wantErr: require.Error, }, { - name: "ValidUserIntegrationTask", - task: &userintegrationtasksv1.UserIntegrationTask{ - Kind: "user_integration_task", + name: "ValidUserTask", + task: &usertasksv1.UserTask{ + Kind: "user_task", Version: "v1", Metadata: &headerv1.Metadata{ Name: "test", }, - Spec: &userintegrationtasksv1.UserIntegrationTaskSpec{ + Spec: &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "failed to enroll ec2 instances", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{}, + DiscoverEc2: &usertasksv1.DiscoverEC2{}, }, }, wantErr: require.NoError, @@ -62,7 +62,7 @@ func TestValidateUserIntegrationTask(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := userintegrationtasks.ValidateUserIntegrationTask(tt.task) + err := usertasks.ValidateUserTask(tt.task) tt.wantErr(t, err) }) } diff --git a/lib/auth/accesspoint/accesspoint.go b/lib/auth/accesspoint/accesspoint.go index b08c49323fc03..f0124a0ed48e7 100644 --- a/lib/auth/accesspoint/accesspoint.go +++ b/lib/auth/accesspoint/accesspoint.go @@ -98,7 +98,7 @@ type Config struct { StaticHostUsers services.StaticHostUser Trust services.Trust UserGroups services.UserGroups - UserIntegrationTasks services.UserIntegrationTasks + UserTasks services.UserTasks UserLoginStates services.UserLoginStates Users services.UsersService WebSession types.WebSessionInterface @@ -192,7 +192,7 @@ func NewCache(cfg Config) (*cache.Cache, error) { Trust: cfg.Trust, UserGroups: cfg.UserGroups, UserLoginStates: cfg.UserLoginStates, - UserIntegrationTasks: cfg.UserIntegrationTasks, + UserTasks: cfg.UserTasks, Users: cfg.Users, WebSession: cfg.WebSession, WebToken: cfg.WebToken, diff --git a/lib/auth/auth.go b/lib/auth/auth.go index ed20d7d29b4f6..49f83e6be83aa 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -315,8 +315,8 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) { return nil, trace.Wrap(err) } } - if cfg.UserIntegrationTasks == nil { - cfg.UserIntegrationTasks, err = local.NewUserIntegrationTasksService(cfg.Backend) + if cfg.UserTasks == nil { + cfg.UserTasks, err = local.NewUserTasksService(cfg.Backend) if err != nil { return nil, trace.Wrap(err) } @@ -436,7 +436,7 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) { SessionTrackerService: cfg.SessionTrackerService, ConnectionsDiagnostic: cfg.ConnectionsDiagnostic, Integrations: cfg.Integrations, - UserIntegrationTasks: cfg.UserIntegrationTasks, + UserTasks: cfg.UserTasks, DiscoveryConfigs: cfg.DiscoveryConfigs, Okta: cfg.Okta, AccessLists: cfg.AccessLists, @@ -637,7 +637,7 @@ type Services struct { services.StatusInternal services.Integrations services.IntegrationsTokenGenerator - services.UserIntegrationTasks + services.UserTasks services.DiscoveryConfigs services.Okta services.AccessLists diff --git a/lib/auth/authclient/api.go b/lib/auth/authclient/api.go index 25f7fb2d6917d..4f7e8935173ec 100644 --- a/lib/auth/authclient/api.go +++ b/lib/auth/authclient/api.go @@ -33,9 +33,9 @@ import ( integrationpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/integration/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" "github.com/gravitational/teleport/api/types/discoveryconfig" @@ -797,8 +797,8 @@ type DiscoveryAccessPoint interface { // UpdateDiscoveryConfigStatus updates the status of a discovery config. UpdateDiscoveryConfigStatus(ctx context.Context, name string, status discoveryconfig.Status) (*discoveryconfig.DiscoveryConfig, error) - // UpsertUserIntegrationTask creates or updates an User Integration Task - UpsertUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) + // UpsertUserTask creates or updates an User Task + UpsertUserTask(ctx context.Context, req *usertasksv1.UserTask) (*usertasksv1.UserTask, error) } // ReadOktaAccessPoint is a read only API interface to be @@ -1167,10 +1167,10 @@ type Cache interface { // IntegrationsGetter defines read/list methods for integrations. services.IntegrationsGetter - // GetUserIntegrationTask returns the user integration tasks resource by name. - GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) - // ListUserIntegrationTasks returns the user integration tasks resources. - ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextToken string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) + // GetUserTask returns the user tasks resource by name. + GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) + // ListUserTasks returns the user tasks resources. + ListUserTasks(ctx context.Context, pageSize int64, nextToken string) ([]*usertasksv1.UserTask, string, error) // NotificationGetter defines list methods for notifications. services.NotificationGetter @@ -1433,9 +1433,9 @@ func (w *DiscoveryWrapper) UpdateDiscoveryConfigStatus(ctx context.Context, name return w.NoCache.UpdateDiscoveryConfigStatus(ctx, name, status) } -// UpserUserIntegrationTask creates or updates an User Integration Task. -func (w *DiscoveryWrapper) UpsertUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) { - return w.NoCache.UpsertUserIntegrationTask(ctx, req) +// UpserUserTask creates or updates an User Task. +func (w *DiscoveryWrapper) UpsertUserTask(ctx context.Context, req *usertasksv1.UserTask) (*usertasksv1.UserTask, error) { + return w.NoCache.UpsertUserTask(ctx, req) } // Close closes all associated resources diff --git a/lib/auth/authclient/clt.go b/lib/auth/authclient/clt.go index 3180575b38dfc..142a078b21a72 100644 --- a/lib/auth/authclient/clt.go +++ b/lib/auth/authclient/clt.go @@ -36,7 +36,7 @@ import ( "github.com/gravitational/teleport/api/client/externalauditstorage" "github.com/gravitational/teleport/api/client/proto" "github.com/gravitational/teleport/api/client/secreport" - "github.com/gravitational/teleport/api/client/userintegrationtask" + "github.com/gravitational/teleport/api/client/usertask" apidefaults "github.com/gravitational/teleport/api/defaults" accessgraphsecretsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/accessgraph/v1" clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" @@ -663,9 +663,9 @@ func (c *Client) IntegrationAWSOIDCClient() integrationv1.AWSOIDCServiceClient { return integrationv1.NewAWSOIDCServiceClient(c.APIClient.GetConnection()) } -// UserIntegrationTasksClient returns a client for managing User Integration Task resources. -func (c *Client) UserIntegrationTasksClient() services.UserIntegrationTasks { - return c.APIClient.UserIntegrationTasksServiceClient() +// UserTasksClient returns a client for managing User Task resources. +func (c *Client) UserTasksClient() services.UserTasks { + return c.APIClient.UserTasksServiceClient() } func (c *Client) NotificationServiceClient() notificationsv1.NotificationServiceClient { @@ -1611,8 +1611,8 @@ type ClientI interface { // IntegrationAWSOIDCClient returns a client to the Integration AWS OIDC gRPC service. IntegrationAWSOIDCClient() integrationv1.AWSOIDCServiceClient - // UserIntegrationTasksServiceClient returns an User Integration Task service client. - UserIntegrationTasksServiceClient() *userintegrationtask.Client + // UserTasksServiceClient returns an User Task service client. + UserTasksServiceClient() *usertask.Client // NewKeepAliver returns a new instance of keep aliver NewKeepAliver(ctx context.Context) (types.KeepAliver, error) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index be9810df36127..4f69c24db88b0 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -65,10 +65,10 @@ import ( notificationsv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" presencev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/presence/v1" trustv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/trust/v1" - userintegrationtaskv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userloginstatev1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userloginstate/v1" userprovisioningv2pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" usersv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" + usertaskv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" vnetv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/vnet/v1" userpreferencesv1pb "github.com/gravitational/teleport/api/gen/proto/go/userpreferences/v1" "github.com/gravitational/teleport/api/internalutils/stream" @@ -92,11 +92,11 @@ import ( "github.com/gravitational/teleport/lib/auth/notifications/notificationsv1" "github.com/gravitational/teleport/lib/auth/presence/presencev1" "github.com/gravitational/teleport/lib/auth/trust/trustv1" - "github.com/gravitational/teleport/lib/auth/userintegrationtasks/userintegrationtasksv1" "github.com/gravitational/teleport/lib/auth/userloginstate/userloginstatev1" "github.com/gravitational/teleport/lib/auth/userpreferences/userpreferencesv1" "github.com/gravitational/teleport/lib/auth/userprovisioning/userprovisioningv2" "github.com/gravitational/teleport/lib/auth/users/usersv1" + "github.com/gravitational/teleport/lib/auth/usertasks/usertasksv1" "github.com/gravitational/teleport/lib/auth/vnetconfig/vnetconfigv1" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/backend" @@ -5311,7 +5311,7 @@ func NewGRPCServer(cfg GRPCServerConfig) (*GRPCServer, error) { } integrationv1pb.RegisterAWSOIDCServiceServer(server, integrationAWSOIDCServiceServer) - userIntegrationTask, err := userintegrationtasksv1.NewService(userintegrationtasksv1.ServiceConfig{ + userTask, err := usertasksv1.NewService(usertasksv1.ServiceConfig{ Authorizer: cfg.Authorizer, Backend: cfg.AuthServer.Services, Cache: cfg.AuthServer.Cache, @@ -5319,7 +5319,7 @@ func NewGRPCServer(cfg GRPCServerConfig) (*GRPCServer, error) { if err != nil { return nil, trace.Wrap(err) } - userintegrationtaskv1pb.RegisterUserIntegrationTaskServiceServer(server, userIntegrationTask) + usertaskv1pb.RegisterUserTaskServiceServer(server, userTask) discoveryConfig, err := discoveryconfigv1.NewService(discoveryconfigv1.ServiceConfig{ Authorizer: cfg.Authorizer, diff --git a/lib/auth/helpers.go b/lib/auth/helpers.go index f474c03460d12..5ee4fb11d19f8 100644 --- a/lib/auth/helpers.go +++ b/lib/auth/helpers.go @@ -347,7 +347,7 @@ func NewTestAuthServer(cfg TestAuthServerConfig) (*TestAuthServer, error) { StaticHostUsers: svces.StaticHostUser, Trust: svces.TrustInternal, UserGroups: svces.UserGroups, - UserIntegrationTasks: svces.UserIntegrationTasks, + UserTasks: svces.UserTasks, UserLoginStates: svces.UserLoginStates, Users: svces.Identity, WebSession: svces.Identity.WebSessions(), diff --git a/lib/auth/init.go b/lib/auth/init.go index e891e271d9928..281d8c6e4f2c4 100644 --- a/lib/auth/init.go +++ b/lib/auth/init.go @@ -233,8 +233,8 @@ type InitConfig struct { // Integrations is a service that manages Integrations. Integrations services.Integrations - // UserIntegrationTasks is a service that manages UserIntegrationTasks. - UserIntegrationTasks services.UserIntegrationTasks + // UserTasks is a service that manages UserTasks. + UserTasks services.UserTasks // DiscoveryConfigs is a service that manages DiscoveryConfigs. DiscoveryConfigs services.DiscoveryConfigs diff --git a/lib/auth/userintegrationtasks/userintegrationtasksv1/service.go b/lib/auth/userintegrationtasks/userintegrationtasksv1/service.go deleted file mode 100644 index 2b98c371f425d..0000000000000 --- a/lib/auth/userintegrationtasks/userintegrationtasksv1/service.go +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Teleport - * Copyright (C) 2024 Gravitational, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package userintegrationtasksv1 - -import ( - "context" - - "github.com/gravitational/trace" - "google.golang.org/protobuf/types/known/emptypb" - - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" - "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/api/types/userintegrationtasks" - "github.com/gravitational/teleport/lib/authz" - "github.com/gravitational/teleport/lib/services" -) - -// ServiceConfig holds configuration options for the UserIntegrationTask gRPC service. -type ServiceConfig struct { - // Authorizer is the authorizer to use. - Authorizer authz.Authorizer - - // Backend is the backend for storing UserIntegrationTask. - Backend services.UserIntegrationTasks - - // Cache is the cache for storing UserIntegrationTask. - Cache Reader -} - -// CheckAndSetDefaults checks the ServiceConfig fields and returns an error if -// a required param is not provided. -// Authorizer, Cache and Backend are required params -func (s *ServiceConfig) CheckAndSetDefaults() error { - if s.Authorizer == nil { - return trace.BadParameter("authorizer is required") - } - if s.Backend == nil { - return trace.BadParameter("backend is required") - } - if s.Cache == nil { - return trace.BadParameter("cache is required") - } - - return nil -} - -// Reader contains the methods defined for cache access. -type Reader interface { - ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextToken string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) - GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) -} - -// Service implements the teleport.UserIntegrationTask.v1.UserIntegrationTaskService RPC service. -type Service struct { - userintegrationtasksv1.UnimplementedUserIntegrationTaskServiceServer - - authorizer authz.Authorizer - backend services.UserIntegrationTasks - cache Reader -} - -// NewService returns a new UserIntegrationTask gRPC service. -func NewService(cfg ServiceConfig) (*Service, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - - return &Service{ - authorizer: cfg.Authorizer, - backend: cfg.Backend, - cache: cfg.Cache, - }, nil -} - -// CreateUserIntegrationTask creates user integration task resource. -func (s *Service) CreateUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.CreateUserIntegrationTaskRequest) (*userintegrationtasksv1.UserIntegrationTask, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbCreate); err != nil { - return nil, trace.Wrap(err) - } - - if err := userintegrationtasks.ValidateUserIntegrationTask(req.UserIntegrationTask); err != nil { - return nil, trace.Wrap(err) - } - - rsp, err := s.backend.CreateUserIntegrationTask(ctx, req.UserIntegrationTask) - if err != nil { - return nil, trace.Wrap(err) - } - - return rsp, nil -} - -// ListUserIntegrationTasks returns a list of user integration tasks. -func (s *Service) ListUserIntegrationTasks(ctx context.Context, req *userintegrationtasksv1.ListUserIntegrationTasksRequest) (*userintegrationtasksv1.ListUserIntegrationTasksResponse, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbRead, types.VerbList); err != nil { - return nil, trace.Wrap(err) - } - - rsp, nextToken, err := s.cache.ListUserIntegrationTasks(ctx, req.PageSize, req.PageToken) - if err != nil { - return nil, trace.Wrap(err) - } - - return &userintegrationtasksv1.ListUserIntegrationTasksResponse{ - UserIntegrationTasks: rsp, - NextPageToken: nextToken, - }, nil -} - -// GetUserIntegrationTask returns user integration task resource. -func (s *Service) GetUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.GetUserIntegrationTaskRequest) (*userintegrationtasksv1.UserIntegrationTask, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbRead); err != nil { - return nil, trace.Wrap(err) - } - - rsp, err := s.cache.GetUserIntegrationTask(ctx, req.GetName()) - if err != nil { - return nil, trace.Wrap(err) - } - - return rsp, nil - -} - -// UpdateUserIntegrationTask updates user integration task resource. -func (s *Service) UpdateUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.UpdateUserIntegrationTaskRequest) (*userintegrationtasksv1.UserIntegrationTask, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbUpdate); err != nil { - return nil, trace.Wrap(err) - } - - if err := userintegrationtasks.ValidateUserIntegrationTask(req.UserIntegrationTask); err != nil { - return nil, trace.Wrap(err) - } - - rsp, err := s.backend.UpdateUserIntegrationTask(ctx, req.UserIntegrationTask) - if err != nil { - return nil, trace.Wrap(err) - } - - return rsp, nil -} - -// UpsertUserIntegrationTask upserts user integration task resource. -func (s *Service) UpsertUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.UpsertUserIntegrationTaskRequest) (*userintegrationtasksv1.UserIntegrationTask, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbUpdate, types.VerbCreate); err != nil { - return nil, trace.Wrap(err) - } - - if err := userintegrationtasks.ValidateUserIntegrationTask(req.UserIntegrationTask); err != nil { - return nil, trace.Wrap(err) - } - - rsp, err := s.backend.UpsertUserIntegrationTask(ctx, req.UserIntegrationTask) - if err != nil { - return nil, trace.Wrap(err) - } - - return rsp, nil - -} - -// DeleteUserIntegrationTask deletes user integration task resource. -func (s *Service) DeleteUserIntegrationTask(ctx context.Context, req *userintegrationtasksv1.DeleteUserIntegrationTaskRequest) (*emptypb.Empty, error) { - authCtx, err := s.authorizer.Authorize(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - if err := authCtx.CheckAccessToKind(types.KindUserIntegrationTask, types.VerbDelete); err != nil { - return nil, trace.Wrap(err) - } - - if err := s.backend.DeleteUserIntegrationTask(ctx, req.GetName()); err != nil { - return nil, trace.Wrap(err) - } - - return &emptypb.Empty{}, nil -} diff --git a/lib/auth/usertasks/usertasksv1/service.go b/lib/auth/usertasks/usertasksv1/service.go new file mode 100644 index 0000000000000..a8ec00a184c9c --- /dev/null +++ b/lib/auth/usertasks/usertasksv1/service.go @@ -0,0 +1,219 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package usertasksv1 + +import ( + "context" + + "github.com/gravitational/trace" + "google.golang.org/protobuf/types/known/emptypb" + + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/api/types/usertasks" + "github.com/gravitational/teleport/lib/authz" + "github.com/gravitational/teleport/lib/services" +) + +// ServiceConfig holds configuration options for the UserTask gRPC service. +type ServiceConfig struct { + // Authorizer is the authorizer to use. + Authorizer authz.Authorizer + + // Backend is the backend for storing UserTask. + Backend services.UserTasks + + // Cache is the cache for storing UserTask. + Cache Reader +} + +// CheckAndSetDefaults checks the ServiceConfig fields and returns an error if +// a required param is not provided. +// Authorizer, Cache and Backend are required params +func (s *ServiceConfig) CheckAndSetDefaults() error { + if s.Authorizer == nil { + return trace.BadParameter("authorizer is required") + } + if s.Backend == nil { + return trace.BadParameter("backend is required") + } + if s.Cache == nil { + return trace.BadParameter("cache is required") + } + + return nil +} + +// Reader contains the methods defined for cache access. +type Reader interface { + ListUserTasks(ctx context.Context, pageSize int64, nextToken string) ([]*usertasksv1.UserTask, string, error) + GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) +} + +// Service implements the teleport.UserTask.v1.UserTaskService RPC service. +type Service struct { + usertasksv1.UnimplementedUserTaskServiceServer + + authorizer authz.Authorizer + backend services.UserTasks + cache Reader +} + +// NewService returns a new UserTask gRPC service. +func NewService(cfg ServiceConfig) (*Service, error) { + if err := cfg.CheckAndSetDefaults(); err != nil { + return nil, trace.Wrap(err) + } + + return &Service{ + authorizer: cfg.Authorizer, + backend: cfg.Backend, + cache: cfg.Cache, + }, nil +} + +// CreateUserTask creates user task resource. +func (s *Service) CreateUserTask(ctx context.Context, req *usertasksv1.CreateUserTaskRequest) (*usertasksv1.UserTask, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbCreate); err != nil { + return nil, trace.Wrap(err) + } + + if err := usertasks.ValidateUserTask(req.UserTask); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.backend.CreateUserTask(ctx, req.UserTask) + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil +} + +// ListUserTasks returns a list of user tasks. +func (s *Service) ListUserTasks(ctx context.Context, req *usertasksv1.ListUserTasksRequest) (*usertasksv1.ListUserTasksResponse, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbRead, types.VerbList); err != nil { + return nil, trace.Wrap(err) + } + + rsp, nextToken, err := s.cache.ListUserTasks(ctx, req.PageSize, req.PageToken) + if err != nil { + return nil, trace.Wrap(err) + } + + return &usertasksv1.ListUserTasksResponse{ + UserTasks: rsp, + NextPageToken: nextToken, + }, nil +} + +// GetUserTask returns user task resource. +func (s *Service) GetUserTask(ctx context.Context, req *usertasksv1.GetUserTaskRequest) (*usertasksv1.UserTask, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbRead); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.cache.GetUserTask(ctx, req.GetName()) + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil + +} + +// UpdateUserTask updates user task resource. +func (s *Service) UpdateUserTask(ctx context.Context, req *usertasksv1.UpdateUserTaskRequest) (*usertasksv1.UserTask, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + + if err := usertasks.ValidateUserTask(req.UserTask); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.backend.UpdateUserTask(ctx, req.UserTask) + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil +} + +// UpsertUserTask upserts user task resource. +func (s *Service) UpsertUserTask(ctx context.Context, req *usertasksv1.UpsertUserTaskRequest) (*usertasksv1.UserTask, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbUpdate, types.VerbCreate); err != nil { + return nil, trace.Wrap(err) + } + + if err := usertasks.ValidateUserTask(req.UserTask); err != nil { + return nil, trace.Wrap(err) + } + + rsp, err := s.backend.UpsertUserTask(ctx, req.UserTask) + if err != nil { + return nil, trace.Wrap(err) + } + + return rsp, nil + +} + +// DeleteUserTask deletes user task resource. +func (s *Service) DeleteUserTask(ctx context.Context, req *usertasksv1.DeleteUserTaskRequest) (*emptypb.Empty, error) { + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + if err := authCtx.CheckAccessToKind(types.KindUserTask, types.VerbDelete); err != nil { + return nil, trace.Wrap(err) + } + + if err := s.backend.DeleteUserTask(ctx, req.GetName()); err != nil { + return nil, trace.Wrap(err) + } + + return &emptypb.Empty{}, nil +} diff --git a/lib/auth/userintegrationtasks/userintegrationtasksv1/service_test.go b/lib/auth/usertasks/usertasksv1/service_test.go similarity index 83% rename from lib/auth/userintegrationtasks/userintegrationtasksv1/service_test.go rename to lib/auth/usertasks/usertasksv1/service_test.go index 797e40e030fe5..3b9627c1ada73 100644 --- a/lib/auth/userintegrationtasks/userintegrationtasksv1/service_test.go +++ b/lib/auth/usertasks/usertasksv1/service_test.go @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package userintegrationtasksv1 +package usertasksv1 import ( "context" @@ -27,7 +27,7 @@ import ( "github.com/gravitational/trace" "github.com/stretchr/testify/require" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/authz" "github.com/gravitational/teleport/lib/backend/memory" @@ -45,27 +45,27 @@ func TestServiceAccess(t *testing.T) { allowedStates []authz.AdminActionAuthState }{ { - name: "CreateUserIntegrationTask", + name: "CreateUserTask", allowedVerbs: []string{types.VerbCreate}, }, { - name: "UpdateUserIntegrationTask", + name: "UpdateUserTask", allowedVerbs: []string{types.VerbUpdate}, }, { - name: "DeleteUserIntegrationTask", + name: "DeleteUserTask", allowedVerbs: []string{types.VerbDelete}, }, { - name: "UpsertUserIntegrationTask", + name: "UpsertUserTask", allowedVerbs: []string{types.VerbCreate, types.VerbUpdate}, }, { - name: "ListUserIntegrationTasks", + name: "ListUserTasks", allowedVerbs: []string{types.VerbRead, types.VerbList}, }, { - name: "GetUserIntegrationTask", + name: "GetUserTask", allowedVerbs: []string{types.VerbRead}, }, } @@ -89,7 +89,7 @@ func TestServiceAccess(t *testing.T) { // verify that all declared methods have matching test cases t.Run("verify coverage", func(t *testing.T) { - for _, method := range userintegrationtasksv1.UserIntegrationTaskService_ServiceDesc.Methods { + for _, method := range usertasksv1.UserTaskService_ServiceDesc.Methods { t.Run(method.MethodName, func(t *testing.T) { match := false for _, testCase := range testCases { @@ -101,9 +101,9 @@ func TestServiceAccess(t *testing.T) { }) } -// callMethod calls a method with given name in the UserIntegrationTask service +// callMethod calls a method with given name in the UserTask service func callMethod(t *testing.T, service *Service, method string) error { - for _, desc := range userintegrationtasksv1.UserIntegrationTaskService_ServiceDesc.Methods { + for _, desc := range usertasksv1.UserTaskService_ServiceDesc.Methods { if desc.MethodName == method { _, err := desc.Handler(service, context.Background(), func(_ any) error { return nil }, nil) return err @@ -119,7 +119,7 @@ type fakeChecker struct { } func (f fakeChecker) CheckAccessToRule(_ services.RuleContext, _ string, resource string, verb string) error { - if resource == types.KindUserIntegrationTask { + if resource == types.KindUserTask { if slices.Contains(f.allowedVerbs, verb) { return nil } @@ -134,7 +134,7 @@ func newService(t *testing.T, checker services.AccessChecker) *Service { b, err := memory.New(memory.Config{}) require.NoError(t, err) - backendService, err := local.NewUserIntegrationTasksService(b) + backendService, err := local.NewUserTasksService(b) require.NoError(t, err) authorizer := authz.AuthorizerFunc(func(ctx context.Context) (*authz.Context, error) { diff --git a/lib/authz/permissions.go b/lib/authz/permissions.go index af55673d91f37..46bd0e87bf652 100644 --- a/lib/authz/permissions.go +++ b/lib/authz/permissions.go @@ -917,7 +917,7 @@ func roleSpecForProxy(clusterName string) types.RoleSpecV6 { types.NewRule(types.KindAuditQuery, services.RO()), types.NewRule(types.KindSecurityReport, services.RO()), types.NewRule(types.KindSecurityReportState, services.RO()), - types.NewRule(types.KindUserIntegrationTask, services.RO()), + types.NewRule(types.KindUserTask, services.RO()), // this rule allows cloud proxies to read // plugins of `openai` type, since Assist uses the OpenAI API and runs in Proxy. { @@ -1196,7 +1196,7 @@ func definitionForBuiltinRole(clusterName string, recConfig readonly.SessionReco types.NewRule(types.KindDiscoveryConfig, services.RO()), types.NewRule(types.KindIntegration, append(services.RO(), types.VerbUse)), types.NewRule(types.KindSemaphore, services.RW()), - types.NewRule(types.KindUserIntegrationTask, services.RW()), + types.NewRule(types.KindUserTask, services.RW()), }, // Discovery service should only access kubes/apps/dbs that originated from discovery. KubernetesLabels: types.Labels{types.OriginLabel: []string{types.OriginCloud}}, diff --git a/lib/cache/cache.go b/lib/cache/cache.go index 78393a9255836..4a9f6f673bd18 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -43,9 +43,9 @@ import ( dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/internalutils/stream" apitracing "github.com/gravitational/teleport/api/observability/tracing" "github.com/gravitational/teleport/api/types" @@ -186,7 +186,7 @@ func ForAuth(cfg Config) Config { {Kind: types.KindAccessGraphSettings}, {Kind: types.KindSPIFFEFederation}, {Kind: types.KindStaticHostUser}, - {Kind: types.KindUserIntegrationTask}, + {Kind: types.KindUserTask}, } cfg.QueueSize = defaults.AuthQueueSize // We don't want to enable partial health for auth cache because auth uses an event stream @@ -239,7 +239,7 @@ func ForProxy(cfg Config) Config { {Kind: types.KindSecurityReport}, {Kind: types.KindSecurityReportState}, {Kind: types.KindKubeWaitingContainer}, - {Kind: types.KindUserIntegrationTask}, + {Kind: types.KindUserTask}, } cfg.QueueSize = defaults.ProxyQueueSize return cfg @@ -405,7 +405,7 @@ func ForDiscovery(cfg Config) Config { {Kind: types.KindApp}, {Kind: types.KindDiscoveryConfig}, {Kind: types.KindIntegration}, - {Kind: types.KindUserIntegrationTask}, + {Kind: types.KindUserTask}, {Kind: types.KindProxy}, } cfg.QueueSize = defaults.DiscoveryQueueSize @@ -517,7 +517,7 @@ type Cache struct { userGroupsCache services.UserGroups oktaCache services.Okta integrationsCache services.Integrations - userIntegrationTasksCache services.UserIntegrationTasks + userTasksCache services.UserTasks discoveryConfigsCache services.DiscoveryConfigs headlessAuthenticationsCache services.HeadlessAuthenticationService secReportsCache services.SecReports @@ -692,8 +692,8 @@ type Config struct { DiscoveryConfigs services.DiscoveryConfigs // UserLoginStates is the user login state service. UserLoginStates services.UserLoginStates - // UserIntegrationTasks is the user integration tasks service. - UserIntegrationTasks services.UserIntegrationTasks + // UserTasks is the user tasks service. + UserTasks services.UserTasks // SecEvents is the security report service. SecReports services.SecReports // AccessLists is the access lists service. @@ -883,7 +883,7 @@ func New(config Config) (*Cache, error) { return nil, trace.Wrap(err) } - userIntegrationTasksCache, err := local.NewUserIntegrationTasksService(config.Backend) + userTasksCache, err := local.NewUserTasksService(config.Backend) if err != nil { cancel() return nil, trace.Wrap(err) @@ -991,7 +991,7 @@ func New(config Config) (*Cache, error) { userGroupsCache: userGroupsCache, oktaCache: oktaCache, integrationsCache: integrationsCache, - userIntegrationTasksCache: userIntegrationTasksCache, + userTasksCache: userTasksCache, discoveryConfigsCache: discoveryConfigsCache, headlessAuthenticationsCache: local.NewIdentityService(config.Backend), secReportsCache: secReportsCache, @@ -2879,30 +2879,30 @@ func (c *Cache) GetIntegration(ctx context.Context, name string) (types.Integrat return rg.reader.GetIntegration(ctx, name) } -// ListUserIntegrationTasks returns a list of UserIntegrationTask resources. -func (c *Cache) ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextKey string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) { - ctx, span := c.Tracer.Start(ctx, "cache/ListUserIntegrationTasks") +// ListUserTasks returns a list of UserTask resources. +func (c *Cache) ListUserTasks(ctx context.Context, pageSize int64, nextKey string) ([]*usertasksv1.UserTask, string, error) { + ctx, span := c.Tracer.Start(ctx, "cache/ListUserTasks") defer span.End() - rg, err := readCollectionCache(c, c.collections.userIntegrationTasks) + rg, err := readCollectionCache(c, c.collections.userTasks) if err != nil { return nil, "", trace.Wrap(err) } defer rg.Release() - return rg.reader.ListUserIntegrationTasks(ctx, pageSize, nextKey) + return rg.reader.ListUserTasks(ctx, pageSize, nextKey) } -// GetUserIntegrationTask returns the specified UserIntegrationTask resource. -func (c *Cache) GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) { - ctx, span := c.Tracer.Start(ctx, "cache/GetUserIntegrationTask") +// GetUserTask returns the specified UserTask resource. +func (c *Cache) GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) { + ctx, span := c.Tracer.Start(ctx, "cache/GetUserTask") defer span.End() - rg, err := readCollectionCache(c, c.collections.userIntegrationTasks) + rg, err := readCollectionCache(c, c.collections.userTasks) if err != nil { return nil, trace.Wrap(err) } defer rg.Release() - return rg.reader.GetUserIntegrationTask(ctx, name) + return rg.reader.GetUserTask(ctx, name) } // ListDiscoveryConfigs returns a paginated list of all DiscoveryConfig resources. diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go index 7bf8a40063603..f95c6862efe0c 100644 --- a/lib/cache/cache_test.go +++ b/lib/cache/cache_test.go @@ -50,8 +50,8 @@ import ( kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" labelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/label/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" "github.com/gravitational/teleport/api/types/clusterconfig" @@ -121,7 +121,7 @@ type testPack struct { userGroups services.UserGroups okta services.Okta integrations services.Integrations - userIntegrationTasks services.UserIntegrationTasks + userTasks services.UserTasks discoveryConfigs services.DiscoveryConfigs userLoginStates services.UserLoginStates secReports services.SecReports @@ -298,11 +298,11 @@ func newPackWithoutCache(dir string, opts ...packOption) (*testPack, error) { } p.integrations = igSvc - userIntegrationTasksSvc, err := local.NewUserIntegrationTasksService(p.backend) + userTasksSvc, err := local.NewUserTasksService(p.backend) if err != nil { return nil, trace.Wrap(err) } - p.userIntegrationTasks = userIntegrationTasksSvc + p.userTasks = userTasksSvc dcSvc, err := local.NewDiscoveryConfigService(p.backend) if err != nil { @@ -405,7 +405,7 @@ func newPack(dir string, setupConfig func(c Config) Config, opts ...packOption) UserGroups: p.userGroups, Okta: p.okta, Integrations: p.integrations, - UserIntegrationTasks: p.userIntegrationTasks, + UserTasks: p.userTasks, DiscoveryConfigs: p.discoveryConfigs, UserLoginStates: p.userLoginStates, SecReports: p.secReports, @@ -812,7 +812,7 @@ func TestCompletenessInit(t *testing.T) { UserGroups: p.userGroups, Okta: p.okta, Integrations: p.integrations, - UserIntegrationTasks: p.userIntegrationTasks, + UserTasks: p.userTasks, DiscoveryConfigs: p.discoveryConfigs, UserLoginStates: p.userLoginStates, SecReports: p.secReports, @@ -892,7 +892,7 @@ func TestCompletenessReset(t *testing.T) { UserGroups: p.userGroups, Okta: p.okta, Integrations: p.integrations, - UserIntegrationTasks: p.userIntegrationTasks, + UserTasks: p.userTasks, DiscoveryConfigs: p.discoveryConfigs, UserLoginStates: p.userLoginStates, SecReports: p.secReports, @@ -1098,7 +1098,7 @@ func TestListResources_NodesTTLVariant(t *testing.T) { UserGroups: p.userGroups, Okta: p.okta, Integrations: p.integrations, - UserIntegrationTasks: p.userIntegrationTasks, + UserTasks: p.userTasks, DiscoveryConfigs: p.discoveryConfigs, UserLoginStates: p.userLoginStates, SecReports: p.secReports, @@ -1189,7 +1189,7 @@ func initStrategy(t *testing.T) { UserGroups: p.userGroups, Okta: p.okta, Integrations: p.integrations, - UserIntegrationTasks: p.userIntegrationTasks, + UserTasks: p.userTasks, DiscoveryConfigs: p.discoveryConfigs, UserLoginStates: p.userLoginStates, SecReports: p.secReports, @@ -2275,38 +2275,38 @@ func TestIntegrations(t *testing.T) { }) } -// TestUserIntegrationTasks tests that CRUD operations on user notification resources are +// TestUserTasks tests that CRUD operations on user notification resources are // replicated from the backend to the cache. -func TestUserIntegrationTasks(t *testing.T) { +func TestUserTasks(t *testing.T) { t.Parallel() p := newTestPack(t, ForAuth) t.Cleanup(p.Close) - testResources153(t, p, testFuncs153[*userintegrationtasksv1.UserIntegrationTask]{ - newResource: func(name string) (*userintegrationtasksv1.UserIntegrationTask, error) { - return newUserIntegrationTasks(t, name), nil + testResources153(t, p, testFuncs153[*usertasksv1.UserTask]{ + newResource: func(name string) (*usertasksv1.UserTask, error) { + return newUserTasks(t, name), nil }, - create: func(ctx context.Context, item *userintegrationtasksv1.UserIntegrationTask) error { - _, err := p.userIntegrationTasks.CreateUserIntegrationTask(ctx, item) + create: func(ctx context.Context, item *usertasksv1.UserTask) error { + _, err := p.userTasks.CreateUserTask(ctx, item) return trace.Wrap(err) }, - list: func(ctx context.Context) ([]*userintegrationtasksv1.UserIntegrationTask, error) { - items, _, err := p.userIntegrationTasks.ListUserIntegrationTasks(ctx, 0, "") + list: func(ctx context.Context) ([]*usertasksv1.UserTask, error) { + items, _, err := p.userTasks.ListUserTasks(ctx, 0, "") return items, trace.Wrap(err) }, - cacheList: func(ctx context.Context) ([]*userintegrationtasksv1.UserIntegrationTask, error) { - items, _, err := p.userIntegrationTasks.ListUserIntegrationTasks(ctx, 0, "") + cacheList: func(ctx context.Context) ([]*usertasksv1.UserTask, error) { + items, _, err := p.userTasks.ListUserTasks(ctx, 0, "") return items, trace.Wrap(err) }, - deleteAll: p.userIntegrationTasks.DeleteAllUserIntegrationTasks, + deleteAll: p.userTasks.DeleteAllUserTasks, }) } -func newUserIntegrationTasks(t *testing.T, name string) *userintegrationtasksv1.UserIntegrationTask { +func newUserTasks(t *testing.T, name string) *usertasksv1.UserTask { t.Helper() - return &userintegrationtasksv1.UserIntegrationTask{ + return &usertasksv1.UserTask{ Metadata: &headerv1.Metadata{ Name: name, }, @@ -3348,7 +3348,7 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) { types.KindAccessGraphSettings: types.Resource153ToLegacy(newAccessGraphSettings(t)), types.KindSPIFFEFederation: types.Resource153ToLegacy(newSPIFFEFederation("test")), types.KindStaticHostUser: types.Resource153ToLegacy(newStaticHostUser(t, "test")), - types.KindUserIntegrationTask: types.Resource153ToLegacy(newUserIntegrationTasks(t, "test")), + types.KindUserTask: types.Resource153ToLegacy(newUserTasks(t, "test")), } for name, cfg := range cases { diff --git a/lib/cache/collections.go b/lib/cache/collections.go index 24da88f7d67f8..f72376d0e1599 100644 --- a/lib/cache/collections.go +++ b/lib/cache/collections.go @@ -35,9 +35,9 @@ import ( kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" userspb "github.com/gravitational/teleport/api/gen/proto/go/teleport/users/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" "github.com/gravitational/teleport/api/types/discoveryconfig" @@ -194,9 +194,9 @@ type crownjewelsGetter interface { GetCrownJewel(ctx context.Context, name string) (*crownjewelv1.CrownJewel, error) } -type userIntegrationTasksGetter interface { - ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextToken string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) - GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) +type userTasksGetter interface { + ListUserTasks(ctx context.Context, pageSize int64, nextToken string) ([]*usertasksv1.UserTask, string, error) + GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) } // cacheCollections is a registry of resource collections used by Cache. @@ -227,7 +227,7 @@ type cacheCollections struct { discoveryConfigs collectionReader[services.DiscoveryConfigsGetter] installers collectionReader[installerGetter] integrations collectionReader[services.IntegrationsGetter] - userIntegrationTasks collectionReader[userIntegrationTasksGetter] + userTasks collectionReader[userTasksGetter] crownJewels collectionReader[crownjewelsGetter] kubeClusters collectionReader[kubernetesClusterGetter] kubeWaitingContainers collectionReader[kubernetesWaitingContainerGetter] @@ -660,15 +660,15 @@ func setupCollections(c *Cache, watches []types.WatchKind) (*cacheCollections, e watch: watch, } collections.byKind[resourceKind] = collections.integrations - case types.KindUserIntegrationTask: - if c.UserIntegrationTasks == nil { - return nil, trace.BadParameter("missing parameter user integration tasks") + case types.KindUserTask: + if c.UserTasks == nil { + return nil, trace.BadParameter("missing parameter user tasks") } - collections.userIntegrationTasks = &genericCollection[*userintegrationtasksv1.UserIntegrationTask, userIntegrationTasksGetter, userIntegrationTasksExecutor]{ + collections.userTasks = &genericCollection[*usertasksv1.UserTask, userTasksGetter, userTasksExecutor]{ cache: c, watch: watch, } - collections.byKind[resourceKind] = collections.userIntegrationTasks + collections.byKind[resourceKind] = collections.userTasks case types.KindDiscoveryConfig: if c.DiscoveryConfigs == nil { return nil, trace.BadParameter("missing parameter DiscoveryConfigs") @@ -2447,15 +2447,15 @@ func (crownJewelsExecutor) getReader(cache *Cache, cacheOK bool) crownjewelsGett var _ executor[*crownjewelv1.CrownJewel, crownjewelsGetter] = crownJewelsExecutor{} -type userIntegrationTasksExecutor struct{} +type userTasksExecutor struct{} -func (userIntegrationTasksExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*userintegrationtasksv1.UserIntegrationTask, error) { - var resources []*userintegrationtasksv1.UserIntegrationTask +func (userTasksExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*usertasksv1.UserTask, error) { + var resources []*usertasksv1.UserTask var nextToken string for { - var page []*userintegrationtasksv1.UserIntegrationTask + var page []*usertasksv1.UserTask var err error - page, nextToken, err = cache.UserIntegrationTasks.ListUserIntegrationTasks(ctx, 0 /* page size */, nextToken) + page, nextToken, err = cache.UserTasks.ListUserTasks(ctx, 0 /* page size */, nextToken) if err != nil { return nil, trace.Wrap(err) } @@ -2468,29 +2468,29 @@ func (userIntegrationTasksExecutor) getAll(ctx context.Context, cache *Cache, lo return resources, nil } -func (userIntegrationTasksExecutor) upsert(ctx context.Context, cache *Cache, resource *userintegrationtasksv1.UserIntegrationTask) error { - _, err := cache.userIntegrationTasksCache.UpsertUserIntegrationTask(ctx, resource) +func (userTasksExecutor) upsert(ctx context.Context, cache *Cache, resource *usertasksv1.UserTask) error { + _, err := cache.userTasksCache.UpsertUserTask(ctx, resource) return trace.Wrap(err) } -func (userIntegrationTasksExecutor) deleteAll(ctx context.Context, cache *Cache) error { - return cache.userIntegrationTasksCache.DeleteAllUserIntegrationTasks(ctx) +func (userTasksExecutor) deleteAll(ctx context.Context, cache *Cache) error { + return cache.userTasksCache.DeleteAllUserTasks(ctx) } -func (userIntegrationTasksExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { - return cache.userIntegrationTasksCache.DeleteUserIntegrationTask(ctx, resource.GetName()) +func (userTasksExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { + return cache.userTasksCache.DeleteUserTask(ctx, resource.GetName()) } -func (userIntegrationTasksExecutor) isSingleton() bool { return false } +func (userTasksExecutor) isSingleton() bool { return false } -func (userIntegrationTasksExecutor) getReader(cache *Cache, cacheOK bool) userIntegrationTasksGetter { +func (userTasksExecutor) getReader(cache *Cache, cacheOK bool) userTasksGetter { if cacheOK { - return cache.userIntegrationTasksCache + return cache.userTasksCache } - return cache.Config.UserIntegrationTasks + return cache.Config.UserTasks } -var _ executor[*userintegrationtasksv1.UserIntegrationTask, userIntegrationTasksGetter] = userIntegrationTasksExecutor{} +var _ executor[*usertasksv1.UserTask, userTasksGetter] = userTasksExecutor{} //nolint:revive // Because we want this to be IdP. type samlIdPServiceProvidersExecutor struct{} diff --git a/lib/service/service.go b/lib/service/service.go index ed2e4935a185e..63336251bcb87 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -2525,7 +2525,7 @@ func (process *TeleportProcess) newAccessCacheForServices(cfg accesspoint.Config cfg.StaticHostUsers = services.StaticHostUser cfg.Trust = services.TrustInternal cfg.UserGroups = services.UserGroups - cfg.UserIntegrationTasks = services.UserIntegrationTasks + cfg.UserTasks = services.UserTasks cfg.UserLoginStates = services.UserLoginStates cfg.Users = services.Identity cfg.WebSession = services.Identity.WebSessions() @@ -2555,7 +2555,7 @@ func (process *TeleportProcess) newAccessCacheForClient(cfg accesspoint.Config, cfg.DynamicAccess = client cfg.Events = client cfg.Integrations = client - cfg.UserIntegrationTasks = client.UserIntegrationTasksServiceClient() + cfg.UserTasks = client.UserTasksServiceClient() cfg.KubeWaitingContainers = client cfg.Kubernetes = client cfg.Notifications = client @@ -2638,7 +2638,7 @@ type combinedDiscoveryClient struct { authclient.ClientI discoveryConfigClient eksClustersEnroller - services.UserIntegrationTasks + services.UserTasks } // newLocalCacheForDiscovery returns a new instance of access point for a discovery service. @@ -2647,7 +2647,7 @@ func (process *TeleportProcess) newLocalCacheForDiscovery(clt authclient.ClientI ClientI: clt, discoveryConfigClient: clt.DiscoveryConfigClient(), eksClustersEnroller: clt.IntegrationAWSOIDCClient(), - UserIntegrationTasks: clt.UserIntegrationTasksServiceClient(), + UserTasks: clt.UserTasksServiceClient(), } // if caching is disabled, return access point diff --git a/lib/services/local/events.go b/lib/services/local/events.go index c93a50c4ff877..e0ffb3954fc33 100644 --- a/lib/services/local/events.go +++ b/lib/services/local/events.go @@ -178,8 +178,8 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type parser = newOktaAssignmentParser() case types.KindIntegration: parser = newIntegrationParser() - case types.KindUserIntegrationTask: - parser = newUserIntegrationTaskParser() + case types.KindUserTask: + parser = newUserTaskParser() case types.KindDiscoveryConfig: parser = newDiscoveryConfigParser() case types.KindHeadlessAuthentication: @@ -1698,22 +1698,22 @@ func (p *integrationParser) parse(event backend.Event) (types.Resource, error) { } } -func newUserIntegrationTaskParser() *userIntegrationTaskParser { - return &userIntegrationTaskParser{ - baseParser: newBaseParser(backend.NewKey(userIntegrationTasksKey)), +func newUserTaskParser() *userTaskParser { + return &userTaskParser{ + baseParser: newBaseParser(backend.NewKey(userTasksKey)), } } -type userIntegrationTaskParser struct { +type userTaskParser struct { baseParser } -func (p *userIntegrationTaskParser) parse(event backend.Event) (types.Resource, error) { +func (p *userTaskParser) parse(event backend.Event) (types.Resource, error) { switch event.Type { case types.OpDelete: - return resourceHeader(event, types.KindUserIntegrationTask, types.V1, 0) + return resourceHeader(event, types.KindUserTask, types.V1, 0) case types.OpPut: - r, err := services.UnmarshalUserIntegrationTask(event.Item.Value, + r, err := services.UnmarshalUserTask(event.Item.Value, services.WithExpires(event.Item.Expires), services.WithRevision(event.Item.Revision), ) diff --git a/lib/services/local/user_integration_task.go b/lib/services/local/user_integration_task.go deleted file mode 100644 index 0e1b416ae590f..0000000000000 --- a/lib/services/local/user_integration_task.go +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Teleport - * Copyright (C) 2024 Gravitational, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package local - -import ( - "context" - - "github.com/gravitational/trace" - - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" - "github.com/gravitational/teleport/api/types" - "github.com/gravitational/teleport/lib/backend" - "github.com/gravitational/teleport/lib/services" - "github.com/gravitational/teleport/lib/services/local/generic" -) - -type UserIntegrationTasksService struct { - service *generic.ServiceWrapper[*userintegrationtasksv1.UserIntegrationTask] -} - -const userIntegrationTasksKey = "user_integration_tasks" - -// NewUserIntegrationTasksService creates a new UserIntegrationTasksService. -func NewUserIntegrationTasksService(backend backend.Backend) (*UserIntegrationTasksService, error) { - service, err := generic.NewServiceWrapper( - generic.ServiceWrapperConfig[*userintegrationtasksv1.UserIntegrationTask]{ - Backend: backend, - ResourceKind: types.KindAccessGraphSecretAuthorizedKey, - BackendPrefix: authorizedKeysPrefix, - MarshalFunc: services.MarshalProtoResource[*userintegrationtasksv1.UserIntegrationTask], - UnmarshalFunc: services.UnmarshalProtoResource[*userintegrationtasksv1.UserIntegrationTask], - }) - if err != nil { - return nil, trace.Wrap(err) - } - return &UserIntegrationTasksService{service: service}, nil -} - -func (s *UserIntegrationTasksService) ListUserIntegrationTasks(ctx context.Context, pagesize int64, lastKey string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) { - r, nextToken, err := s.service.ListResources(ctx, int(pagesize), lastKey) - return r, nextToken, trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) { - r, err := s.service.GetResource(ctx, name) - return r, trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) CreateUserIntegrationTask(ctx context.Context, userIntegrationTask *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) { - r, err := s.service.CreateResource(ctx, userIntegrationTask) - return r, trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) UpdateUserIntegrationTask(ctx context.Context, userIntegrationTask *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) { - r, err := s.service.ConditionalUpdateResource(ctx, userIntegrationTask) - return r, trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) UpsertUserIntegrationTask(ctx context.Context, userIntegrationTask *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) { - r, err := s.service.UpsertResource(ctx, userIntegrationTask) - return r, trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) DeleteUserIntegrationTask(ctx context.Context, name string) error { - err := s.service.DeleteResource(ctx, name) - return trace.Wrap(err) -} - -func (s *UserIntegrationTasksService) DeleteAllUserIntegrationTasks(ctx context.Context) error { - err := s.service.DeleteAllResources(ctx) - return trace.Wrap(err) -} diff --git a/lib/services/local/user_task.go b/lib/services/local/user_task.go new file mode 100644 index 0000000000000..d3ede57e64ae0 --- /dev/null +++ b/lib/services/local/user_task.go @@ -0,0 +1,88 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package local + +import ( + "context" + + "github.com/gravitational/trace" + + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/local/generic" +) + +type UserTasksService struct { + service *generic.ServiceWrapper[*usertasksv1.UserTask] +} + +const userTasksKey = "user_tasks" + +// NewUserTasksService creates a new UserTasksService. +func NewUserTasksService(backend backend.Backend) (*UserTasksService, error) { + service, err := generic.NewServiceWrapper( + generic.ServiceWrapperConfig[*usertasksv1.UserTask]{ + Backend: backend, + ResourceKind: types.KindAccessGraphSecretAuthorizedKey, + BackendPrefix: authorizedKeysPrefix, + MarshalFunc: services.MarshalProtoResource[*usertasksv1.UserTask], + UnmarshalFunc: services.UnmarshalProtoResource[*usertasksv1.UserTask], + }) + if err != nil { + return nil, trace.Wrap(err) + } + return &UserTasksService{service: service}, nil +} + +func (s *UserTasksService) ListUserTasks(ctx context.Context, pagesize int64, lastKey string) ([]*usertasksv1.UserTask, string, error) { + r, nextToken, err := s.service.ListResources(ctx, int(pagesize), lastKey) + return r, nextToken, trace.Wrap(err) +} + +func (s *UserTasksService) GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) { + r, err := s.service.GetResource(ctx, name) + return r, trace.Wrap(err) +} + +func (s *UserTasksService) CreateUserTask(ctx context.Context, userTask *usertasksv1.UserTask) (*usertasksv1.UserTask, error) { + r, err := s.service.CreateResource(ctx, userTask) + return r, trace.Wrap(err) +} + +func (s *UserTasksService) UpdateUserTask(ctx context.Context, userTask *usertasksv1.UserTask) (*usertasksv1.UserTask, error) { + r, err := s.service.ConditionalUpdateResource(ctx, userTask) + return r, trace.Wrap(err) +} + +func (s *UserTasksService) UpsertUserTask(ctx context.Context, userTask *usertasksv1.UserTask) (*usertasksv1.UserTask, error) { + r, err := s.service.UpsertResource(ctx, userTask) + return r, trace.Wrap(err) +} + +func (s *UserTasksService) DeleteUserTask(ctx context.Context, name string) error { + err := s.service.DeleteResource(ctx, name) + return trace.Wrap(err) +} + +func (s *UserTasksService) DeleteAllUserTasks(ctx context.Context) error { + err := s.service.DeleteAllResources(ctx) + return trace.Wrap(err) +} diff --git a/lib/services/local/user_integration_task_test.go b/lib/services/local/user_task_test.go similarity index 60% rename from lib/services/local/user_integration_task_test.go rename to lib/services/local/user_task_test.go index 58ccc476de807..e051c8d7456db 100644 --- a/lib/services/local/user_integration_task_test.go +++ b/lib/services/local/user_task_test.go @@ -32,72 +32,72 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" - "github.com/gravitational/teleport/api/types/userintegrationtasks" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" + "github.com/gravitational/teleport/api/types/usertasks" "github.com/gravitational/teleport/lib/backend/memory" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local" ) -func TestCreateUserIntegrationTask(t *testing.T) { +func TestCreateUserTask(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) + service := getUserTasksService(t) - obj, err := userintegrationtasks.NewUserIntegrationTask("obj", &userintegrationtasksv1.UserIntegrationTaskSpec{ + obj, err := usertasks.NewUserTask("obj", &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "ssm_agent_not_running", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{}, + DiscoverEc2: &usertasksv1.DiscoverEC2{}, }) require.NoError(t, err) // first attempt should succeed - objOut, err := service.CreateUserIntegrationTask(ctx, obj) + objOut, err := service.CreateUserTask(ctx, obj) require.NoError(t, err) require.Equal(t, obj, objOut) // second attempt should fail, object already exists - _, err = service.CreateUserIntegrationTask(ctx, obj) + _, err = service.CreateUserTask(ctx, obj) require.Error(t, err) } -func TestUpsertUserIntegrationTask(t *testing.T) { +func TestUpsertUserTask(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) - obj, err := userintegrationtasks.NewUserIntegrationTask("obj", &userintegrationtasksv1.UserIntegrationTaskSpec{ + service := getUserTasksService(t) + obj, err := usertasks.NewUserTask("obj", &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "ssm_agent_not_running", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{}, + DiscoverEc2: &usertasksv1.DiscoverEC2{}, }) require.NoError(t, err) // the first attempt should succeed - objOut, err := service.UpsertUserIntegrationTask(ctx, obj) + objOut, err := service.UpsertUserTask(ctx, obj) require.NoError(t, err) require.Equal(t, obj, objOut) // the second attempt should also succeed - objOut, err = service.UpsertUserIntegrationTask(ctx, obj) + objOut, err = service.UpsertUserTask(ctx, obj) require.NoError(t, err) require.Equal(t, obj, objOut) } -func TestGetUserIntegrationTask(t *testing.T) { +func TestGetUserTask(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) - prepopulateUserIntegrationTask(t, service, 1) + service := getUserTasksService(t) + prepopulateUserTask(t, service, 1) tests := []struct { name string key string wantErr bool - wantObj *userintegrationtasksv1.UserIntegrationTask + wantObj *usertasksv1.UserTask }{ { name: "object does not exist", @@ -107,16 +107,16 @@ func TestGetUserIntegrationTask(t *testing.T) { }, { name: "success", - key: getUserIntegrationTaskObject(t, 0).GetMetadata().GetName(), + key: getUserTaskObject(t, 0).GetMetadata().GetName(), wantErr: false, - wantObj: getUserIntegrationTaskObject(t, 0), + wantObj: getUserTaskObject(t, 0), }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Fetch a specific object. - obj, err := service.GetUserIntegrationTask(ctx, tt.key) + obj, err := service.GetUserTask(ctx, tt.key) if tt.wantErr { require.Error(t, err) } else { @@ -132,53 +132,53 @@ func TestGetUserIntegrationTask(t *testing.T) { } } -func TestUpdateUserIntegrationTask(t *testing.T) { +func TestUpdateUserTask(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) - prepopulateUserIntegrationTask(t, service, 1) + service := getUserTasksService(t) + prepopulateUserTask(t, service, 1) expiry := timestamppb.New(clock.Now().Add(30 * time.Minute)) // Fetch the object from the backend so the revision is populated. - obj, err := service.GetUserIntegrationTask(ctx, getUserIntegrationTaskObject(t, 0).GetMetadata().GetName()) + obj, err := service.GetUserTask(ctx, getUserTaskObject(t, 0).GetMetadata().GetName()) require.NoError(t, err) // update the expiry time obj.Metadata.Expires = expiry - objUpdated, err := service.UpdateUserIntegrationTask(ctx, obj) + objUpdated, err := service.UpdateUserTask(ctx, obj) require.NoError(t, err) require.Equal(t, expiry, objUpdated.Metadata.Expires) - objFresh, err := service.GetUserIntegrationTask(ctx, obj.Metadata.Name) + objFresh, err := service.GetUserTask(ctx, obj.Metadata.Name) require.NoError(t, err) require.Equal(t, expiry, objFresh.Metadata.Expires) } -func TestUpdateUserIntegrationTaskMissingRevision(t *testing.T) { +func TestUpdateUserTaskMissingRevision(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) - prepopulateUserIntegrationTask(t, service, 1) + service := getUserTasksService(t) + prepopulateUserTask(t, service, 1) expiry := timestamppb.New(clock.Now().Add(30 * time.Minute)) - obj := getUserIntegrationTaskObject(t, 0) + obj := getUserTaskObject(t, 0) obj.Metadata.Expires = expiry // Update should be rejected as the revision is missing. - _, err := service.UpdateUserIntegrationTask(ctx, obj) + _, err := service.UpdateUserTask(ctx, obj) require.Error(t, err) } -func TestDeleteUserIntegrationTask(t *testing.T) { +func TestDeleteUserTask(t *testing.T) { t.Parallel() ctx := context.Background() - service := getUserIntegrationTasksService(t) - prepopulateUserIntegrationTask(t, service, 1) + service := getUserTasksService(t) + prepopulateUserTask(t, service, 1) tests := []struct { name string @@ -192,7 +192,7 @@ func TestDeleteUserIntegrationTask(t *testing.T) { }, { name: "success", - key: getUserIntegrationTaskObject(t, 0).GetMetadata().GetName(), + key: getUserTaskObject(t, 0).GetMetadata().GetName(), wantErr: false, }, } @@ -200,7 +200,7 @@ func TestDeleteUserIntegrationTask(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Fetch a specific object. - err := service.DeleteUserIntegrationTask(ctx, tt.key) + err := service.DeleteUserTask(ctx, tt.key) if tt.wantErr { require.Error(t, err) } else { @@ -210,7 +210,7 @@ func TestDeleteUserIntegrationTask(t *testing.T) { } } -func TestListUserIntegrationTask(t *testing.T) { +func TestListUserTask(t *testing.T) { t.Parallel() ctx := context.Background() @@ -218,12 +218,12 @@ func TestListUserIntegrationTask(t *testing.T) { counts := []int{0, 1, 5, 10} for _, count := range counts { t.Run(fmt.Sprintf("count=%v", count), func(t *testing.T) { - service := getUserIntegrationTasksService(t) - prepopulateUserIntegrationTask(t, service, count) + service := getUserTasksService(t) + prepopulateUserTask(t, service, count) t.Run("one page", func(t *testing.T) { // Fetch all objects. - elements, nextToken, err := service.ListUserIntegrationTasks(ctx, 200, "") + elements, nextToken, err := service.ListUserTasks(ctx, 200, "") require.NoError(t, err) require.Empty(t, nextToken) require.Len(t, elements, count) @@ -233,16 +233,16 @@ func TestListUserIntegrationTask(t *testing.T) { protocmp.IgnoreFields(&headerv1.Metadata{}, "revision"), protocmp.Transform(), } - require.Equal(t, "", cmp.Diff(getUserIntegrationTaskObject(t, i), elements[i], cmpOpts...)) + require.Equal(t, "", cmp.Diff(getUserTaskObject(t, i), elements[i], cmpOpts...)) } }) t.Run("paginated", func(t *testing.T) { // Fetch a paginated list of objects - elements := make([]*userintegrationtasksv1.UserIntegrationTask, 0) + elements := make([]*usertasksv1.UserTask, 0) nextToken := "" for { - out, token, err := service.ListUserIntegrationTasks(ctx, 2, nextToken) + out, token, err := service.ListUserTasks(ctx, 2, nextToken) require.NoError(t, err) nextToken = token @@ -257,32 +257,32 @@ func TestListUserIntegrationTask(t *testing.T) { protocmp.IgnoreFields(&headerv1.Metadata{}, "revision"), protocmp.Transform(), } - require.Equal(t, "", cmp.Diff(getUserIntegrationTaskObject(t, i), elements[i], cmpOpts...)) + require.Equal(t, "", cmp.Diff(getUserTaskObject(t, i), elements[i], cmpOpts...)) } }) }) } } -func getUserIntegrationTasksService(t *testing.T) services.UserIntegrationTasks { +func getUserTasksService(t *testing.T) services.UserTasks { backend, err := memory.New(memory.Config{ Context: context.Background(), Clock: clockwork.NewFakeClock(), }) require.NoError(t, err) - service, err := local.NewUserIntegrationTasksService(backend) + service, err := local.NewUserTasksService(backend) require.NoError(t, err) return service } -func getUserIntegrationTaskObject(t *testing.T, index int) *userintegrationtasksv1.UserIntegrationTask { +func getUserTaskObject(t *testing.T, index int) *usertasksv1.UserTask { name := fmt.Sprintf("obj%v", index) - obj, err := userintegrationtasks.NewUserIntegrationTask(name, &userintegrationtasksv1.UserIntegrationTaskSpec{ + obj, err := usertasks.NewUserTask(name, &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "ssm_agent_not_running", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{}, + DiscoverEc2: &usertasksv1.DiscoverEC2{}, }) require.NoError(t, err) require.NoError(t, err) @@ -290,9 +290,9 @@ func getUserIntegrationTaskObject(t *testing.T, index int) *userintegrationtasks return obj } -func prepopulateUserIntegrationTask(t *testing.T, service services.UserIntegrationTasks, count int) { +func prepopulateUserTask(t *testing.T, service services.UserTasks, count int) { for i := 0; i < count; i++ { - _, err := service.CreateUserIntegrationTask(context.Background(), getUserIntegrationTaskObject(t, i)) + _, err := service.CreateUserTask(context.Background(), getUserTaskObject(t, i)) require.NoError(t, err) } } diff --git a/lib/services/presets.go b/lib/services/presets.go index d05fa2eec7076..75e7adfe6e0c9 100644 --- a/lib/services/presets.go +++ b/lib/services/presets.go @@ -181,7 +181,7 @@ func NewPresetEditorRole() types.Role { types.NewRule(types.KindSPIFFEFederation, RW()), types.NewRule(types.KindNotification, RW()), types.NewRule(types.KindStaticHostUser, RW()), - types.NewRule(types.KindUserIntegrationTask, RW()), + types.NewRule(types.KindUserTask, RW()), }, }, }, diff --git a/lib/services/resource.go b/lib/services/resource.go index 6c9656d6af39d..a73cecf9920fd 100644 --- a/lib/services/resource.go +++ b/lib/services/resource.go @@ -245,8 +245,8 @@ func ParseShortcut(in string) (string, error) { return types.KindSPIFFEFederation, nil case types.KindStaticHostUser, types.KindStaticHostUser + "s", "host_user", "host_users": return types.KindStaticHostUser, nil - case types.KindUserIntegrationTask, types.KindUserIntegrationTask + "s": - return types.KindUserIntegrationTask, nil + case types.KindUserTask, types.KindUserTask + "s": + return types.KindUserTask, nil } return "", trace.BadParameter("unsupported resource: %q - resources should be expressed as 'type/name', for example 'connector/github'", in) } diff --git a/lib/services/user_integration_task.go b/lib/services/user_integration_task.go deleted file mode 100644 index bafc8a4274bca..0000000000000 --- a/lib/services/user_integration_task.go +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Teleport - * Copyright (C) 2024 Gravitational, Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -package services - -import ( - "context" - - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" -) - -// UserIntegrationTasks is the interface for managing user integration tasks resources. -type UserIntegrationTasks interface { - // CreateUserIntegrationTask creates a new user integration tasks resource. - CreateUserIntegrationTask(context.Context, *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) - // UpsertUserIntegrationTask creates or updates the user integration tasks resource. - UpsertUserIntegrationTask(context.Context, *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) - // GetUserIntegrationTask returns the user integration tasks resource by name. - GetUserIntegrationTask(ctx context.Context, name string) (*userintegrationtasksv1.UserIntegrationTask, error) - // ListUserIntegrationTasks returns the user integration tasks resources. - ListUserIntegrationTasks(ctx context.Context, pageSize int64, nextToken string) ([]*userintegrationtasksv1.UserIntegrationTask, string, error) - // UpdateUserIntegrationTask updates the user integration tasks resource. - UpdateUserIntegrationTask(context.Context, *userintegrationtasksv1.UserIntegrationTask) (*userintegrationtasksv1.UserIntegrationTask, error) - // DeleteUserIntegrationTask deletes the user integration tasks resource by name. - DeleteUserIntegrationTask(context.Context, string) error - // DeleteAllUserIntegrationTasks deletes all User Integration Tasks. - DeleteAllUserIntegrationTasks(context.Context) error -} - -// MarshalUserIntegrationTask marshals the UserIntegrationTask object into a JSON byte array. -func MarshalUserIntegrationTask(object *userintegrationtasksv1.UserIntegrationTask, opts ...MarshalOption) ([]byte, error) { - return MarshalProtoResource(object, opts...) -} - -// UnmarshalUserIntegrationTask unmarshals the UserIntegrationTask object from a JSON byte array. -func UnmarshalUserIntegrationTask(data []byte, opts ...MarshalOption) (*userintegrationtasksv1.UserIntegrationTask, error) { - return UnmarshalProtoResource[*userintegrationtasksv1.UserIntegrationTask](data, opts...) -} diff --git a/lib/services/user_task.go b/lib/services/user_task.go new file mode 100644 index 0000000000000..64f3ae2d54c6c --- /dev/null +++ b/lib/services/user_task.go @@ -0,0 +1,53 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package services + +import ( + "context" + + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" +) + +// UserTasks is the interface for managing user tasks resources. +type UserTasks interface { + // CreateUserTask creates a new user tasks resource. + CreateUserTask(context.Context, *usertasksv1.UserTask) (*usertasksv1.UserTask, error) + // UpsertUserTask creates or updates the user tasks resource. + UpsertUserTask(context.Context, *usertasksv1.UserTask) (*usertasksv1.UserTask, error) + // GetUserTask returns the user tasks resource by name. + GetUserTask(ctx context.Context, name string) (*usertasksv1.UserTask, error) + // ListUserTasks returns the user tasks resources. + ListUserTasks(ctx context.Context, pageSize int64, nextToken string) ([]*usertasksv1.UserTask, string, error) + // UpdateUserTask updates the user tasks resource. + UpdateUserTask(context.Context, *usertasksv1.UserTask) (*usertasksv1.UserTask, error) + // DeleteUserTask deletes the user tasks resource by name. + DeleteUserTask(context.Context, string) error + // DeleteAllUserTasks deletes all user tasks. + DeleteAllUserTasks(context.Context) error +} + +// MarshalUserTask marshals the UserTask object into a JSON byte array. +func MarshalUserTask(object *usertasksv1.UserTask, opts ...MarshalOption) ([]byte, error) { + return MarshalProtoResource(object, opts...) +} + +// UnmarshalUserTask unmarshals the UserTask object from a JSON byte array. +func UnmarshalUserTask(data []byte, opts ...MarshalOption) (*usertasksv1.UserTask, error) { + return UnmarshalProtoResource[*usertasksv1.UserTask](data, opts...) +} diff --git a/lib/services/user_integration_task_test.go b/lib/services/user_task_test.go similarity index 68% rename from lib/services/user_integration_task_test.go rename to lib/services/user_task_test.go index c52d7edf8fdcf..46be4b7c209a6 100644 --- a/lib/services/user_integration_task_test.go +++ b/lib/services/user_task_test.go @@ -28,28 +28,28 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/lib/utils" ) -func TestMarshalUserIntegrationTaskRoundTrip(t *testing.T) { +func TestMarshalUserTaskRoundTrip(t *testing.T) { t.Parallel() - obj := &userintegrationtasksv1.UserIntegrationTask{ + obj := &usertasksv1.UserTask{ Version: "v1", - Kind: "user_integration_task", + Kind: "user_task", Metadata: &headerv1.Metadata{ - Name: "example-user-integration-task", + Name: "example-user-task", Labels: map[string]string{ "env": "example", }, }, - Spec: &userintegrationtasksv1.UserIntegrationTaskSpec{ + Spec: &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "SSM_AGENT_MISSING", State: "OPEN", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{Instances: map[string]*userintegrationtasksv1.DiscoverEC2Instance{ + DiscoverEc2: &usertasksv1.DiscoverEC2{Instances: map[string]*usertasksv1.DiscoverEC2Instance{ "i-1234567890": { Name: "instance-name", Region: "us-east-1", @@ -62,24 +62,24 @@ func TestMarshalUserIntegrationTaskRoundTrip(t *testing.T) { }, } - out, err := MarshalUserIntegrationTask(obj) + out, err := MarshalUserTask(obj) require.NoError(t, err) - newObj, err := UnmarshalUserIntegrationTask(out) + newObj, err := UnmarshalUserTask(out) require.NoError(t, err) require.True(t, proto.Equal(obj, newObj), "messages are not equal") } -func TestUnmarshalUserIntegrationTask(t *testing.T) { +func TestUnmarshalUserTask(t *testing.T) { t.Parallel() syncTime := timestamppb.Now() syncTimeString := syncTime.AsTime().Format(time.RFC3339Nano) - correctUserIntegrationTaskYAML := fmt.Sprintf(` + correctUserTaskYAML := fmt.Sprintf(` version: v1 -kind: user_integration_task +kind: user_task metadata: - name: example-user-integration-task + name: example-user-task labels: env: example spec: @@ -98,24 +98,24 @@ spec: sync_time: "%s" `, syncTimeString) - data, err := utils.ToJSON([]byte(correctUserIntegrationTaskYAML)) + data, err := utils.ToJSON([]byte(correctUserTaskYAML)) require.NoError(t, err) - expected := &userintegrationtasksv1.UserIntegrationTask{ + expected := &usertasksv1.UserTask{ Version: "v1", - Kind: "user_integration_task", + Kind: "user_task", Metadata: &headerv1.Metadata{ - Name: "example-user-integration-task", + Name: "example-user-task", Labels: map[string]string{ "env": "example", }, }, - Spec: &userintegrationtasksv1.UserIntegrationTaskSpec{ + Spec: &usertasksv1.UserTaskSpec{ Integration: "my-integration", TaskType: "discover-ec2", IssueType: "SSM_AGENT_MISSING", State: "OPEN", - DiscoverEc2: &userintegrationtasksv1.DiscoverEC2{Instances: map[string]*userintegrationtasksv1.DiscoverEC2Instance{ + DiscoverEc2: &usertasksv1.DiscoverEC2{Instances: map[string]*usertasksv1.DiscoverEC2Instance{ "i-1234567890": { Name: "instance-name", Region: "us-east-1", @@ -128,7 +128,7 @@ spec: }, } - obj, err := UnmarshalUserIntegrationTask(data) + obj, err := UnmarshalUserTask(data) require.NoError(t, err) - require.True(t, proto.Equal(expected, obj), "UserIntegrationTask objects are not equal") + require.True(t, proto.Equal(expected, obj), "UserTask objects are not equal") } diff --git a/lib/services/useracl.go b/lib/services/useracl.go index ee9e2d495dea1..6df6e63316e67 100644 --- a/lib/services/useracl.go +++ b/lib/services/useracl.go @@ -84,8 +84,8 @@ type UserACL struct { Plugins ResourceAccess `json:"plugins"` // Integrations defines whether the user has access to manage integrations. Integrations ResourceAccess `json:"integrations"` - // UserIntegrationTasks defines whether the user has access to manage UserIntegrationTasks. - UserIntegrationTasks ResourceAccess `json:"userIntegrationTasks"` + // UserTasks defines whether the user has access to manage UserTasks. + UserTasks ResourceAccess `json:"userTasks"` // DeviceTrust defines access to device trust. DeviceTrust ResourceAccess `json:"deviceTrust"` // Locks defines access to locking resources. @@ -200,7 +200,7 @@ func NewUserACL(user types.User, userRoles RoleSet, features proto.Features, des bots := newAccess(userRoles, ctx, types.KindBot) botInstances := newAccess(userRoles, ctx, types.KindBotInstance) crownJewelAccess := newAccess(userRoles, ctx, types.KindCrownJewel) - userIntegrationTasksAccess := newAccess(userRoles, ctx, types.KindUserIntegrationTask) + userTasksAccess := newAccess(userRoles, ctx, types.KindUserTask) var auditQuery ResourceAccess var securityReports ResourceAccess @@ -234,7 +234,7 @@ func NewUserACL(user types.User, userRoles RoleSet, features proto.Features, des License: license, Plugins: pluginsAccess, Integrations: integrationsAccess, - UserIntegrationTasks: userIntegrationTasksAccess, + UserTasks: userTasksAccess, DiscoveryConfig: discoveryConfigsAccess, DeviceTrust: deviceTrust, Locks: lockAccess, diff --git a/tool/tctl/common/collection.go b/tool/tctl/common/collection.go index 36b6ab8e61018..a534c9fd37a24 100644 --- a/tool/tctl/common/collection.go +++ b/tool/tctl/common/collection.go @@ -37,8 +37,8 @@ import ( devicepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/devicetrust/v1" loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1" machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/gen/proto/go/teleport/vnet/v1" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/types/accesslist" @@ -1796,11 +1796,11 @@ func printSortedStringSlice(s []string) string { return strings.Join(s, ",") } -type userIntegrationTaskCollection struct { - items []*userintegrationtasksv1.UserIntegrationTask +type userTaskCollection struct { + items []*usertasksv1.UserTask } -func (c *userIntegrationTaskCollection) resources() []types.Resource { +func (c *userTaskCollection) resources() []types.Resource { r := make([]types.Resource, 0, len(c.items)) for _, resource := range c.items { r = append(r, types.Resource153ToLegacy(resource)) @@ -1808,21 +1808,17 @@ func (c *userIntegrationTaskCollection) resources() []types.Resource { return r } -// writeText formats the user integration tasks into a table and writes them into w. +// writeText formats the user tasks into a table and writes them into w. // If verbose is disabled, labels column can be truncated to fit into the console. -func (c *userIntegrationTaskCollection) writeText(w io.Writer, verbose bool) error { +func (c *userTaskCollection) writeText(w io.Writer, verbose bool) error { var rows [][]string for _, item := range c.items { labels := common.FormatLabels(item.GetMetadata().GetLabels(), verbose) - rows = append(rows, []string{item.Metadata.GetName(), labels, item.Spec.GetIntegration(), item.Spec.TaskType, item.Spec.IssueType}) + rows = append(rows, []string{item.Metadata.GetName(), labels, item.Spec.TaskType, item.Spec.IssueType, item.Spec.GetIntegration()}) } - headers := []string{"Name", "Labels", "Integration", "TaskType", "IssueType"} + headers := []string{"Name", "Labels", "TaskType", "IssueType", "Integration"} var t asciitable.Table - if verbose { - t = asciitable.MakeTable(headers, rows...) - } else { - t = asciitable.MakeTableWithTruncatedColumn(headers, rows, "Node Expression") - } + t = asciitable.MakeTable(headers, rows...) // stable sort by name. t.SortRowsBy([]int{0}, true) diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go index 986aac7f2ec81..b1bd0125e03c7 100644 --- a/tool/tctl/common/resource_command.go +++ b/tool/tctl/common/resource_command.go @@ -50,8 +50,8 @@ import ( loginrulepb "github.com/gravitational/teleport/api/gen/proto/go/teleport/loginrule/v1" machineidv1pb "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" pluginsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/plugins/v1" - userintegrationtasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/userintegrationtasks/v1" userprovisioningpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/userprovisioning/v2" + usertasksv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/usertasks/v1" "github.com/gravitational/teleport/api/gen/proto/go/teleport/vnet/v1" "github.com/gravitational/teleport/api/internalutils/stream" "github.com/gravitational/teleport/api/mfa" @@ -169,7 +169,7 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *servicec types.KindPlugin: rc.createPlugin, types.KindSPIFFEFederation: rc.createSPIFFEFederation, types.KindStaticHostUser: rc.createStaticHostUser, - types.KindUserIntegrationTask: rc.createUserIntegrationTask, + types.KindUserTask: rc.createUserTask, } rc.UpdateHandlers = map[ResourceKind]ResourceCreateHandler{ types.KindUser: rc.updateUser, @@ -186,7 +186,7 @@ func (rc *ResourceCommand) Initialize(app *kingpin.Application, config *servicec types.KindAccessGraphSettings: rc.updateAccessGraphSettings, types.KindPlugin: rc.updatePlugin, types.KindStaticHostUser: rc.updateStaticHostUser, - types.KindUserIntegrationTask: rc.updateUserIntegrationTask, + types.KindUserTask: rc.updateUserTask, } rc.config = config @@ -966,23 +966,23 @@ func (rc *ResourceCommand) createCrownJewel(ctx context.Context, client *authcli return nil } -func (rc *ResourceCommand) createUserIntegrationTask(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error { - resource, err := services.UnmarshalUserIntegrationTask(raw.Raw) +func (rc *ResourceCommand) createUserTask(ctx context.Context, client *authclient.Client, raw services.UnknownResource) error { + resource, err := services.UnmarshalUserTask(raw.Raw) if err != nil { return trace.Wrap(err) } - c := client.UserIntegrationTasksServiceClient() + c := client.UserTasksServiceClient() if rc.force { - if _, err := c.UpsertUserIntegrationTask(ctx, resource); err != nil { + if _, err := c.UpsertUserTask(ctx, resource); err != nil { return trace.Wrap(err) } - fmt.Printf("user integration task %q has been updated\n", resource.GetMetadata().GetName()) + fmt.Printf("user task %q has been updated\n", resource.GetMetadata().GetName()) } else { - if _, err := c.CreateUserIntegrationTask(ctx, resource); err != nil { + if _, err := c.CreateUserTask(ctx, resource); err != nil { return trace.Wrap(err) } - fmt.Printf("user integration task %q has been created\n", resource.GetMetadata().GetName()) + fmt.Printf("user task %q has been created\n", resource.GetMetadata().GetName()) } return nil @@ -1017,15 +1017,15 @@ func (rc *ResourceCommand) updateCrownJewel(ctx context.Context, client *authcli return nil } -func (rc *ResourceCommand) updateUserIntegrationTask(ctx context.Context, client *authclient.Client, resource services.UnknownResource) error { - in, err := services.UnmarshalUserIntegrationTask(resource.Raw) +func (rc *ResourceCommand) updateUserTask(ctx context.Context, client *authclient.Client, resource services.UnknownResource) error { + in, err := services.UnmarshalUserTask(resource.Raw) if err != nil { return trace.Wrap(err) } - if _, err := client.UserIntegrationTasksServiceClient().UpdateUserIntegrationTask(ctx, in); err != nil { + if _, err := client.UserTasksServiceClient().UpdateUserTask(ctx, in); err != nil { return trace.Wrap(err) } - fmt.Printf("user integration task %q has been updated\n", in.GetMetadata().GetName()) + fmt.Printf("user task %q has been updated\n", in.GetMetadata().GetName()) return nil } @@ -1796,11 +1796,11 @@ func (rc *ResourceCommand) Delete(ctx context.Context, client *authclient.Client } fmt.Printf("Integration %q removed\n", rc.ref.Name) - case types.KindUserIntegrationTask: - if err := client.UserIntegrationTasksServiceClient().DeleteUserIntegrationTask(ctx, rc.ref.Name); err != nil { + case types.KindUserTask: + if err := client.UserTasksServiceClient().DeleteUserTask(ctx, rc.ref.Name); err != nil { return trace.Wrap(err) } - fmt.Printf("user integration task %q has been deleted\n", rc.ref.Name) + fmt.Printf("user task %q has been deleted\n", rc.ref.Name) case types.KindDiscoveryConfig: remote := client.DiscoveryConfigClient() @@ -2818,20 +2818,20 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient } } return &integrationCollection{integrations: resources}, nil - case types.KindUserIntegrationTask: - userIntegrationTasksClient := client.UserIntegrationTasksClient() + case types.KindUserTask: + userTasksClient := client.UserTasksClient() if rc.ref.Name != "" { - uit, err := userIntegrationTasksClient.GetUserIntegrationTask(ctx, rc.ref.Name) + uit, err := userTasksClient.GetUserTask(ctx, rc.ref.Name) if err != nil { return nil, trace.Wrap(err) } - return &userIntegrationTaskCollection{items: []*userintegrationtasksv1.UserIntegrationTask{uit}}, nil + return &userTaskCollection{items: []*usertasksv1.UserTask{uit}}, nil } - var tasks []*userintegrationtasksv1.UserIntegrationTask + var tasks []*usertasksv1.UserTask nextToken := "" for { - resp, token, err := userIntegrationTasksClient.ListUserIntegrationTasks(ctx, 0 /* default size */, nextToken) + resp, token, err := userTasksClient.ListUserTasks(ctx, 0 /* default size */, nextToken) if err != nil { return nil, trace.Wrap(err) } @@ -2842,7 +2842,7 @@ func (rc *ResourceCommand) getCollection(ctx context.Context, client *authclient } nextToken = token } - return &userIntegrationTaskCollection{items: tasks}, nil + return &userTaskCollection{items: tasks}, nil case types.KindDiscoveryConfig: remote := client.DiscoveryConfigClient() if rc.ref.Name != "" {