diff --git a/api/workers/option.gen.go b/api/workers/option.gen.go index 29ba168a3..ca1fb0aa4 100644 --- a/api/workers/option.gen.go +++ b/api/workers/option.gen.go @@ -87,18 +87,6 @@ func WithRecursive(recurse bool) Option { } } -func WithAddress(inAddress string) Option { - return func(o *options) { - o.postMap["address"] = inAddress - } -} - -func DefaultAddress() Option { - return func(o *options) { - o.postMap["address"] = nil - } -} - func WithDescription(inDescription string) Option { return func(o *options) { o.postMap["description"] = inDescription diff --git a/api/workers/worker.gen.go b/api/workers/worker.gen.go index f108a3191..1a021c000 100644 --- a/api/workers/worker.gen.go +++ b/api/workers/worker.gen.go @@ -13,23 +13,22 @@ import ( ) type Worker struct { - Id string `json:"id,omitempty"` - ScopeId string `json:"scope_id,omitempty"` - Scope *scopes.ScopeInfo `json:"scope,omitempty"` - Name string `json:"name,omitempty"` - Description string `json:"description,omitempty"` - CreatedTime time.Time `json:"created_time,omitempty"` - UpdatedTime time.Time `json:"updated_time,omitempty"` - Version uint32 `json:"version,omitempty"` - Address string `json:"address,omitempty"` - CanonicalAddress string `json:"canonical_address,omitempty"` - Tags map[string][]string `json:"tags,omitempty"` - CanonicalTags map[string][]string `json:"canonical_tags,omitempty"` - LastStatusTime time.Time `json:"last_status_time,omitempty"` - WorkerProvidedConfiguration *WorkerProvidedConfiguration `json:"worker_provided_configuration,omitempty"` - WorkerGeneratedAuthToken string `json:"worker_generated_auth_token,omitempty"` - ActiveConnectionCount uint32 `json:"active_connection_count,omitempty"` - AuthorizedActions []string `json:"authorized_actions,omitempty"` + Id string `json:"id,omitempty"` + ScopeId string `json:"scope_id,omitempty"` + Scope *scopes.ScopeInfo `json:"scope,omitempty"` + Name string `json:"name,omitempty"` + Description string `json:"description,omitempty"` + CreatedTime time.Time `json:"created_time,omitempty"` + UpdatedTime time.Time `json:"updated_time,omitempty"` + Version uint32 `json:"version,omitempty"` + Address string `json:"address,omitempty"` + CanonicalTags map[string][]string `json:"canonical_tags,omitempty"` + ConfigTags map[string][]string `json:"config_tags,omitempty"` + LastStatusTime time.Time `json:"last_status_time,omitempty"` + WorkerGeneratedAuthToken string `json:"worker_generated_auth_token,omitempty"` + ActiveConnectionCount uint32 `json:"active_connection_count,omitempty"` + Type string `json:"type,omitempty"` + AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response } diff --git a/api/workers/worker_provided_configuration.gen.go b/api/workers/worker_provided_configuration.gen.go deleted file mode 100644 index 4a276211a..000000000 --- a/api/workers/worker_provided_configuration.gen.go +++ /dev/null @@ -1,8 +0,0 @@ -// Code generated by "make api"; DO NOT EDIT. -package workers - -type WorkerProvidedConfiguration struct { - Address string `json:"address,omitempty"` - Name string `json:"name,omitempty"` - Tags map[string][]string `json:"tags,omitempty"` -} diff --git a/globals/fields.go b/globals/fields.go index 4dd361862..f8577afdc 100644 --- a/globals/fields.go +++ b/globals/fields.go @@ -78,6 +78,7 @@ const ( CanonicalAddressField = "canonical_address" TagsField = "tags" CanonicalTagsField = "canonical_tags" + ConfigTagsField = "config_tags" ConfigurationField = "configuration" WorkerGeneratedAuthTokenField = "worker_generated_auth_token" WorkerProvidedConfigurationField = "worker_provided_configuration" diff --git a/internal/api/genapi/input.go b/internal/api/genapi/input.go index bd2179a61..f2a0286fe 100644 --- a/internal/api/genapi/input.go +++ b/internal/api/genapi/input.go @@ -746,10 +746,6 @@ var inputStructs = []*structInfo{ fieldFilter: []string{"private_key"}, recursiveListing: true, }, - { - inProto: &workers.WorkerProvidedConfiguration{}, - outFile: "workers/worker_provided_configuration.gen.go", - }, { inProto: &workers.Worker{}, outFile: "workers/worker.gen.go", diff --git a/internal/api/genapi/parse.go b/internal/api/genapi/parse.go index 564b48c2e..9062e3aa8 100644 --- a/internal/api/genapi/parse.go +++ b/internal/api/genapi/parse.go @@ -70,7 +70,7 @@ func parsePBs() { name = fmt.Sprintf("%s.%s", pkg, name) } switch name { - case "v1.AuthorizedCollectionActionsEntry", "v1.CanonicalTagsEntry", "v1.TagsEntry": + case "v1.AuthorizedCollectionActionsEntry", "v1.CanonicalTagsEntry", "v1.TagsEntry", "v1.ConfigTagsEntry": fi.FieldType = "map[string][]string" default: fi.FieldType = sliceText + ptr + name diff --git a/internal/cmd/commands/dev/dev.go b/internal/cmd/commands/dev/dev.go index 8081efa49..fe8b9b8bc 100644 --- a/internal/cmd/commands/dev/dev.go +++ b/internal/cmd/commands/dev/dev.go @@ -587,6 +587,8 @@ func (c *Command) Run(args []string) int { c.UI.Error("Worker Auth KMS not found after parsing KMS blocks") return base.CommandUserError } + c.Config.Worker.Name = "" + c.Config.Worker.Description = "" c.InfoKeys = append(c.InfoKeys, "[Worker-Auth] AEAD Key Bytes") c.Info["[Worker-Auth] AEAD Key Bytes"] = c.Config.DevWorkerAuthKey } diff --git a/internal/cmd/commands/server/server.go b/internal/cmd/commands/server/server.go index 9a7a07897..cf819ae9a 100644 --- a/internal/cmd/commands/server/server.go +++ b/internal/cmd/commands/server/server.go @@ -197,6 +197,10 @@ func (c *Command) Run(args []string) int { c.UI.Error("No worker auth KMS specified and no worker auth storage path specified.") return base.CommandUserError } + if c.Config.Worker.Name != "" || c.Config.Worker.Description != "" { + c.UI.Error("Worker config cannot contain name or description when using PKI-based worker authentication; it must be set via the API.") + return base.CommandUserError + } default: if c.Config.Worker.Name == "" { c.UI.Error("Worker is using KMS auth but has no name set. It must be the unique name of this instance.") diff --git a/internal/cmd/commands/server/worker_tags_reload_test.go b/internal/cmd/commands/server/worker_tags_reload_test.go index 74bc29f01..0fbd9a13f 100644 --- a/internal/cmd/commands/server/worker_tags_reload_test.go +++ b/internal/cmd/commands/server/worker_tags_reload_test.go @@ -106,7 +106,7 @@ func TestServer_ReloadWorkerTags(t *testing.T) { t.Helper() serversRepo, err := testController.Controller().ServersRepoFn() require.NoError(err) - w, err := serversRepo.LookupWorkerByWorkerReportedName(testController.Context(), name) + w, err := serversRepo.LookupWorkerByName(testController.Context(), name) require.NoError(err) require.NotNil(w) v, ok := w.CanonicalTags()[key] diff --git a/internal/cmd/commands/workerscmd/funcs.go b/internal/cmd/commands/workerscmd/funcs.go index 6103be64d..380a83f86 100644 --- a/internal/cmd/commands/workerscmd/funcs.go +++ b/internal/cmd/commands/workerscmd/funcs.go @@ -59,6 +59,11 @@ func (c *Command) printListTable(items []*workers.Worker) string { fmt.Sprintf(" Scope ID: %s", item.ScopeId), ) } + if item.Type != "" { + output = append(output, + fmt.Sprintf(" Type: %s", item.Type), + ) + } if item.Version > 0 { output = append(output, fmt.Sprintf(" Version: %d", item.Version), @@ -74,9 +79,9 @@ func (c *Command) printListTable(items []*workers.Worker) string { fmt.Sprintf(" Description: %s", item.Description), ) } - if item.CanonicalAddress != "" { + if item.Address != "" { output = append(output, - fmt.Sprintf(" Canonical Address: %s", item.CanonicalAddress), + fmt.Sprintf(" Address: %s", item.Address), ) } if !item.LastStatusTime.IsZero() { @@ -117,6 +122,12 @@ func printItemTable(result api.GenericResult) string { if item.Description != "" { nonAttributeMap["Description"] = item.Description } + if item.Type != "" { + nonAttributeMap["Type"] = item.Type + } + if item.Address != "" { + nonAttributeMap["Address"] = item.Address + } if !item.LastStatusTime.IsZero() { nonAttributeMap["Last Status Time"] = item.LastStatusTime } @@ -142,69 +153,14 @@ func printItemTable(result api.GenericResult) string { ) } - var workerProvidedTags map[string][]string - var workerProvidedAddress string - if item.WorkerProvidedConfiguration != nil { - config := item.WorkerProvidedConfiguration - configMap := make(map[string]any) - if config.Address != "" { - configMap["Address"] = config.Address - workerProvidedAddress = config.Address - } - if config.Name != "" { - configMap["Name"] = config.Name - } - ret = append(ret, - "", - " Worker-Provided Configuration:", - base.WrapMap(4, maxLength, configMap), - ) - workerProvidedTags = config.Tags - } - - if len(item.Address) > 0 || len(item.CanonicalAddress) > 0 || len(workerProvidedAddress) > 0 { - ret = append(ret, - "", - " Address:", - ) - if len(item.Address) > 0 { - ret = append(ret, - " Item (via API):", - " "+item.Address, - ) - } - if len(workerProvidedAddress) > 0 { - ret = append(ret, - " Worker Configuration:", - " "+workerProvidedAddress, - ) - } - if len(item.CanonicalAddress) > 0 { - ret = append(ret, - " Canonical:", - " "+item.CanonicalAddress, - ) - } - } - - if len(item.Tags) > 0 || len(item.CanonicalTags) > 0 || len(workerProvidedTags) > 0 { + if len(item.CanonicalTags) > 0 || len(item.ConfigTags) > 0 { ret = append(ret, "", " Tags:", ) - if len(item.Tags) > 0 { - tagMap := make(map[string]any, len(item.Tags)) - for k, v := range item.Tags { - tagMap[k] = v - } - ret = append(ret, - " Item (via API):", - base.WrapMap(6, 2, tagMap), - ) - } - if len(workerProvidedTags) > 0 { - tagMap := make(map[string]any, len(workerProvidedTags)) - for k, v := range workerProvidedTags { + if len(item.ConfigTags) > 0 { + tagMap := make(map[string]any, len(item.ConfigTags)) + for k, v := range item.ConfigTags { tagMap[k] = v } ret = append(ret, diff --git a/internal/daemon/cluster/handlers/worker_service.go b/internal/daemon/cluster/handlers/worker_service.go index d1badb5a3..581182341 100644 --- a/internal/daemon/cluster/handlers/worker_service.go +++ b/internal/daemon/cluster/handlers/worker_service.go @@ -65,7 +65,9 @@ func (ws *workerServiceServer) Status(ctx context.Context, req *pbs.StatusReques } switch { case wStat.GetName() == "" && wStat.GetKeyId() == "": - return &pbs.StatusResponse{}, status.Error(codes.InvalidArgument, "Name and keyId are not set in the request; at least one is required.") + return &pbs.StatusResponse{}, status.Error(codes.InvalidArgument, "Name and keyId are not set in the request; one is required.") + case wStat.GetName() != "" && wStat.GetKeyId() != "": + return &pbs.StatusResponse{}, status.Error(codes.InvalidArgument, "Name and keyId are both set in the request; only one is allowed.") case wStat.GetAddress() == "": return &pbs.StatusResponse{}, status.Error(codes.InvalidArgument, "Address is not set but is required.") } @@ -88,17 +90,18 @@ func (ws *workerServiceServer) Status(ctx context.Context, req *pbs.StatusReques }) } - wKeyId := wStat.GetKeyId() - - wConf := servers.NewWorkerForStatus(scope.Global.String(), + wConf := servers.NewWorker(scope.Global.String(), servers.WithName(wStat.GetName()), + servers.WithDescription(wStat.GetDescription()), servers.WithAddress(wStat.GetAddress()), - servers.WithWorkerTags(workerTags...), - servers.WithKeyId(wKeyId)) + servers.WithWorkerTags(workerTags...)) opts := []servers.Option{servers.WithUpdateTags(req.GetUpdateTags())} if wStat.GetPublicId() != "" { opts = append(opts, servers.WithPublicId(wStat.GetPublicId())) } + if wStat.GetKeyId() != "" { + opts = append(opts, servers.WithKeyId(wStat.GetKeyId())) + } wrk, err := serverRepo.UpsertWorkerStatus(ctx, wConf, opts...) if err != nil { event.WriteError(ctx, op, err, event.WithInfoMsg("error storing worker status")) @@ -229,7 +232,7 @@ func (ws *workerServiceServer) LookupSession(ctx context.Context, req *pbs.Looku } var w *servers.Worker if req.WorkerKeyId != "" { - workerId, err := serversRepo.LookupWorkerIdByWorkerReportedKeyId(ctx, req.WorkerKeyId) + workerId, err := serversRepo.LookupWorkerIdByKeyId(ctx, req.WorkerKeyId) if err != nil { event.WriteError(ctx, op, err, event.WithInfoMsg("error looking up worker by keyId", "keyId", req.WorkerKeyId)) return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal, "Error looking up tags for server: %v", err) @@ -240,7 +243,7 @@ func (ws *workerServiceServer) LookupSession(ctx context.Context, req *pbs.Looku return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal, "Error looking up tags for server: %v", err) } } else { - w, err = serversRepo.LookupWorkerByWorkerReportedName(ctx, req.GetServerId()) + w, err = serversRepo.LookupWorkerByName(ctx, req.GetServerId()) if err != nil { event.WriteError(ctx, op, err, event.WithInfoMsg("error looking up worker by name", "name", req.ServerId)) return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal, "Error looking up tags for server: %v", err) @@ -255,12 +258,8 @@ func (ws *workerServiceServer) LookupSession(ctx context.Context, req *pbs.Looku event.WriteError(ctx, op, err, event.WithInfoMsg("error creating worker filter evaluator", "server_id", req.ServerId)) return &pbs.LookupSessionResponse{}, status.Errorf(codes.Internal, "Error creating worker filter evaluator: %v", err) } - name := w.GetName() - if name == "" { - name = w.GetWorkerReportedName() - } filterInput := map[string]interface{}{ - "name": name, + "name": w.GetName(), "tags": tagMap, } ok, err := eval.Evaluate(filterInput) @@ -391,7 +390,7 @@ func (ws *workerServiceServer) AuthorizeConnection(ctx context.Context, req *pbs if err != nil { return nil, status.Errorf(codes.Internal, "error getting servers repo: %v", err) } - w, err := serversRepo.LookupWorkerByWorkerReportedName(ctx, req.GetWorkerId()) + w, err := serversRepo.LookupWorkerByName(ctx, req.GetWorkerId()) if err != nil { return nil, status.Errorf(codes.Internal, "error looking up worker: %v", err) } diff --git a/internal/daemon/cluster/handlers/worker_service_status_test.go b/internal/daemon/cluster/handlers/worker_service_status_test.go index 144a753b2..9a9c77d4f 100644 --- a/internal/daemon/cluster/handlers/worker_service_status_test.go +++ b/internal/daemon/cluster/handlers/worker_service_status_test.go @@ -71,7 +71,7 @@ func TestStatus(t *testing.T) { target.WithSessionConnectionLimit(-1), ) - worker1 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, @@ -107,8 +107,8 @@ func TestStatus(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Name: worker1.GetName(), + Address: worker1.GetAddress(), }, }, want: &pbs.StatusResponse{ @@ -127,8 +127,8 @@ func TestStatus(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Name: worker1.GetName(), + Address: worker1.GetAddress(), }, Jobs: []*pbs.JobStatus{ { @@ -166,10 +166,10 @@ func TestStatus(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Address: worker1.CanonicalAddress(), + Address: worker1.GetAddress(), }, }, - wantErrMsg: status.Error(codes.InvalidArgument, "Name and keyId are not set in the request; at least one is required.").Error(), + wantErrMsg: status.Error(codes.InvalidArgument, "Name and keyId are not set in the request; one is required.").Error(), }, { name: "No Address", @@ -177,7 +177,7 @@ func TestStatus(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Name: worker1.GetWorkerReportedName(), + Name: worker1.GetName(), }, }, wantErrMsg: status.Error(codes.InvalidArgument, "Address is not set but is required.").Error(), @@ -257,7 +257,7 @@ func TestStatusSessionClosed(t *testing.T) { target.WithSessionConnectionLimit(-1), ) - worker1 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, @@ -310,8 +310,8 @@ func TestStatusSessionClosed(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Name: worker1.GetName(), + Address: worker1.GetAddress(), }, Jobs: []*pbs.JobStatus{ { @@ -408,7 +408,7 @@ func TestStatusDeadConnection(t *testing.T) { Address: "127.0.0.1", }) - worker1 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) serversRepoFn := func() (*servers.Repository, error) { return serverRepo, nil @@ -477,8 +477,8 @@ func TestStatusDeadConnection(t *testing.T) { req := &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ PublicId: worker1.GetPublicId(), - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Name: worker1.GetName(), + Address: worker1.GetAddress(), }, Jobs: []*pbs.JobStatus{ { @@ -578,7 +578,7 @@ func TestStatusWorkerWithKeyId(t *testing.T) { target.WithSessionConnectionLimit(-1), ) - worker1 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestPkiWorker(t, conn, wrapper) rootStorage, err := servers.NewRepositoryStorage(ctx, rw, rw, kms) require.NoError(t, err) @@ -636,8 +636,7 @@ func TestStatusWorkerWithKeyId(t *testing.T) { wantErr: false, req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Address: "someaddress", KeyId: nodeInfo.Id, }, }, @@ -657,8 +656,7 @@ func TestStatusWorkerWithKeyId(t *testing.T) { req: &pbs.StatusRequest{ WorkerStatus: &servers.ServerWorkerStatus{ KeyId: nodeInfo.Id, - Name: worker1.GetWorkerReportedName(), - Address: worker1.CanonicalAddress(), + Address: "someaddress", }, Jobs: []*pbs.JobStatus{ { @@ -703,6 +701,7 @@ func TestStatusWorkerWithKeyId(t *testing.T) { assert.Equal(tc.wantErrMsg, err.Error()) return } + require.NoError(err) assert.Empty( cmp.Diff( tc.want, diff --git a/internal/daemon/controller/handlers/targets/target_service.go b/internal/daemon/controller/handlers/targets/target_service.go index ad2c33956..164a5fafe 100644 --- a/internal/daemon/controller/handlers/targets/target_service.go +++ b/internal/daemon/controller/handlers/targets/target_service.go @@ -2140,7 +2140,7 @@ type workerList []*servers.Worker func (w workerList) addresses() []string { ret := make([]string, 0, len(w)) for _, worker := range w { - ret = append(ret, worker.CanonicalAddress()) + ret = append(ret, worker.GetAddress()) } return ret } @@ -2149,7 +2149,7 @@ func (w workerList) addresses() []string { func (w workerList) workerInfos() []*pb.WorkerInfo { ret := make([]*pb.WorkerInfo, 0, len(w)) for _, worker := range w { - ret = append(ret, &pb.WorkerInfo{Address: worker.CanonicalAddress()}) + ret = append(ret, &pb.WorkerInfo{Address: worker.GetAddress()}) } return ret } @@ -2159,15 +2159,8 @@ func (w workerList) workerInfos() []*pb.WorkerInfo { func (w workerList) filtered(eval *bexpr.Evaluator) (workerList, error) { var ret []*servers.Worker for _, worker := range w { - - // TODO: Decide how we are actually going to filter by name now that - // we are separating reported status name and the resource name. - name := worker.GetName() - if name == "" { - name = worker.GetWorkerReportedName() - } filterInput := map[string]interface{}{ - "name": name, + "name": worker.GetName(), "tags": worker.CanonicalTags(), } ok, err := eval.Evaluate(filterInput) diff --git a/internal/daemon/controller/handlers/targets/target_service_test.go b/internal/daemon/controller/handlers/targets/target_service_test.go index 675946ac4..e7f635326 100644 --- a/internal/daemon/controller/handlers/targets/target_service_test.go +++ b/internal/daemon/controller/handlers/targets/target_service_test.go @@ -4,6 +4,7 @@ import ( "fmt" "testing" + "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/servers" "github.com/hashicorp/boundary/internal/types/scope" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/targets" @@ -32,18 +33,20 @@ func TestWorkerList_Addresses(t *testing.T) { } func TestWorkerList_Filter(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) var workers []*servers.Worker for i := 0; i < 5; i++ { switch { case i%2 == 0: - workers = append(workers, servers.NewWorker(scope.Global.String(), + workers = append(workers, servers.TestKmsWorker(t, conn, wrapper, servers.WithName(fmt.Sprintf("test_worker_%d", i)), servers.WithWorkerTags(&servers.Tag{ Key: fmt.Sprintf("key%d", i), Value: fmt.Sprintf("value%d", i), }))) default: - workers = append(workers, servers.NewWorkerForStatus(scope.Global.String(), + workers = append(workers, servers.TestPkiWorker(t, conn, wrapper, servers.WithName(fmt.Sprintf("test_worker_%d", i)), servers.WithWorkerTags(&servers.Tag{ Key: "key", diff --git a/internal/daemon/controller/handlers/targets/tcp/target_service_test.go b/internal/daemon/controller/handlers/targets/tcp/target_service_test.go index 940963743..cb0f2a8a1 100644 --- a/internal/daemon/controller/handlers/targets/tcp/target_service_test.go +++ b/internal/daemon/controller/handlers/targets/tcp/target_service_test.go @@ -2784,7 +2784,7 @@ func TestAuthorizeSession(t *testing.T) { require.NoError(t, err) // Tell our DB that there is a worker ready to serve the data - servers.TestWorker(t, conn, wrapper) + servers.TestKmsWorker(t, conn, wrapper) asRes1, err := s.AuthorizeSession(ctx, &pbs.AuthorizeSessionRequest{ Id: tar.GetPublicId(), @@ -3062,7 +3062,7 @@ func TestAuthorizeSessionTypedCredentials(t *testing.T) { require.NoError(t, err) // Tell our DB that there is a worker ready to serve the data - servers.TestWorker(t, conn, wrapper) + servers.TestKmsWorker(t, conn, wrapper) asRes, err := s.AuthorizeSession(ctx, &pbs.AuthorizeSessionRequest{ Id: tar.GetPublicId(), diff --git a/internal/daemon/controller/handlers/workers/worker_service.go b/internal/daemon/controller/handlers/workers/worker_service.go index 922fbb41b..f2c7726b7 100644 --- a/internal/daemon/controller/handlers/workers/worker_service.go +++ b/internal/daemon/controller/handlers/workers/worker_service.go @@ -3,6 +3,7 @@ package workers import ( "context" "fmt" + "strings" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/auth" @@ -19,6 +20,7 @@ import ( "github.com/hashicorp/boundary/internal/types/resource" "github.com/hashicorp/boundary/internal/types/scope" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers" + "github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/nodeenrollment/types" "github.com/mr-tron/base58" "google.golang.org/grpc/codes" @@ -27,6 +29,11 @@ import ( "google.golang.org/protobuf/types/known/wrapperspb" ) +const ( + PkiWorkerType = "pki" + KmsWorkerType = "kms" +) + var ( maskManager handlers.MaskManager @@ -330,7 +337,6 @@ func (s Service) createInRepo(ctx context.Context, worker *pb.Worker, creds *typ worker.GetScopeId(), servers.WithName(worker.GetName().GetValue()), servers.WithDescription(worker.GetDescription().GetValue()), - servers.WithAddress(worker.GetAddress().GetValue()), ) retWorker, err := repo.CreateWorker(ctx, newWorker, servers.WithFetchNodeCredentialsRequest(creds)) if err != nil { @@ -364,9 +370,6 @@ func (s Service) updateInRepo(ctx context.Context, scopeId, id string, mask []st if name := item.GetName(); name != nil { opts = append(opts, servers.WithName(name.GetValue())) } - if addr := item.GetAddress(); addr != nil { - opts = append(opts, servers.WithAddress(addr.GetValue())) - } w := servers.NewWorker(scopeId, opts...) w.PublicId = id dbMask := maskManager.Translate(mask) @@ -452,12 +455,22 @@ func toProto(ctx context.Context, in *servers.Worker, opt ...handlers.Option) (* } if outputFields.Has(globals.AuthorizedActionsField) { out.AuthorizedActions = opts.WithAuthorizedActions + if in.Type == KmsWorkerType && out.AuthorizedActions != nil { + // KMS workers cannot be updated through the API + allActions := out.AuthorizedActions + out.AuthorizedActions = make([]string, 0, len(allActions)) + for _, act := range allActions { + if act != action.Update.String() { + out.AuthorizedActions = append(out.AuthorizedActions, act) + } + } + } } if outputFields.Has(globals.AddressField) && in.GetAddress() != "" { - out.Address = wrapperspb.String(in.GetAddress()) + out.Address = in.GetAddress() } - if outputFields.Has(globals.CanonicalAddressField) { - out.CanonicalAddress = in.CanonicalAddress() + if outputFields.Has(globals.TypeField) && in.GetType() != "" { + out.Type = in.GetType() } if outputFields.Has(globals.LastStatusTimeField) { out.LastStatusTime = in.GetLastStatusTime().GetTimestamp() @@ -465,6 +478,13 @@ func toProto(ctx context.Context, in *servers.Worker, opt ...handlers.Option) (* if outputFields.Has(globals.ActiveConnectionCountField) { out.ActiveConnectionCount = &wrapperspb.UInt32Value{Value: in.ActiveConnectionCount()} } + if outputFields.Has(globals.ConfigTagsField) && len(in.GetConfigTags()) > 0 { + var err error + out.ConfigTags, err = tagsToMapProto(in.GetConfigTags()) + if err != nil { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing config tags proto")) + } + } if outputFields.Has(globals.CanonicalTagsField) && len(in.CanonicalTags()) > 0 { var err error out.CanonicalTags, err = tagsToMapProto(in.CanonicalTags()) @@ -472,31 +492,6 @@ func toProto(ctx context.Context, in *servers.Worker, opt ...handlers.Option) (* return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing canonical tags proto")) } } - if outputFields.Has(globals.TagsField) && len(in.GetApiTags()) > 0 { - var err error - out.Tags, err = tagsToMapProto(in.GetApiTags()) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing api tags proto")) - } - } - if outputFields.Has(globals.ConfigurationField) { - if in.GetWorkerReportedAddress() != "" || - in.GetWorkerReportedName() != "" || - len(in.GetConfigTags()) > 0 { - out.WorkerProvidedConfiguration = &pb.WorkerProvidedConfiguration{} - } - if len(in.GetConfigTags()) > 0 { - var err error - out.GetWorkerProvidedConfiguration().Tags, err = tagsToMapProto(in.GetConfigTags()) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error preparing config tags proto")) - } - } - if out.WorkerProvidedConfiguration != nil { - out.GetWorkerProvidedConfiguration().Address = in.GetWorkerReportedAddress() - out.GetWorkerProvidedConfiguration().Name = in.GetWorkerReportedName() - } - } return &out, nil } @@ -551,17 +546,25 @@ func validateDeleteRequest(req *pbs.DeleteWorkerRequest) error { func validateUpdateRequest(req *pbs.UpdateWorkerRequest) error { return handlers.ValidateUpdateRequest(req, req.GetItem(), func() map[string]string { badFields := map[string]string{} - if req.GetItem().GetWorkerProvidedConfiguration() != nil { - badFields[globals.ConfigurationField] = "This is a read only field." - } - if req.GetItem().GetCanonicalAddress() != "" { - badFields[globals.CanonicalAddressField] = "This is a read only field." + if req.GetItem().GetAddress() != "" { + badFields[globals.AddressField] = "This is a read only field." } if req.GetItem().GetCanonicalTags() != nil { badFields[globals.CanonicalAddressField] = "This is a read only field." } - if req.GetItem().GetTags() != nil { - badFields[globals.TagsField] = "These values cannot be updated in this type of request." + if req.GetItem().GetConfigTags() != nil { + badFields[globals.TagsField] = "This is a read only field." + } + nameString := req.GetItem().GetName().String() + if !strutil.Printable(nameString) { + badFields[globals.NameField] = "Contains non-printable characters" + } + if strings.ToLower(nameString) != nameString { + badFields[globals.NameField] = "Must be all lowercase." + } + descriptionString := req.GetItem().GetDescription().String() + if !strutil.Printable(descriptionString) { + badFields[globals.DescriptionField] = "Contains non-printable characters." } return badFields }, servers.WorkerPrefix) @@ -583,24 +586,32 @@ func validateCreateRequest(req *pbs.CreateWorkerLedRequest) error { if req.GetItem().WorkerGeneratedAuthToken == nil { badFields[globals.WorkerGeneratedAuthTokenField] = cannotBeEmptyMsg } - if req.GetItem().CanonicalAddress != "" { + if req.GetItem().Address != "" { badFields[globals.CanonicalAddressField] = readOnlyFieldMsg } - if req.GetItem().Tags != nil { - badFields[globals.TagsField] = readOnlyFieldMsg - } if req.GetItem().CanonicalTags != nil { badFields[globals.CanonicalTagsField] = readOnlyFieldMsg } + if req.GetItem().ConfigTags != nil { + badFields[globals.ConfigTagsField] = readOnlyFieldMsg + } if req.GetItem().LastStatusTime != nil { badFields[globals.LastStatusTimeField] = readOnlyFieldMsg } - if req.GetItem().WorkerProvidedConfiguration != nil { - badFields[globals.WorkerProvidedConfigurationField] = readOnlyFieldMsg - } if req.GetItem().AuthorizedActions != nil { badFields[globals.AuthorizedActionsField] = readOnlyFieldMsg } + nameString := req.GetItem().GetName().String() + if !strutil.Printable(nameString) { + badFields[globals.NameField] = "Name contains non-printable characters." + } + if strings.ToLower(nameString) != nameString { + badFields[globals.NameField] = "Name must be all lowercase." + } + descriptionString := req.GetItem().GetDescription().String() + if !strutil.Printable(descriptionString) { + badFields[globals.DescriptionField] = "Description contains non-printable characters." + } return badFields }) } diff --git a/internal/daemon/controller/handlers/workers/worker_service_test.go b/internal/daemon/controller/handlers/workers/worker_service_test.go index 20ef70d9c..4fb69d62b 100644 --- a/internal/daemon/controller/handlers/workers/worker_service_test.go +++ b/internal/daemon/controller/handlers/workers/worker_service_test.go @@ -16,10 +16,12 @@ import ( "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/servers" + "github.com/hashicorp/boundary/internal/types/action" "github.com/hashicorp/boundary/internal/types/scope" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers" pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers" + "github.com/hashicorp/go-secure-stdlib/strutil" "github.com/hashicorp/nodeenrollment/rotation" "github.com/hashicorp/nodeenrollment/storage/file" "github.com/hashicorp/nodeenrollment/types" @@ -63,51 +65,73 @@ func TestGet(t *testing.T) { return repo, nil } - worker := servers.TestWorker(t, conn, wrap, - servers.WithName("test worker names"), - servers.WithDescription("test worker description"), - servers.WithAddress("test worker address"), + kmsWorker := servers.TestKmsWorker(t, conn, wrap, + servers.WithName("test kms worker names"), + servers.WithDescription("test kms worker description"), + servers.WithAddress("test kms worker address"), servers.WithWorkerTags(&servers.Tag{Key: "key", Value: "val"})) + + kmsAuthzActions := make([]string, len(testAuthorizedActions)) + copy(kmsAuthzActions, testAuthorizedActions) + + wantKmsWorker := &pb.Worker{ + Id: kmsWorker.GetPublicId(), + ScopeId: kmsWorker.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: kmsWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, + CreatedTime: kmsWorker.CreateTime.GetTimestamp(), + UpdatedTime: kmsWorker.UpdateTime.GetTimestamp(), + Version: kmsWorker.GetVersion(), + Name: wrapperspb.String(kmsWorker.GetName()), + Description: wrapperspb.String(kmsWorker.GetDescription()), + Address: kmsWorker.GetAddress(), + AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()), + LastStatusTime: kmsWorker.GetLastStatusTime().GetTimestamp(), + CanonicalTags: map[string]*structpb.ListValue{ + "key": structListValue(t, "val"), + }, + ConfigTags: map[string]*structpb.ListValue{ + "key": structListValue(t, "val"), + }, + Type: KmsWorkerType, + } + + var pkiWorkerKeyId string + pkiWorker := servers.TestPkiWorker(t, conn, wrap, + servers.WithName("test pki worker names"), + servers.WithDescription("test pki worker description"), + servers.WithTestPkiWorkerAuthorizedKeyId(&pkiWorkerKeyId)) // Add config tags to the created worker - worker, err = repo.UpsertWorkerStatus(context.Background(), - servers.NewWorkerForStatus(worker.GetScopeId(), - servers.WithName(worker.GetWorkerReportedName()), - servers.WithAddress(worker.GetWorkerReportedAddress()), + pkiWorker, err = repo.UpsertWorkerStatus(context.Background(), + servers.NewWorker(pkiWorker.GetScopeId(), + servers.WithAddress("test kms worker address"), servers.WithWorkerTags(&servers.Tag{ Key: "config", Value: "test", })), servers.WithUpdateTags(true), - servers.WithPublicId(worker.GetPublicId())) + servers.WithPublicId(pkiWorker.GetPublicId()), + servers.WithKeyId(pkiWorkerKeyId)) require.NoError(t, err) - wantWorker := &pb.Worker{ - Id: worker.GetPublicId(), - ScopeId: worker.GetScopeId(), - Scope: &scopes.ScopeInfo{Id: worker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, - CreatedTime: worker.CreateTime.GetTimestamp(), - UpdatedTime: worker.UpdateTime.GetTimestamp(), - Version: worker.GetVersion(), - Name: wrapperspb.String(worker.GetName()), - Description: wrapperspb.String(worker.GetDescription()), - Address: wrapperspb.String(worker.GetAddress()), + wantPkiWorker := &pb.Worker{ + Id: pkiWorker.GetPublicId(), + ScopeId: pkiWorker.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: pkiWorker.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, + CreatedTime: pkiWorker.CreateTime.GetTimestamp(), + UpdatedTime: pkiWorker.UpdateTime.GetTimestamp(), + Version: pkiWorker.GetVersion(), + Name: wrapperspb.String(pkiWorker.GetName()), + Description: wrapperspb.String(pkiWorker.GetDescription()), + Address: pkiWorker.GetAddress(), AuthorizedActions: testAuthorizedActions, - CanonicalAddress: worker.CanonicalAddress(), - LastStatusTime: worker.GetLastStatusTime().GetTimestamp(), + LastStatusTime: pkiWorker.GetLastStatusTime().GetTimestamp(), CanonicalTags: map[string]*structpb.ListValue{ - "key": structListValue(t, "val"), "config": structListValue(t, "test"), }, - Tags: map[string]*structpb.ListValue{ - "key": structListValue(t, "val"), - }, - WorkerProvidedConfiguration: &pb.WorkerProvidedConfiguration{ - Address: worker.GetWorkerReportedAddress(), - Name: worker.GetWorkerReportedName(), - Tags: map[string]*structpb.ListValue{ - "config": structListValue(t, "test"), - }, + ConfigTags: map[string]*structpb.ListValue{ + "config": structListValue(t, "test"), }, + Type: PkiWorkerType, } cases := []struct { @@ -118,10 +142,16 @@ func TestGet(t *testing.T) { err error }{ { - name: "Get an Existing Worker", - scopeId: worker.GetScopeId(), - req: &pbs.GetWorkerRequest{Id: worker.GetPublicId()}, - res: &pbs.GetWorkerResponse{Item: wantWorker}, + name: "Get an Existing KMS Worker", + scopeId: kmsWorker.GetScopeId(), + req: &pbs.GetWorkerRequest{Id: kmsWorker.GetPublicId()}, + res: &pbs.GetWorkerResponse{Item: wantKmsWorker}, + }, + { + name: "Get an Existing PKI Worker", + scopeId: pkiWorker.GetScopeId(), + req: &pbs.GetWorkerRequest{Id: pkiWorker.GetPublicId()}, + res: &pbs.GetWorkerResponse{Item: wantPkiWorker}, }, { name: "Get a non-existent Worker", @@ -172,10 +202,30 @@ func TestList(t *testing.T) { return servers.NewRepository(rw, rw, kms) } - var wantWorkers []*pb.Worker + var wantKmsWorkers []*pb.Worker for i := 0; i < 10; i++ { - w := servers.TestWorker(t, conn, wrap, servers.WithName(fmt.Sprintf("worker%d", i))) - wantWorkers = append(wantWorkers, &pb.Worker{ + w := servers.TestKmsWorker(t, conn, wrap, servers.WithName(fmt.Sprintf("kms-worker%d", i))) + kmsAuthzActions := make([]string, len(testAuthorizedActions)) + copy(kmsAuthzActions, testAuthorizedActions) + wantKmsWorkers = append(wantKmsWorkers, &pb.Worker{ + Id: w.GetPublicId(), + ScopeId: w.GetScopeId(), + Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, + CreatedTime: w.CreateTime.GetTimestamp(), + UpdatedTime: w.UpdateTime.GetTimestamp(), + Version: w.GetVersion(), + Name: wrapperspb.String(w.GetName()), + AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()), + Address: w.GetAddress(), + Type: KmsWorkerType, + LastStatusTime: w.GetLastStatusTime().GetTimestamp(), + }) + } + + var wantPkiWorkers []*pb.Worker + for i := 0; i < 10; i++ { + w := servers.TestPkiWorker(t, conn, wrap, servers.WithName(fmt.Sprintf("pki-worker%d", i))) + wantPkiWorkers = append(wantPkiWorkers, &pb.Worker{ Id: w.GetPublicId(), ScopeId: w.GetScopeId(), Scope: &scopes.ScopeInfo{Id: w.GetScopeId(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, @@ -184,12 +234,9 @@ func TestList(t *testing.T) { Version: w.GetVersion(), Name: wrapperspb.String(w.GetName()), AuthorizedActions: testAuthorizedActions, - CanonicalAddress: w.CanonicalAddress(), + Address: w.GetAddress(), + Type: PkiWorkerType, LastStatusTime: w.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: &pb.WorkerProvidedConfiguration{ - Address: w.GetWorkerReportedAddress(), - Name: w.GetWorkerReportedName(), - }, }) } @@ -202,27 +249,27 @@ func TestList(t *testing.T) { { name: "List All Workers", req: &pbs.ListWorkersRequest{ScopeId: scope.Global.String()}, - res: &pbs.ListWorkersResponse{Items: wantWorkers}, + res: &pbs.ListWorkersResponse{Items: append(wantKmsWorkers, wantPkiWorkers...)}, }, { name: "List global workers recursively", req: &pbs.ListWorkersRequest{ScopeId: "global", Recursive: true}, res: &pbs.ListWorkersResponse{ - Items: wantWorkers, + Items: append(wantKmsWorkers, wantPkiWorkers...), }, }, { - name: "Filter to a single workers", - req: &pbs.ListWorkersRequest{ScopeId: "global", Recursive: true, Filter: `"/item/name"=="worker2"`}, + name: "Filter to a single worker of each type", + req: &pbs.ListWorkersRequest{ScopeId: "global", Recursive: true, Filter: `"/item/name"=="kms-worker2" or "/item/name"=="pki-worker2"`}, res: &pbs.ListWorkersResponse{ - Items: wantWorkers[2:3], + Items: []*pb.Worker{wantKmsWorkers[2], wantPkiWorkers[2]}, }, }, { - name: "Filter to 2 workers", - req: &pbs.ListWorkersRequest{ScopeId: "global", Recursive: true, Filter: `"/item/name" matches "worker[23]"`}, + name: "Filter to 2 workers of each type", + req: &pbs.ListWorkersRequest{ScopeId: "global", Recursive: true, Filter: `"/item/name" matches "kms-worker[23]" or "/item/name" matches "pki-worker[23]"`}, res: &pbs.ListWorkersResponse{ - Items: wantWorkers[2:4], + Items: []*pb.Worker{wantKmsWorkers[2], wantKmsWorkers[3], wantPkiWorkers[2], wantPkiWorkers[3]}, }, }, { @@ -253,6 +300,10 @@ func TestList(t *testing.T) { sort.Slice(got.Items, func(i, j int) bool { return got.Items[i].GetName().GetValue() < got.Items[j].GetName().GetValue() }) + require.NoError(gErr) + sort.Slice(tc.res.Items, func(i, j int) bool { + return tc.res.Items[i].GetName().GetValue() < tc.res.Items[j].GetName().GetValue() + }) assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListWorkers(%q) got response %q, wanted %q", tc.req.GetScopeId(), got, tc.res) // Test the anon case @@ -285,7 +336,7 @@ func TestDelete(t *testing.T) { s, err := NewService(ctx, repoFn, iamRepoFn) require.NoError(t, err, "Error when getting new worker service.") - w := servers.TestWorker(t, conn, wrap) + w := servers.TestKmsWorker(t, conn, wrap) cases := []struct { name string @@ -349,16 +400,15 @@ func TestUpdate(t *testing.T) { return repo, nil } - wkr := servers.TestWorker(t, conn, wrapper, + wkr := servers.TestPkiWorker(t, conn, wrapper, servers.WithName("default"), - servers.WithDescription("default"), - servers.WithAddress("default")) + servers.WithDescription("default")) version := wkr.GetVersion() resetWorker := func() { version++ - _, _, err = repo.UpdateWorker(context.Background(), wkr, version, []string{"Name", "Description", "Address"}) + _, _, err = repo.UpdateWorker(context.Background(), wkr, version, []string{"Name", "Description"}) require.NoError(t, err, "Failed to reset worker.") version++ } @@ -370,10 +420,6 @@ func TestUpdate(t *testing.T) { workerService, err := NewService(ctx, repoFn, iamRepoFn) require.NoError(t, err) expectedScope := &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"} - expectedConfig := &pb.WorkerProvidedConfiguration{ - Address: wkr.GetWorkerReportedAddress(), - Name: wkr.GetWorkerReportedName(), - } cases := []struct { name string @@ -385,27 +431,24 @@ func TestUpdate(t *testing.T) { name: "Update an Existing Worker", req: &pbs.UpdateWorkerRequest{ UpdateMask: &field_mask.FieldMask{ - Paths: []string{"name", "description", "address"}, + Paths: []string{"name", "description"}, }, Item: &pb.Worker{ Name: wrapperspb.String("name"), Description: wrapperspb.String("desc"), - Address: wrapperspb.String("address"), }, }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("name"), - Description: wrapperspb.String("desc"), - Address: wrapperspb.String("address"), - CanonicalAddress: "address", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("name"), + Description: wrapperspb.String("desc"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, @@ -422,20 +465,30 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("name"), - Description: wrapperspb.String("desc"), - Address: wrapperspb.String("default"), - CanonicalAddress: "default", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("name"), + Description: wrapperspb.String("desc"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, + { + name: "cant update address", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"address"}, + }, + Item: &pb.Worker{ + Address: "updated", + }, + }, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, { name: "No Update Mask", req: &pbs.UpdateWorkerRequest{ @@ -457,14 +510,6 @@ func TestUpdate(t *testing.T) { }, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, - { - name: "Update port to 0", - req: &pbs.UpdateWorkerRequest{ - UpdateMask: &field_mask.FieldMask{Paths: []string{"default_port"}}, - Item: &pb.Worker{}, - }, - err: handlers.ApiErrorWithCode(codes.InvalidArgument), - }, { name: "Only non-existant paths in Mask", req: &pbs.UpdateWorkerRequest{ @@ -488,16 +533,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Description: wrapperspb.String("default"), - Address: wrapperspb.String("default"), - CanonicalAddress: "default", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Description: wrapperspb.String("default"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, @@ -513,16 +556,14 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("default"), - Address: wrapperspb.String("default"), - CanonicalAddress: "default", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("default"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, @@ -539,17 +580,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("updated"), - Description: wrapperspb.String("default"), - Address: wrapperspb.String("default"), - CanonicalAddress: "default", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("updated"), + Description: wrapperspb.String("default"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, @@ -566,17 +605,15 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("default"), - Description: wrapperspb.String("notignored"), - Address: wrapperspb.String("default"), - CanonicalAddress: "default", - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - WorkerProvidedConfiguration: expectedConfig, - AuthorizedActions: testAuthorizedActions, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("default"), + Description: wrapperspb.String("notignored"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, }, }, }, @@ -593,38 +630,6 @@ func TestUpdate(t *testing.T) { }, err: handlers.ApiErrorWithCode(codes.NotFound), }, - { - name: "Cant change Worker Defined Name", - req: &pbs.UpdateWorkerRequest{ - Id: wkr.GetPublicId(), - UpdateMask: &field_mask.FieldMask{ - Paths: []string{"worker_provided_configuration.name"}, - }, - Item: &pb.Worker{ - WorkerProvidedConfiguration: &pb.WorkerProvidedConfiguration{ - Name: "name", - }, - }, - }, - res: nil, - err: handlers.ApiErrorWithCode(codes.InvalidArgument), - }, - { - name: "Cant change Worker Defined Address", - req: &pbs.UpdateWorkerRequest{ - Id: wkr.GetPublicId(), - UpdateMask: &field_mask.FieldMask{ - Paths: []string{"worker_provided_configuration.address"}, - }, - Item: &pb.Worker{ - WorkerProvidedConfiguration: &pb.WorkerProvidedConfiguration{ - Address: "address", - }, - }, - }, - res: nil, - err: handlers.ApiErrorWithCode(codes.InvalidArgument), - }, { name: "Cant change Id", req: &pbs.UpdateWorkerRequest{ @@ -672,7 +677,7 @@ func TestUpdate(t *testing.T) { Paths: []string{"tags"}, }, Item: &pb.Worker{ - Tags: map[string]*structpb.ListValue{ + ConfigTags: map[string]*structpb.ListValue{ "foo": structListValue(t, "bar"), }, }, @@ -696,13 +701,52 @@ func TestUpdate(t *testing.T) { err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, { - name: "Cant specify canonical address", + name: "Cant specify address", req: &pbs.UpdateWorkerRequest{ UpdateMask: &field_mask.FieldMask{ - Paths: []string{"canonical_address"}, + Paths: []string{globals.AddressField}, }, Item: &pb.Worker{ - CanonicalAddress: "should_fail", + Address: "should_fail", + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, + { + name: "Invalid name- uppercase", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name", "description", "address"}, + }, + Item: &pb.Worker{ + Name: wrapperspb.String("BADNAME"), + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, + { + name: "Invalid name- non-printable", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name", "description", "address"}, + }, + Item: &pb.Worker{ + Name: wrapperspb.String("\x00"), + }, + }, + res: nil, + err: handlers.ApiErrorWithCode(codes.InvalidArgument), + }, + { + name: "Invalid description- nonprintable", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name", "description", "address"}, + }, + Item: &pb.Worker{ + Description: wrapperspb.String("\x00"), }, }, res: nil, @@ -743,6 +787,85 @@ func TestUpdate(t *testing.T) { } } +func TestUpdate_KMS(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + kms := kms.TestKms(t, conn, wrapper) + ctx := context.Background() + rw := db.New(conn) + + iamRepo := iam.TestRepo(t, conn, wrapper) + iamRepoFn := func() (*iam.Repository, error) { + return iamRepo, nil + } + repo, err := servers.NewRepository(rw, rw, kms) + require.NoError(t, err) + repoFn := func() (*servers.Repository, error) { + return repo, nil + } + + wkr := servers.TestKmsWorker(t, conn, wrapper, + servers.WithName("default"), + servers.WithDescription("default")) + + toMerge := &pbs.UpdateWorkerRequest{ + Id: wkr.GetPublicId(), + } + workerService, err := NewService(ctx, repoFn, iamRepoFn) + require.NoError(t, err) + + cases := []struct { + name string + req *pbs.UpdateWorkerRequest + res *pbs.UpdateWorkerResponse + err error + }{ + { + name: "Cant set name", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"name"}, + }, + Item: &pb.Worker{ + Name: wrapperspb.String("name"), + }, + }, + }, + { + name: "Cant set description", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"description"}, + }, + Item: &pb.Worker{ + Description: wrapperspb.String("description"), + }, + }, + }, + { + name: "Cant set address", + req: &pbs.UpdateWorkerRequest{ + UpdateMask: &field_mask.FieldMask{ + Paths: []string{"address"}, + }, + Item: &pb.Worker{ + Address: "address", + }, + }, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + req := proto.Clone(toMerge).(*pbs.UpdateWorkerRequest) + proto.Merge(req, tc.req) + got, gErr := workerService.UpdateWorker(auth.DisabledAuthTestContext(iamRepoFn, scope.Global.String()), req) + assert.Error(t, gErr) + assert.Nil(t, got) + }) + } +} + func TestUpdate_BadVersion(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") @@ -767,7 +890,7 @@ func TestUpdate_BadVersion(t *testing.T) { workerService, err := NewService(ctx, repoFn, iamRepoFn) require.NoError(t, err, "Failed to create a new host set service.") - wkr := servers.TestWorker(t, conn, wrapper) + wkr := servers.TestKmsWorker(t, conn, wrapper) upTar, err := workerService.UpdateWorker(auth.DisabledAuthTestContext(iamRepoFn, proj.GetPublicId()), &pbs.UpdateWorkerRequest{ Id: wkr.GetPublicId(), @@ -877,29 +1000,29 @@ func TestCreateWorkerLed(t *testing.T) { wantErrContains: globals.IdField, }, { - name: "invalid-canonical-address", + name: "invalid-address", service: testSrv, scopeId: scope.Global.String(), req: &pbs.CreateWorkerLedRequest{ Item: &workers.Worker{ ScopeId: scope.Global.String(), WorkerGeneratedAuthToken: &wrapperspb.StringValue{Value: fetchReqFn()}, - CanonicalAddress: "invalid-canonical-address", + Address: "invalid-address", }, }, wantErr: true, wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), - wantErrContains: globals.CanonicalAddressField, + wantErrContains: globals.AddressField, }, { - name: "invalid-tags", + name: "invalid-config-tags", service: testSrv, scopeId: scope.Global.String(), req: &pbs.CreateWorkerLedRequest{ Item: &workers.Worker{ ScopeId: scope.Global.String(), WorkerGeneratedAuthToken: &wrapperspb.StringValue{Value: fetchReqFn()}, - Tags: map[string]*structpb.ListValue{ + ConfigTags: map[string]*structpb.ListValue{ "invalid": {Values: []*structpb.Value{ structpb.NewStringValue("invalid-tags"), }}, @@ -908,7 +1031,7 @@ func TestCreateWorkerLed(t *testing.T) { }, wantErr: true, wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), - wantErrContains: globals.TagsField, + wantErrContains: globals.ConfigTagsField, }, { name: "invalid-canonical-tags", @@ -944,21 +1067,6 @@ func TestCreateWorkerLed(t *testing.T) { wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), wantErrContains: globals.LastStatusTimeField, }, - { - name: "invalid-worker-config", - service: testSrv, - scopeId: scope.Global.String(), - req: &pbs.CreateWorkerLedRequest{ - Item: &workers.Worker{ - ScopeId: scope.Global.String(), - WorkerGeneratedAuthToken: &wrapperspb.StringValue{Value: fetchReqFn()}, - WorkerProvidedConfiguration: &pb.WorkerProvidedConfiguration{}, - }, - }, - wantErr: true, - wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), - wantErrContains: globals.WorkerProvidedConfigurationField, - }, { name: "invalid-authorized-actions", service: testSrv, @@ -1131,6 +1239,7 @@ func TestCreateWorkerLed(t *testing.T) { Name: &wrapperspb.StringValue{Value: "success"}, Description: &wrapperspb.StringValue{Value: "success-description"}, Version: 1, + Type: PkiWorkerType, }, }, }, diff --git a/internal/daemon/worker/status.go b/internal/daemon/worker/status.go index aaeffe710..9d312a6d7 100644 --- a/internal/daemon/worker/status.go +++ b/internal/daemon/worker/status.go @@ -157,10 +157,11 @@ func (w *Worker) sendWorkerStatus(cancelCtx context.Context) { result, err := client.Status(statusCtx, &pbs.StatusRequest{ Jobs: activeJobs, WorkerStatus: &servers.ServerWorkerStatus{ - Name: w.conf.RawConfig.Worker.Name, - Address: w.conf.RawConfig.Worker.PublicAddr, - Tags: tags, - KeyId: keyId, + Name: w.conf.RawConfig.Worker.Name, + Description: w.conf.RawConfig.Worker.Description, + Address: w.conf.RawConfig.Worker.PublicAddr, + Tags: tags, + KeyId: keyId, }, UpdateTags: w.updateTags.Load(), }) diff --git a/internal/db/schema/migrations/oss/postgres/99/01_domain_types.up.sql b/internal/db/schema/migrations/oss/postgres/32/01_domain_types.up.sql similarity index 100% rename from internal/db/schema/migrations/oss/postgres/99/01_domain_types.up.sql rename to internal/db/schema/migrations/oss/postgres/32/01_domain_types.up.sql diff --git a/internal/db/schema/migrations/oss/postgres/99/02_worker_controller_tables.up.sql b/internal/db/schema/migrations/oss/postgres/32/02_worker_controller_tables.up.sql similarity index 60% rename from internal/db/schema/migrations/oss/postgres/99/02_worker_controller_tables.up.sql rename to internal/db/schema/migrations/oss/postgres/32/02_worker_controller_tables.up.sql index f2ff45a45..e67230adb 100644 --- a/internal/db/schema/migrations/oss/postgres/99/02_worker_controller_tables.up.sql +++ b/internal/db/schema/migrations/oss/postgres/32/02_worker_controller_tables.up.sql @@ -27,64 +27,73 @@ create trigger controller_update_time_column before update on server_controller -- Worker table takes the place of the server table. -- instead of the private_id we use a wt_public_id field named public_id since -- workers will now be exposed as resources in boundary. + +create table server_worker_type_enm ( + name text primary key + constraint only_predefined_types_allowed + check ( + name in ( + 'pki', + 'kms' + ) + ) +); +comment on table server_worker_type_enm is + 'server_worker_type_enm is an enumeration table for worker types. ' + 'It contains rows for representing the pki and kms types.'; + +insert into server_worker_type_enm (name) +values + ('pki'), + ('kms'); + create table server_worker ( public_id wt_public_id primary key, scope_id wt_scope_id not null references iam_scope_global(scope_id) on delete cascade on update cascade, - description wt_description, - name wt_name unique, - -- The address can be null since it is an optional value from the API. - address wt_network_address, + description wt_description + constraint description_only_has_printable_characters + check (description is null or description !~ '[^[:print:]]'), + name wt_name -- server_worker_scope_id_name_uq defines an appropriate uniqueness constraint for name + constraint worker_name_must_be_set_by_status + check ( + type != 'kms' or name is not null + ) + constraint name_must_be_lowercase + check (name is null or lower(trim(name)) = name) + constraint name_only_has_printable_characters + check (name is null or name !~ '[^[:print:]]'), + address wt_network_address + constraint address_must_be_set_by_status + check ( + -- address can be null only no status update has been received yet. + (last_status_time is not null and address is not null) + or + (last_status_time is null and address is null) + ), create_time wt_timestamp, update_time wt_timestamp, version wt_version, - last_status_time timestamp with time zone, - constraint last_status_time_not_before_create_time - check (last_status_time >= create_time), - -- This is the calculated address that the worker reports it is reachable on. - -- This must be set if the worker has ever received a status update. - worker_reported_address wt_network_address - constraint worker_reported_address_must_be_set_by_status - check ( - (last_status_time is null and worker_reported_address is null) - or - (last_status_time is not null and worker_reported_address is not null) - ), - -- This is the name that the worker reports in it's status updates. - worker_reported_name wt_name - constraint worker_reported_name_must_be_set_by_status - check ( - (last_status_time is null and worker_reported_name is null) - or - (last_status_time is not null and worker_reported_name is not null) - or - (last_status_time is not null and worker_reported_key_id is not null) - ) - constraint worker_reported_name_must_be_lowercase - check (lower(trim(worker_reported_name)) = worker_reported_name) - constraint worker_reported_name_only_has_printable_characters - check (worker_reported_name !~ '[^[:print:]]'), - worker_reported_key_id text - constraint worker_reported_key_id_must_be_set_by_status - check ( - (last_status_time is null and worker_reported_key_id is null) - or - (last_status_time is not null and worker_reported_name is not null) - or - (last_status_time is not null and worker_reported_key_id is not null) - ), + type text not null + constraint server_worker_type_enm_fkey + references server_worker_type_enm (name) + on delete restrict + on update cascade, + last_status_time timestamp with time zone + constraint last_status_time_not_before_create_time + check (last_status_time >= create_time) + constraint last_status_time_always_set_for_kms + check (type != 'kms' or last_status_time is not null), constraint server_worker_scope_id_name_uq - unique(scope_id, name), - constraint server_worker_scope_id_worker_reported_name_uq - unique(scope_id, worker_reported_name) + unique(scope_id, name) ); comment on table server_worker is 'server_worker is a table where each row represents a Boundary worker.'; create trigger immutable_columns before update on server_worker - for each row execute procedure immutable_columns('public_id', 'scope_id', 'create_time'); + for each row execute procedure immutable_columns('public_id', 'scope_id', 'type', 'create_time'); create trigger default_create_time_column before insert on server_worker for each row execute procedure default_create_time(); @@ -95,38 +104,78 @@ create trigger worker_insert_time_column before insert on server_worker create trigger worker_update_time_column before update on server_worker for each row execute procedure update_time_column(); -create trigger update_version_column after update of version, description, name, address on server_worker +-- fixme: we should only update the version column when type = 'pki', but that +-- can be deferred +create trigger update_version_column after update of version, description, name on server_worker for each row execute procedure update_version_column(); -create function update_server_worker_update_last_status_time_column() +create function immutable_kms_name() returns trigger as $$ begin - new.last_status_time = now(); + if old.type = 'kms' and new.name is distinct from old.name then + raise exception 'immutable column for kms worker: server_worker.name' using + errcode = '23601', + schema = tg_table_schema, + table = tg_table_name, + column = 'name'; + end if; return new; end; $$ language plpgsql; -comment on function update_server_worker_update_last_status_time_column is - 'function used to update the last_status_time column in server_worker to now'; +comment on function immutable_kms_name is + 'function used in before update triggers to make name column immutable for kms workers'; -create trigger update_server_worker_last_status_time_column before update of worker_reported_address, worker_reported_name on server_worker - for each row execute procedure update_server_worker_update_last_status_time_column(); +create trigger immutable_kms_name before update on server_worker + for each row execute procedure immutable_kms_name(); -create function insert_server_worker_update_last_status_time_column() +create function update_kms_server_worker_update_last_status_time_column() returns trigger as $$ begin - if new.worker_reported_address is not null or new.worker_reported_name is not null then + if new.type = 'kms' then new.last_status_time = now(); end if; return new; end; $$ language plpgsql; -comment on function insert_server_worker_update_last_status_time_column is - 'function used to update the last_status_time column in server_worker to now'; +comment on function update_kms_server_worker_update_last_status_time_column is + 'function used to update the last_status_time column in server_worker with type kms to now'; + +create trigger update_kms_server_worker_last_status_time_column before update of address, name, description on server_worker + for each row execute procedure update_kms_server_worker_update_last_status_time_column(); + +create function update_pki_server_worker_update_last_status_time_column() + returns trigger +as $$ +begin + if new.type = 'pki' then + new.last_status_time = now(); + end if; + return new; +end; +$$ language plpgsql; +comment on function update_pki_server_worker_update_last_status_time_column is + 'function used to update the last_status_time column in server_worker with type pki to now'; + +create trigger update_pki_server_worker_last_status_time_column before update of address on server_worker + for each row execute procedure update_pki_server_worker_update_last_status_time_column(); + +create function insert_kms_server_worker_update_last_status_time_column() + returns trigger +as $$ +begin + if new.type = 'kms' then + new.last_status_time = now(); + end if; + return new; +end; +$$ language plpgsql; +comment on function insert_kms_server_worker_update_last_status_time_column is + 'function used to update the last_status_time column in server_worker with type kms to now'; create trigger insert_server_worker_last_update_time_column before insert on server_worker - for each row execute procedure insert_server_worker_update_last_status_time_column(); + for each row execute procedure insert_kms_server_worker_update_last_status_time_column(); -- Create table worker tag create table server_worker_tag_enm ( diff --git a/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql b/internal/db/schema/migrations/oss/postgres/32/03_worker_authentication.up.sql similarity index 89% rename from internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql rename to internal/db/schema/migrations/oss/postgres/32/03_worker_authentication.up.sql index 33d71f06e..b6e39a48e 100644 --- a/internal/db/schema/migrations/oss/postgres/99/03_worker_authentication.up.sql +++ b/internal/db/schema/migrations/oss/postgres/32/03_worker_authentication.up.sql @@ -112,6 +112,8 @@ create table worker_auth_authorized( on update cascade, nonce bytea -- encrypted value ); +comment on table worker_auth_authorized is + 'worker_auth_authorized is a table where each row represents key and cert data associated with an authorized worker.'; create trigger immutable_columns @@ -120,8 +122,22 @@ create trigger for each row execute procedure immutable_columns('worker_key_identifier', 'worker_id', 'worker_signing_pub_key', 'worker_encryption_pub_key', 'controller_encryption_priv_key', 'key_id', 'nonce'); -comment on table worker_auth_authorized is - 'worker_auth_authorized is a table where each row represents key and cert data associated with an authorized worker.'; +create function insert_worker_auth_authorized_type_check() + returns trigger +as $$ +begin + perform from server_worker where type = 'pki' and public_id = new.worker_id; + if not found then + raise exception 'invalid type: non pki worker cannot be authorized in worker_auth_authorized table'; + end if; + return new; +end; +$$ language plpgsql; +comment on function insert_worker_auth_authorized_type_check is + 'function used to only allow workers of type pki to be authorized'; + +create trigger insert_worker_auth_authorized_type_check before insert on worker_auth_authorized + for each row execute procedure insert_worker_auth_authorized_type_check(); create table worker_auth_certificate_bundle( root_certificate_public_key bytea not null diff --git a/internal/db/schema/migrations/oss/postgres/99/04_views.up.sql b/internal/db/schema/migrations/oss/postgres/32/04_views.up.sql similarity index 97% rename from internal/db/schema/migrations/oss/postgres/99/04_views.up.sql rename to internal/db/schema/migrations/oss/postgres/32/04_views.up.sql index 80e7bf993..c67d3ee4a 100644 --- a/internal/db/schema/migrations/oss/postgres/99/04_views.up.sql +++ b/internal/db/schema/migrations/oss/postgres/32/04_views.up.sql @@ -29,9 +29,8 @@ select w.create_time, w.update_time, w.version, - w.worker_reported_name, - w.worker_reported_address, w.last_status_time, + w.type, cc.count as active_connection_count, -- keys and tags can be any lowercase printable character so use uppercase characters as delimitors. wt.tags as api_tags, @@ -46,7 +45,6 @@ from server_worker w comment on view server_worker_aggregate is 'server_worker_aggregate contains the worker resource with its worker provided config values and its configuration and api provided tags.'; - -- Replaces the view created in 9/01. -- Remove the worker id from this view. In actuality this is almost a no-op -- because no server information was ever getting populated here due to a bug diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index 48efff41a..33c1a15d5 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -5524,11 +5524,11 @@ }, "name": { "type": "string", - "description": "Optional name for identification purposes." + "description": "Optional name for identification purposes. Can only be set through the API\nfor `pki`-type workers; read-only for `kms`-type workers." }, "description": { "type": "string", - "description": "Optional user-set description for identification purposes." + "description": "Optional user-set description for identification purposes. Can only be set\nthrough the API for `pki`-type workers; read-only for `kms`-type workers." }, "created_time": { "type": "string", @@ -5549,22 +5549,7 @@ }, "address": { "type": "string", - "description": "The address that this worker is reachable at." - }, - "canonical_address": { - "type": "string", - "description": "Output only. This is the address used by authorized session. The value\nis the same as the address field if set. Otherwise it uses the address the\nworker reports.", - "readOnly": true - }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "object" - } - }, - "description": "Output only. The tags attached to this worker.", + "description": "Output only. The address that this worker is reachable at, as sourced from\nthe worker's configuration file.", "readOnly": true }, "canonical_tags": { @@ -5575,7 +5560,18 @@ "type": "object" } }, - "description": "Output only. The deduplicated union of the tags reported by the worker and\nthe tags added through the user facing api. This is used when applying\nworker filters.", + "description": "Output only. The deduplicated union of the tags reported by the worker from\nits configuration and any tags added through other means. This is used\nwhen applying worker filters.", + "readOnly": true + }, + "config_tags": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "object" + } + }, + "description": "Output only. The tags set in the worker's configuration file.", "readOnly": true }, "last_status_time": { @@ -5584,11 +5580,6 @@ "description": "Output only. The time this worker daemon last reported its status.", "readOnly": true }, - "worker_provided_configuration": { - "$ref": "#/definitions/controller.api.resources.workers.v1.WorkerProvidedConfiguration", - "description": "Output only. The set of information the worker daemon has reported about\nitself.", - "readOnly": true - }, "worker_generated_auth_token": { "type": "string", "title": "worker_generated_auth_token is input only. Supports the worker led node\nenrollment flow where this credentials token is produced by a worker. This\ntoken is a base58 encoded types.FetchNodeCredentialsRequest from\nhttps://github.com/hashicorp/nodeenrollment" @@ -5599,6 +5590,11 @@ "description": "Output only. The number of connections that this worker is currently handling.", "readOnly": true }, + "type": { + "type": "string", + "description": "Output only. The type of the worker, denoted by how it authenticates: `pki`\nor `kms`.", + "readOnly": true + }, "authorized_actions": { "type": "array", "items": { @@ -5610,33 +5606,6 @@ }, "title": "Worker contains all fields related to a Worker resource" }, - "controller.api.resources.workers.v1.WorkerProvidedConfiguration": { - "type": "object", - "properties": { - "address": { - "type": "string", - "description": "Output only. The address the worker daemon reports itself as reachable at.", - "readOnly": true - }, - "name": { - "type": "string", - "description": "Output only. The name the worker daemon reports itself having.", - "readOnly": true - }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "array", - "items": { - "type": "object" - } - }, - "description": "Output only. The tags reporteed by the worker daemon.", - "readOnly": true - } - }, - "description": "WorkerProvidedConfiguration contains configuration values reported by the worker daemon." - }, "controller.api.services.v1.AddGroupMembersResponse": { "type": "object", "properties": { diff --git a/internal/proto/controller/api/resources/workers/v1/worker.proto b/internal/proto/controller/api/resources/workers/v1/worker.proto index ec1bbfa86..9119a6cc4 100644 --- a/internal/proto/controller/api/resources/workers/v1/worker.proto +++ b/internal/proto/controller/api/resources/workers/v1/worker.proto @@ -10,18 +10,6 @@ import "google/protobuf/wrappers.proto"; option go_package = "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/workers;workers"; -// WorkerProvidedConfiguration contains configuration values reported by the worker daemon. -message WorkerProvidedConfiguration { - // Output only. The address the worker daemon reports itself as reachable at. - string address = 10; - - // Output only. The name the worker daemon reports itself having. - string name = 20; - - // Output only. The tags reporteed by the worker daemon. - map tags = 40; -} - // Worker contains all fields related to a Worker resource message Worker { // Output only. The ID of the User. @@ -33,7 +21,8 @@ message Worker { // Output only. Scope information for this resource. resources.scopes.v1.ScopeInfo scope = 30; - // Optional name for identification purposes. + // Optional name for identification purposes. Can only be set through the API + // for `pki`-type workers; read-only for `kms`-type workers. google.protobuf.StringValue name = 40 [ (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { @@ -42,7 +31,8 @@ message Worker { } ]; // @gotags: `class:"sensitive"` - // Optional user-set description for identification purposes. + // Optional user-set description for identification purposes. Can only be set + // through the API for `pki`-type workers; read-only for `kms`-type workers. google.protobuf.StringValue description = 50 [ (custom_options.v1.generate_sdk_option) = true, (custom_options.v1.mask_mapping) = { @@ -61,34 +51,20 @@ message Worker { // The mutation will fail if the version does not match the latest known good version. uint32 version = 80; // @gotags: `class:"public"` - // The address that this worker is reachable at. - google.protobuf.StringValue address = 90 [ - (custom_options.v1.generate_sdk_option) = true, - (custom_options.v1.mask_mapping) = { - this: "address" - that: "address" - } - ]; // @gotags: `class:"public"` + // Output only. The address that this worker is reachable at, as sourced from + // the worker's configuration file. + string address = 90; // @gotags: `class:"public"` - // Output only. This is the address used by authorized session. The value - // is the same as the address field if set. Otherwise it uses the address the - // worker reports. - string canonical_address = 100 [json_name = "canonical_address"]; // @gotags: `class:"public"` - - // Output only. The tags attached to this worker. - map tags = 110; // @gotags: `class:"public"` - - // Output only. The deduplicated union of the tags reported by the worker and - // the tags added through the user facing api. This is used when applying - // worker filters. + // Output only. The deduplicated union of the tags reported by the worker from + // its configuration and any tags added through other means. This is used + // when applying worker filters. map canonical_tags = 120 [json_name = "canonical_tags"]; // @gotags: `class:"public"` - // Output only. The time this worker daemon last reported its status. - google.protobuf.Timestamp last_status_time = 130 [json_name = "last_status_time"]; // @gotags: `class:"public"` + // Output only. The tags set in the worker's configuration file. + map config_tags = 130 [json_name = "config_tags"]; // @gotags: `class:"public"` - // Output only. The set of information the worker daemon has reported about - // itself. - WorkerProvidedConfiguration worker_provided_configuration = 140 [json_name = "worker_provided_configuration"]; + // Output only. The time this worker daemon last reported its status. + google.protobuf.Timestamp last_status_time = 140 [json_name = "last_status_time"]; // @gotags: `class:"public"` // worker_generated_auth_token is input only. Supports the worker led node // enrollment flow where this credentials token is produced by a worker. This @@ -99,6 +75,10 @@ message Worker { // Output only. The number of connections that this worker is currently handling. google.protobuf.UInt32Value active_connection_count = 160 [json_name = "active_connection_count"]; // @gotags: `class:"public"` + // Output only. The type of the worker, denoted by how it authenticates: `pki` + // or `kms`. + string type = 170; + // Output only. The available actions on this resource for the requester. repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: `class:"public"` } diff --git a/internal/proto/controller/servers/v1/servers.proto b/internal/proto/controller/servers/v1/servers.proto index 33b06d696..2b2ac63cd 100644 --- a/internal/proto/controller/servers/v1/servers.proto +++ b/internal/proto/controller/servers/v1/servers.proto @@ -18,6 +18,9 @@ message ServerWorkerStatus { // Name of the resource (optional) string name = 20; // @gotags: `class:"public"` + // Description of the resource (optional) + string description = 25; // @gotags: `class:"public"` + // Address for the worker. This must be set. string address = 30; // @gotags: `class:"public"` diff --git a/internal/proto/controller/storage/servers/store/v1/worker.proto b/internal/proto/controller/storage/servers/store/v1/worker.proto index 0a160a87e..20c83d8a3 100644 --- a/internal/proto/controller/storage/servers/store/v1/worker.proto +++ b/internal/proto/controller/storage/servers/store/v1/worker.proto @@ -29,10 +29,7 @@ message Worker { // Address for the worker. This is optional. // @inject_tag: `gorm:"default:null"` - string address = 40 [(custom_options.v1.mask_mapping) = { - this: "address" - that: "address" - }]; + string address = 40; // The create_time is set by the database. // @inject_tag: `gorm:"default:current_timestamp"` @@ -50,22 +47,13 @@ message Worker { // @inject_tag: `gorm:"default:null"` uint32 version = 80; - // Name of the resource (optional) - // @inject_tag: `gorm:"default:null"` - string worker_reported_name = 90; - - // Address for the worker. This must be set when the worker has received - // at least 1 status update fromt he worker daemon. - // @inject_tag: `gorm:"default:null"` - string worker_reported_address = 100; - // The last_status_time is the last time a worker daemon sent a status update. // @inject_tag: `gorm:"default:null"` timestamp.v1.Timestamp last_status_time = 110; - // keyId reported by a PKI worker (optional) - // @inject_tag: `gorm:"default:null"` - string worker_reported_key_id = 120; + // The type of the worker, denoted by how it authenticates: pki or kms. + // @inject_tag: `gorm:"not_null"` + string type = 130; } // WorkerTag is a tag for a worker. The primary key is comprised of the diff --git a/internal/servers/options.go b/internal/servers/options.go index 052ed55f5..b2a883624 100644 --- a/internal/servers/options.go +++ b/internal/servers/options.go @@ -36,6 +36,8 @@ type options struct { withNonce []byte withNewIdFunc func(context.Context) (string, error) withFetchNodeCredentialsRequest *types.FetchNodeCredentialsRequest + withTestPkiWorkerAuthorized bool + withTestPkiWorkerKeyId *string } func getDefaultOptions() options { @@ -151,3 +153,13 @@ func WithFetchNodeCredentialsRequest(req *types.FetchNodeCredentialsRequest) Opt o.withFetchNodeCredentialsRequest = req } } + +// WithTestPkiWorkerAuthorizedKeyId should only be used in tests. +// It specifies that the test worker should be authorized when returned and +// assigns the key id for that worker to the string pointer in this option. +func WithTestPkiWorkerAuthorizedKeyId(id *string) Option { + return func(o *options) { + o.withTestPkiWorkerAuthorized = true + o.withTestPkiWorkerKeyId = id + } +} diff --git a/internal/servers/options_test.go b/internal/servers/options_test.go index a1ef9ad8e..d5839c21d 100644 --- a/internal/servers/options_test.go +++ b/internal/servers/options_test.go @@ -145,4 +145,17 @@ func Test_GetOpts(t *testing.T) { runtime.FuncForPC(reflect.ValueOf(testOpts.withNewIdFunc).Pointer()).Name(), ) }) + t.Run("WithTestPkiWorkerAuthorizedKeyId", func(t *testing.T) { + assert := assert.New(t) + testOpts := getDefaultOptions() + + var keyId string + opts := getOpts(WithTestPkiWorkerAuthorizedKeyId(&keyId)) + testOpts = getDefaultOptions() + testOpts.withTestPkiWorkerAuthorized = true + testOpts.withTestPkiWorkerKeyId = &keyId + testOpts.withNewIdFunc = nil + opts.withNewIdFunc = nil + assert.Equal(opts, testOpts) + }) } diff --git a/internal/servers/public_ids.go b/internal/servers/public_ids.go index 16d9a7829..0658c36f2 100644 --- a/internal/servers/public_ids.go +++ b/internal/servers/public_ids.go @@ -19,3 +19,15 @@ func newWorkerId(ctx context.Context) (string, error) { } return id, nil } + +// newWorkerIdFromScopeAndName generates a predictable public id based on the +// scope and the worker name. This should only be used on kms workers at +// upsert time. +func newWorkerIdFromScopeAndName(ctx context.Context, scope, name string) (string, error) { + const op = "servers.newWorkerIdFromScopeAndName" + id, err := db.NewPublicId(WorkerPrefix, db.WithPrngValues([]string{scope, name})) + if err != nil { + return "", errors.Wrap(ctx, err, "servers.newWorkerId") + } + return id, nil +} diff --git a/internal/servers/repository_worker.go b/internal/servers/repository_worker.go index 836509f3f..e652bc317 100644 --- a/internal/servers/repository_worker.go +++ b/internal/servers/repository_worker.go @@ -57,19 +57,32 @@ func (r *Repository) DeleteWorker(ctx context.Context, publicId string, _ ...Opt return rowsDeleted, nil } -// LookupWorkerByWorkerReportedName returns the worker which has had a status update -// where the worker has reported this name. This is different from the name -// on the resource itself which is set over the API. In the event that no -// worker is found that matches then nil, nil will be returned. -func (r *Repository) LookupWorkerByWorkerReportedName(ctx context.Context, name string) (*Worker, error) { - const op = "servers.(Repository).LookupWorkerByWorkerReportedName" +// LookupWorkerByName returns the worker with the provided name. In the event +// that no worker is found that matches then nil, nil will be returned. +func (r *Repository) LookupWorkerByName(ctx context.Context, name string) (*Worker, error) { + const op = "servers.(Repository).LookupWorkerByName" switch { case name == "": return nil, errors.New(ctx, errors.InvalidParameter, op, "name is empty") } + w, err := lookupWorkerByName(ctx, r.reader, name) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + return w, nil +} + +func lookupWorkerByName(ctx context.Context, reader db.Reader, name string) (*Worker, error) { + const op = "servers.lookupWorkerByName" + switch { + case isNil(reader): + return nil, errors.New(ctx, errors.InvalidParameter, op, "reader is nil") + case name == "": + return nil, errors.New(ctx, errors.InvalidParameter, op, "name is empty") + } wAgg := &workerAggregate{} - err := r.reader.LookupWhere(ctx, &wAgg, "worker_reported_name = ?", []interface{}{name}) + err := reader.LookupWhere(ctx, &wAgg, "name = ?", []interface{}{name}) if err != nil { if errors.IsNotFoundError(err) { return nil, nil @@ -83,8 +96,8 @@ func (r *Repository) LookupWorkerByWorkerReportedName(ctx context.Context, name return w, nil } -func (r *Repository) LookupWorkerIdByWorkerReportedKeyId(ctx context.Context, keyId string) (string, error) { - const op = "servers.(Repository).LookupWorkerIdByWorkerReportedKeyId" +func (r *Repository) LookupWorkerIdByKeyId(ctx context.Context, keyId string) (string, error) { + const op = "servers.(Repository).LookupWorkerIdByKeyId" switch { case keyId == "": return "", errors.New(ctx, errors.InvalidParameter, op, "keyId is empty") @@ -200,62 +213,51 @@ func (r *Repository) ListWorkers(ctx context.Context, scopeIds []string, opt ... return workers, nil } -// UpsertWorkerStatus creates a new worker if one with the provided public id -// doesn't already exist. If it does, UpsertWorkerStatus updates the worker -// status. This returns the Worker object with the updated WorkerStatus applied. -// The WithPublicId and WithUpdateTags options are the only ones used. All others are ignored. +// UpsertWorkerStatus will update the address and last status time for a worker. +// If the worker is a kms worker that hasn't been seen yet, it'll attempt to +// create a new one, but will return an error if another worker (kms or other) +// has the same name. This returns the Worker object with the changes applied. +// The WithPublicId, WithKeyId, and WithUpdateTags options are +// the only ones used. All others are ignored. // Workers are intentionally not oplogged. func (r *Repository) UpsertWorkerStatus(ctx context.Context, worker *Worker, opt ...Option) (*Worker, error) { const op = "servers.UpsertWorkerStatus" + opts := getOpts(opt...) switch { case worker == nil: return nil, errors.New(ctx, errors.InvalidParameter, op, "worker is nil") - case worker.GetWorkerReportedAddress() == "": + case worker.GetAddress() == "": return nil, errors.New(ctx, errors.InvalidParameter, op, "worker reported address is empty") case worker.ScopeId == "": return nil, errors.New(ctx, errors.InvalidParameter, op, "scope id is empty") case worker.PublicId != "": return nil, errors.New(ctx, errors.InvalidParameter, op, "worker id is not empty") - case worker.GetWorkerReportedName() == "" && worker.WorkerReportedKeyId == "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "worker keyId and reported name are both empty; at least one is required") - case len(worker.apiTags) > 0: - return nil, errors.New(ctx, errors.InvalidParameter, op, "api tags is not empty") + case worker.GetName() == "" && opts.withKeyId == "": + return nil, errors.New(ctx, errors.InvalidParameter, op, "worker keyId and reported name are both empty; one is required") + case worker.GetName() != "" && opts.withKeyId != "": + return nil, errors.New(ctx, errors.InvalidParameter, op, "worker keyId and reported name are both set; no more than one is allowed") } - // Only retain the worker reported fields. - worker = NewWorkerForStatus(worker.GetScopeId(), - WithName(worker.GetWorkerReportedName()), - WithAddress(worker.GetWorkerReportedAddress()), - WithWorkerTags(worker.configTags...), - WithKeyId(worker.WorkerReportedKeyId)) - - opts := getOpts(opt...) - + var workerId string var err error switch { case opts.withPublicId != "": - worker.PublicId = opts.withPublicId - case worker.WorkerReportedKeyId != "": - workerId, err := r.LookupWorkerIdByWorkerReportedKeyId(ctx, worker.WorkerReportedKeyId) + workerId = opts.withPublicId + case opts.withKeyId != "": + workerId, err = r.LookupWorkerIdByKeyId(ctx, opts.withKeyId) if err != nil || workerId == "" { return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error finding worker by keyId")) } - worker.PublicId = workerId default: - // Attempt to find workerId by name. If not found, generate an id - w, err := r.LookupWorkerByWorkerReportedName(ctx, worker.GetWorkerReportedName()) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error finding worker by name")) - } - if w != nil { - worker.PublicId = w.PublicId - } else { - workerId, err := newWorkerId(ctx) - if err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error error generating worker id")) - } - worker.PublicId = workerId + // generating the worker id based off of the scope and name ensures + // that if 2 kms workers are making requests with the same name they + // are treated as the same worker. Allowing this only for kms workers + // also ensures that we maintain the unique name constraint between pki + // workers and kms workers. + workerId, err = newWorkerIdFromScopeAndName(ctx, worker.GetScopeId(), worker.GetName()) + if err != nil || workerId == "" { + return nil, errors.Wrap(ctx, err, op, errors.WithMsg("error creating a worker id")) } } @@ -266,13 +268,52 @@ func (r *Repository) UpsertWorkerStatus(ctx context.Context, worker *Worker, opt db.ExpBackoff{}, func(reader db.Reader, w db.Writer) error { worker := worker.clone() - workerCreateConflict := &db.OnConflict{ - Target: db.Columns{"public_id"}, - Action: append(db.SetColumns([]string{"worker_reported_name", "worker_reported_address"}), - db.SetColumnValues(map[string]interface{}{"last_status_time": "now()"})...), - } - if err := w.Create(ctx, worker, db.WithOnConflict(workerCreateConflict)); err != nil { - return errors.Wrap(ctx, err, op, errors.WithMsg("error creating a worker")) + worker.PublicId = workerId + switch { + case opts.withKeyId != "": + // This case goes first in case we want to relax the restriction + // around both name and key ID being supplied to account for + // e.g. config processing bugs. In that case, a key ID being + // supplied should be a clear indicator that we are working with + // a PKI worker, and a lack of one a clear indication we are + // working with a KMS worker. + // + // Note: unlike in the below case, this purposefully leaves out + // "description" since we want description changes for PKI-based + // workers to come via API only. We can't really guard on this + // in the DB so we need to be sure to not include it here. + n, err := w.Update(ctx, worker, []string{"address"}, nil) + if err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("unable to update status of pki worker")) + } + switch n { + case 0: + return errors.New(ctx, errors.RecordNotFound, op, fmt.Sprintf("failed to find worker with key id %q", opts.withKeyId)) + case 1: + break + default: + return errors.New(ctx, errors.MultipleRecords, op, fmt.Sprintf("multiple records found when updating worker with id %q", worker.GetPublicId())) + } + + case worker.GetName() != "": + worker.Type = KmsWorkerType.String() + workerCreateConflict := &db.OnConflict{ + Target: db.Columns{"public_id"}, + Action: append(db.SetColumns([]string{"description", "address"}), + db.SetColumnValues(map[string]interface{}{"last_status_time": "now()"})...), + } + var withRowsAffected int64 + err := w.Create(ctx, worker, db.WithOnConflict(workerCreateConflict), db.WithReturnRowsAffected(&withRowsAffected), + // The intent of this WithWhere option is to operate with the OnConflict such that the action + // taken by the OnConflict only applies if the conflict is on a row that is returned by this where + // statement, otherwise it should error out. + db.WithWhere("server_worker.type = 'kms'")) + switch { + case err != nil: + return errors.Wrap(ctx, err, op, errors.WithMsg("error creating a worker")) + case withRowsAffected == 0: + return errors.New(ctx, errors.NotUnique, op, "error updating worker") + } } // If we've been told to update tags, we need to clean out old @@ -280,7 +321,9 @@ func (r *Repository) UpsertWorkerStatus(ctx context.Context, worker *Worker, opt // delete all tags for the given worker, then add the new ones // we've been sent. if opts.withUpdateTags { - setWorkerTags(ctx, w, worker.GetPublicId(), ConfigurationTagSource, worker.configTags) + if err := setWorkerTags(ctx, w, worker.GetPublicId(), ConfigurationTagSource, worker.inputTags); err != nil { + return errors.Wrap(ctx, err, op, errors.WithMsg("error setting worker tags")) + } } wAgg := &workerAggregate{PublicId: worker.GetPublicId()} @@ -355,9 +398,8 @@ func setWorkerTags(ctx context.Context, w db.Writer, id string, ts TagSource, ta // the path then an error is returned. func (r *Repository) UpdateWorker(ctx context.Context, worker *Worker, version uint32, fieldMaskPaths []string, opt ...Option) (*Worker, int, error) { const ( - nameField = "name" - descField = "description" - addressField = "address" + nameField = "name" + descField = "description" ) const op = "servers.(Repository).UpdateWorker" switch { @@ -373,7 +415,6 @@ func (r *Repository) UpdateWorker(ctx context.Context, worker *Worker, version u switch { case strings.EqualFold(nameField, f): case strings.EqualFold(descField, f): - case strings.EqualFold(addressField, f): default: return nil, db.NoRowsAffected, errors.New(ctx, errors.InvalidFieldMask, op, fmt.Sprintf("invalid field mask: %s", f)) } @@ -382,9 +423,8 @@ func (r *Repository) UpdateWorker(ctx context.Context, worker *Worker, version u var dbMask, nullFields []string dbMask, nullFields = dbcommon.BuildUpdatePaths( map[string]interface{}{ - nameField: worker.Name, - descField: worker.Description, - addressField: worker.Address, + nameField: worker.Name, + descField: worker.Description, }, fieldMaskPaths, nil, @@ -448,10 +488,8 @@ func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Op return nil, errors.New(ctx, errors.InvalidParameter, op, "missing scope id") case worker.ScopeId != scope.Global.String(): return nil, errors.New(ctx, errors.InvalidParameter, op, fmt.Sprintf("scope id must be %q", scope.Global.String())) - case worker.WorkerReportedAddress != "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "worker reported address is not empty") - case worker.WorkerReportedName != "": - return nil, errors.New(ctx, errors.InvalidParameter, op, "worker reported name is not empty") + case worker.Address != "": + return nil, errors.New(ctx, errors.InvalidParameter, op, "address is not empty") case worker.LastStatusTime != nil: return nil, errors.New(ctx, errors.InvalidParameter, op, "last status time is not nil") } @@ -476,7 +514,6 @@ func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Op if err != nil { return nil, errors.Wrap(ctx, err, op) } - } var returnedWorker *Worker @@ -486,6 +523,7 @@ func (r *Repository) CreateWorker(ctx context.Context, worker *Worker, opt ...Op db.ExpBackoff{}, func(read db.Reader, w db.Writer) error { returnedWorker = worker.clone() + returnedWorker.Type = PkiWorkerType.String() if err := w.Create( ctx, returnedWorker, diff --git a/internal/servers/repository_worker_test.go b/internal/servers/repository_worker_test.go index 73df90403..217a255c8 100644 --- a/internal/servers/repository_worker_test.go +++ b/internal/servers/repository_worker_test.go @@ -2,7 +2,6 @@ package servers_test import ( "context" - "crypto/rand" "fmt" "strings" "testing" @@ -21,8 +20,6 @@ import ( "github.com/hashicorp/boundary/internal/types/scope" "github.com/hashicorp/go-dbw" "github.com/hashicorp/go-kms-wrapping/extras/kms/v2/migrations" - "github.com/hashicorp/nodeenrollment" - "github.com/hashicorp/nodeenrollment/registration" "github.com/hashicorp/nodeenrollment/rotation" "github.com/hashicorp/nodeenrollment/storage/file" "github.com/hashicorp/nodeenrollment/types" @@ -54,7 +51,7 @@ func TestDeleteWorker(t *testing.T) { { name: "valid", args: args{ - worker: servers.TestWorker(t, conn, wrapper), + worker: servers.TestKmsWorker(t, conn, wrapper), }, wantRowsDeleted: 1, wantErr: false, @@ -108,7 +105,7 @@ func TestDeleteWorker(t *testing.T) { } } -func TestLookupWorkerByWorkerReportedName(t *testing.T) { +func TestLookupWorkerByName(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) wrapper := db.TestWrapper(t) @@ -117,14 +114,14 @@ func TestLookupWorkerByWorkerReportedName(t *testing.T) { require.NoError(t, err) ctx := context.Background() - w := servers.TestWorker(t, conn, wrapper) + w := servers.TestKmsWorker(t, conn, wrapper) t.Run("success", func(t *testing.T) { - got, err := repo.LookupWorkerByWorkerReportedName(ctx, w.GetWorkerReportedName()) + got, err := repo.LookupWorkerByName(ctx, w.GetName()) require.NoError(t, err) assert.Empty(t, cmp.Diff(w.Worker, got.Worker, protocmp.Transform())) }) t.Run("not found", func(t *testing.T) { - got, err := repo.LookupWorkerByWorkerReportedName(ctx, "unknown_name") + got, err := repo.LookupWorkerByName(ctx, "unknown_name") require.NoError(t, err) assert.Nil(t, got) }) @@ -134,14 +131,14 @@ func TestLookupWorkerByWorkerReportedName(t *testing.T) { mock.ExpectQuery(`SELECT`).WillReturnError(errors.New(context.Background(), errors.Internal, "test", "lookup-error")) r, err := servers.NewRepository(rw, rw, kms) require.NoError(t, err) - got, err := r.LookupWorkerByWorkerReportedName(ctx, w.GetWorkerReportedName()) + got, err := r.LookupWorkerByName(ctx, w.GetName()) assert.NoError(t, mock.ExpectationsWereMet()) - assert.Truef(t, errors.Match(errors.T(errors.Op("servers.(Repository).LookupWorkerByWorkerReportedName")), err), "got error %v", err) + assert.Truef(t, errors.Match(errors.T(errors.Op("servers.(Repository).LookupWorkerByName")), err), "got error %v", err) assert.Nil(t, got) }) } -func TestLookupWorkerByWorkerReportedKeyId(t *testing.T) { +func TestLookupWorkerIdByKeyId(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) wrapper := db.TestWrapper(t) @@ -149,39 +146,15 @@ func TestLookupWorkerByWorkerReportedKeyId(t *testing.T) { repo, err := servers.NewRepository(rw, rw, kmsCache) require.NoError(t, err) ctx := context.Background() - // Ensures the global scope contains a valid root key - err = kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)) - require.NoError(t, err) - - w := servers.TestWorker(t, conn, wrapper) - - rootStorage, err := servers.NewRepositoryStorage(ctx, rw, rw, kmsCache) - require.NoError(t, err) - _, err = rotation.RotateRootCertificates(ctx, rootStorage) - require.NoError(t, err) - // Create struct to pass in with workerId that will be passed along to storage - state, err := servers.AttachWorkerIdToState(ctx, w.PublicId) - require.NoError(t, err) - - // This happens on the worker - fileStorage, err := file.New(ctx) - require.NoError(t, err) - nodeCreds, err := types.NewNodeCredentials(ctx, fileStorage) - require.NoError(t, err) - // Create request using worker id - fetchReq, err := nodeCreds.CreateFetchNodeCredentialsRequest(ctx) - require.NoError(t, err) - - // The AuthorizeNode request will result in a WorkerAuth record being stored - registeredNode, err := registration.AuthorizeNode(ctx, rootStorage, fetchReq, nodeenrollment.WithState(state)) - require.NoError(t, err) + var workerKeyId string + w := servers.TestPkiWorker(t, conn, wrapper, servers.WithTestPkiWorkerAuthorizedKeyId(&workerKeyId)) t.Run("success", func(t *testing.T) { - got, err := repo.LookupWorkerIdByWorkerReportedKeyId(ctx, registeredNode.Id) + got, err := repo.LookupWorkerIdByKeyId(ctx, workerKeyId) require.NoError(t, err) assert.Equal(t, w.PublicId, got) }) t.Run("not found", func(t *testing.T) { - got, err := repo.LookupWorkerIdByWorkerReportedKeyId(ctx, "unknown_key") + got, err := repo.LookupWorkerIdByKeyId(ctx, "unknown_key") require.NoError(t, err) assert.Empty(t, got) }) @@ -191,9 +164,9 @@ func TestLookupWorkerByWorkerReportedKeyId(t *testing.T) { mock.ExpectQuery(`SELECT`).WillReturnError(errors.New(context.Background(), errors.Internal, "test", "lookup-error")) r, err := servers.NewRepository(rw, rw, kmsCache) require.NoError(t, err) - got, err := r.LookupWorkerIdByWorkerReportedKeyId(ctx, w.GetWorkerReportedName()) + got, err := r.LookupWorkerIdByKeyId(ctx, "somekey") assert.NoError(t, mock.ExpectationsWereMet()) - assert.Truef(t, errors.Match(errors.T(errors.Op("servers.(Repository).LookupWorkerIdByWorkerReportedKeyId")), err), "got error %v", err) + assert.Truef(t, errors.Match(errors.T(errors.Op("servers.(Repository).LookupWorkerIdByKeyId")), err), "got error %v", err) assert.Empty(t, got) }) } @@ -207,21 +180,11 @@ func TestLookupWorker(t *testing.T) { require.NoError(t, err) ctx := context.Background() - w := servers.TestWorker(t, conn, wrapper, + w := servers.TestKmsWorker(t, conn, wrapper, servers.WithName("name"), servers.WithDescription("description"), servers.WithAddress("address"), servers.WithWorkerTags(&servers.Tag{"key", "val"})) - w, err = repo.UpsertWorkerStatus(context.Background(), - servers.NewWorkerForStatus(w.GetScopeId(), - servers.WithName(w.GetWorkerReportedName()), - servers.WithAddress(w.GetWorkerReportedAddress()), - servers.WithWorkerTags(&servers.Tag{ - Key: "config", - Value: "test", - })), - servers.WithUpdateTags(true), - servers.WithPublicId(w.GetPublicId())) require.NoError(t, err) sessRepo, err := session.NewRepository(rw, rw, kms) @@ -261,12 +224,10 @@ func TestLookupWorker(t *testing.T) { require.NoError(t, err) assert.Empty(t, cmp.Diff(w, got, protocmp.Transform())) assert.Equal(t, uint32(3), got.ActiveConnectionCount()) - assert.Equal(t, map[string][]string{"key": {"val"}}, got.GetApiTags()) - assert.Equal(t, map[string][]string{"config": {"test"}}, got.GetConfigTags()) assert.Equal(t, map[string][]string{ - "key": {"val"}, - "config": {"test"}, + "key": {"val"}, }, got.CanonicalTags()) + assert.Equal(t, got.CanonicalTags(), got.GetConfigTags()) }) t.Run("not found", func(t *testing.T) { got, err := repo.LookupWorker(ctx, "w_unknownid") @@ -290,35 +251,83 @@ func TestUpsertWorkerStatus(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) wrapper := db.TestWrapper(t) - kms := kms.TestKms(t, conn, wrapper) - repo, err := servers.NewRepository(rw, rw, kms) + kmsCache := kms.TestKms(t, conn, wrapper) + repo, err := servers.NewRepository(rw, rw, kmsCache) require.NoError(t, err) + ctx := context.Background() - wStatus1 := servers.NewWorkerForStatus(scope.Global.String(), - servers.WithAddress("address"), servers.WithName("config_name1")) - worker, err := repo.UpsertWorkerStatus(ctx, wStatus1) - require.NoError(t, err) - { + t.Run("create an initial kms worker and update status", func(t *testing.T) { + wStatus1 := servers.NewWorker(scope.Global.String(), + servers.WithAddress("address"), servers.WithName("config_name1"), + servers.WithDescription("kms_description1")) + worker, err := repo.UpsertWorkerStatus(ctx, wStatus1) + require.NoError(t, err) + assert.True(t, strings.HasPrefix(worker.GetPublicId(), "w_")) - assert.Equal(t, wStatus1.GetWorkerReportedAddress(), worker.CanonicalAddress()) - assert.Empty(t, worker.Name) - assert.Equal(t, worker.GetLastStatusTime(), worker.UpdateTime) + assert.Equal(t, wStatus1.GetAddress(), worker.GetAddress()) + assert.Equal(t, "config_name1", worker.Name) + assert.Equal(t, "kms_description1", worker.Description) + assert.Equal(t, worker.GetLastStatusTime().AsTime(), worker.GetUpdateTime().AsTime()) assert.Equal(t, uint32(1), worker.Version) - assert.Empty(t, worker.Address) - assert.Empty(t, worker.Description) - } + assert.Equal(t, "address", worker.GetAddress()) + + // update again and see updated last status time + wStatus2 := servers.NewWorker(scope.Global.String(), + servers.WithAddress("new_address"), servers.WithName("config_name1"), + servers.WithDescription("kms_description2")) + worker, err = repo.UpsertWorkerStatus(ctx, wStatus2) + require.NoError(t, err) + assert.Greater(t, worker.GetLastStatusTime().AsTime(), worker.GetCreateTime().AsTime()) + assert.Equal(t, "config_name1", worker.Name) + assert.Equal(t, "kms_description2", worker.Description) + assert.Equal(t, worker.GetLastStatusTime().AsTime(), worker.GetUpdateTime().AsTime()) + assert.Equal(t, uint32(2), worker.Version) + assert.Equal(t, "new_address", worker.GetAddress()) + }) + + // Setup and use a pki worker + var pkiWorkerKeyId string + pkiWorker := servers.TestPkiWorker(t, conn, wrapper, servers.WithName("pki"), servers.WithDescription("pki_description1"), servers.WithTestPkiWorkerAuthorizedKeyId(&pkiWorkerKeyId)) + + t.Run("update status for pki worker", func(t *testing.T) { + wStatus1 := servers.NewWorker(scope.Global.String(), + servers.WithAddress("pki_address"), servers.WithDescription("pki_description2")) + worker, err := repo.UpsertWorkerStatus(ctx, wStatus1, servers.WithKeyId(pkiWorkerKeyId)) + require.NoError(t, err) + + assert.True(t, strings.HasPrefix(worker.GetPublicId(), "w_")) + assert.Equal(t, wStatus1.GetAddress(), worker.GetAddress()) + assert.Equal(t, "pki", worker.Name) + assert.Equal(t, "pki_description1", worker.Description) // PKI workers don't update description via status + assert.Greater(t, worker.GetLastStatusTime().AsTime(), worker.GetCreateTime().AsTime()) + assert.Equal(t, worker.GetLastStatusTime().AsTime(), worker.GetUpdateTime().AsTime()) + assert.Equal(t, uint32(1), worker.Version) + assert.Equal(t, "pki_address", worker.GetAddress()) + }) failureCases := []struct { name string repo *servers.Repository status *servers.Worker + options []servers.Option errAssert func(*testing.T, error) }{ + { + name: "conflicting name with pki", + repo: repo, + status: servers.NewWorker(scope.Global.String(), + servers.WithName(pkiWorker.GetName()), + servers.WithAddress("someaddress")), + errAssert: func(t *testing.T, err error) { + t.Helper() + assert.True(t, errors.Match(errors.T(errors.NotUnique), err), err) + }, + }, { name: "no address", repo: repo, - status: servers.NewWorkerForStatus(scope.Global.String(), + status: servers.NewWorker(scope.Global.String(), servers.WithName("worker_with_no_address")), errAssert: func(t *testing.T, err error) { t.Helper() @@ -326,10 +335,10 @@ func TestUpsertWorkerStatus(t *testing.T) { }, }, { - name: "cant specifying public id", + name: "cant specify public id", repo: repo, status: func() *servers.Worker { - w := servers.NewWorkerForStatus(scope.Global.String(), + w := servers.NewWorker(scope.Global.String(), servers.WithName("worker_with_no_address"), servers.WithAddress("workeraddress")) w.PublicId = "w_specified" @@ -341,9 +350,21 @@ func TestUpsertWorkerStatus(t *testing.T) { }, }, { - name: "no name", + name: "name and key id provided", repo: repo, - status: servers.NewWorkerForStatus(scope.Global.String(), + status: servers.NewWorker(scope.Global.String(), + servers.WithName("name and key id provided"), + servers.WithAddress("someaddress")), + options: []servers.Option{servers.WithKeyId(pkiWorkerKeyId)}, + errAssert: func(t *testing.T, err error) { + t.Helper() + assert.True(t, errors.Match(errors.T(errors.InvalidParameter), err), err) + }, + }, + { + name: "no name or key id", + repo: repo, + status: servers.NewWorker(scope.Global.String(), servers.WithAddress("no_name_address")), errAssert: func(t *testing.T, err error) { t.Helper() @@ -362,7 +383,7 @@ func TestUpsertWorkerStatus(t *testing.T) { { name: "empty scope", repo: repo, - status: servers.NewWorkerForStatus("", + status: servers.NewWorker("", servers.WithAddress("address"), servers.WithName("config_name1")), errAssert: func(t *testing.T, err error) { @@ -370,21 +391,6 @@ func TestUpsertWorkerStatus(t *testing.T) { assert.True(t, errors.Match(errors.T(errors.InvalidParameter), err)) }, }, - { - name: "providing api tags", - repo: repo, - status: func() *servers.Worker { - w := servers.NewWorker(scope.Global.String(), - servers.WithWorkerTags(&servers.Tag{Key: "test", Value: "test"})) - w.WorkerReportedAddress = "some_address" - w.WorkerReportedName = "providing api tags" - return w - }(), - errAssert: func(t *testing.T, err error) { - t.Helper() - assert.True(t, errors.Match(errors.T(errors.InvalidParameter), err)) - }, - }, { name: "database failure", repo: func() *servers.Repository { @@ -393,11 +399,11 @@ func TestUpsertWorkerStatus(t *testing.T) { mock.ExpectBegin() mock.ExpectQuery(`INSERT`).WillReturnError(errors.New(context.Background(), errors.Internal, "test", "create-error")) mock.ExpectRollback() - r, err := servers.NewRepository(rw, rw, kms) + r, err := servers.NewRepository(rw, rw, kmsCache) require.NoError(t, err) return r }(), - status: servers.NewWorkerForStatus(scope.Global.String(), + status: servers.NewWorker(scope.Global.String(), servers.WithName("database failure"), servers.WithAddress("address")), errAssert: func(t *testing.T, err error) { @@ -408,29 +414,28 @@ func TestUpsertWorkerStatus(t *testing.T) { } for _, tc := range failureCases { t.Run(fmt.Sprintf("Failures %s", tc.name), func(t *testing.T) { - _, err = tc.repo.UpsertWorkerStatus(ctx, tc.status) + _, err = tc.repo.UpsertWorkerStatus(ctx, tc.status, tc.options...) assert.Error(t, err) tc.errAssert(t, err) // Still only the original worker exists. workers, err := repo.ListWorkers(ctx, []string{scope.Global.String()}) require.NoError(t, err) - assert.Len(t, workers, 1) + assert.Len(t, workers, 2) }) } - { - anotherStatus := servers.NewWorkerForStatus(scope.Global.String(), + t.Run("add another status", func(t *testing.T) { + anotherStatus := servers.NewWorker(scope.Global.String(), servers.WithName("another_test_worker"), servers.WithAddress("address")) _, err = repo.UpsertWorkerStatus(ctx, anotherStatus) require.NoError(t, err) - { - workers, err := repo.ListWorkers(ctx, []string{scope.Global.String()}) - require.NoError(t, err) - assert.Len(t, workers, 2) - } - } + + workers, err := repo.ListWorkers(ctx, []string{scope.Global.String()}) + require.NoError(t, err) + assert.Len(t, workers, 3) + }) } func TestTagUpdatingListing(t *testing.T) { @@ -443,10 +448,10 @@ func TestTagUpdatingListing(t *testing.T) { require.NoError(err) ctx := context.Background() - worker1 := servers.TestWorker(t, conn, wrapper) - wStatus := servers.NewWorkerForStatus(scope.Global.String(), - servers.WithName(worker1.GetWorkerReportedName()), - servers.WithAddress("127.0.0.1"), + worker1 := servers.TestKmsWorker(t, conn, wrapper) + wStatus := servers.NewWorker(scope.Global.String(), + servers.WithName(worker1.GetName()), + servers.WithAddress("somethingnew"), servers.WithWorkerTags( &servers.Tag{ Key: "tag1", @@ -464,9 +469,9 @@ func TestTagUpdatingListing(t *testing.T) { assert.ElementsMatch(t, []string{"value1", "value2"}, worker1.CanonicalTags()["tag1"]) // Update without saying to update tags - wStatus = servers.NewWorkerForStatus(scope.Global.String(), - servers.WithName(worker1.GetWorkerReportedName()), - servers.WithAddress(worker1.GetWorkerReportedAddress()), + wStatus = servers.NewWorker(scope.Global.String(), + servers.WithName(worker1.GetName()), + servers.WithAddress(worker1.GetAddress()), servers.WithWorkerTags( &servers.Tag{ Key: "tag22", @@ -542,7 +547,7 @@ func TestListWorkers(t *testing.T) { w := servers.NewWorker(scope.Global.String()) db.TestDeleteWhere(t, conn, w, "true") for i := 0; i < tt.createCnt; i++ { - servers.TestWorker(t, conn, wrapper) + servers.TestKmsWorker(t, conn, wrapper) } // the purpose of these tests isn't to check liveness, so disable // liveness checking. @@ -569,18 +574,20 @@ func TestListWorkers_WithLiveness(t *testing.T) { require.NoError(err) ctx := context.Background() - worker1 := servers.TestWorker(t, conn, wrapper) - worker2 := servers.TestWorker(t, conn, wrapper) - worker3 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) + worker2 := servers.TestKmsWorker(t, conn, wrapper) + worker3 := servers.TestKmsWorker(t, conn, wrapper) // Sleep the default liveness time (15sec currently) +1s time.Sleep(time.Second * 16) // Push an upsert to the first worker so that its status has been // updated. - _, err = serversRepo.UpsertWorkerStatus(ctx, servers.NewWorkerForStatus(scope.Global.String(), - servers.WithName(worker1.GetWorkerReportedName()), - servers.WithAddress(worker1.GetWorkerReportedAddress()))) + _, err = serversRepo.UpsertWorkerStatus(ctx, + servers.NewWorker(scope.Global.String(), + servers.WithName(worker1.GetName()), + servers.WithAddress(worker1.GetAddress())), + servers.WithPublicId(worker1.GetPublicId())) require.NoError(err) requireIds := func(expected []string, actual []*servers.Worker) { @@ -605,9 +612,11 @@ func TestListWorkers_WithLiveness(t *testing.T) { requireIds([]string{worker1.GetPublicId()}, result) // Upsert second server. - _, err = serversRepo.UpsertWorkerStatus(ctx, servers.NewWorkerForStatus(scope.Global.String(), - servers.WithName(worker2.GetWorkerReportedName()), - servers.WithAddress(worker1.GetWorkerReportedAddress()))) + _, err = serversRepo.UpsertWorkerStatus(ctx, + servers.NewWorker(scope.Global.String(), + servers.WithName(worker2.GetName()), + servers.WithAddress(worker2.GetAddress())), + servers.WithPublicId(worker2.GetPublicId())) require.NoError(err) // Static liveness. Should get two, so long as this did not take @@ -641,6 +650,8 @@ func TestRepository_CreateWorker(t *testing.T) { return "", errors.New(testCtx, errors.Internal, "test", "testNewIdFn-error") } + kmsWorker := servers.TestKmsWorker(t, conn, wrapper) + rootStorage, err := servers.NewRepositoryStorage(testCtx, rw, rw, testKms) require.NoError(t, err) _, err = rotation.RotateRootCertificates(testCtx, rootStorage) @@ -739,25 +750,13 @@ func TestRepository_CreateWorker(t *testing.T) { name: "no worker reported address", setup: func() *servers.Worker { w := servers.NewWorker(scope.Global.String()) - w.WorkerReportedAddress = "foo" + w.Address = "foo" return w }, repo: testRepo, wantErr: true, wantErrIs: errors.InvalidParameter, - wantErrContains: "worker reported address is not empty", - }, - { - name: "no worker reported name", - setup: func() *servers.Worker { - w := servers.NewWorker(scope.Global.String()) - w.WorkerReportedName = "foo" - return w - }, - repo: testRepo, - wantErr: true, - wantErrIs: errors.InvalidParameter, - wantErrContains: "worker reported name is not empty", + wantErrContains: "address is not empty", }, { name: "no last status update", @@ -815,10 +814,46 @@ func TestRepository_CreateWorker(t *testing.T) { wantErr: true, wantErrContains: "unable to authorize node", }, + { + name: "unique name violation with kms worker", + setup: func() *servers.Worker { + w := servers.NewWorker(scope.Global.String()) + w.Name = kmsWorker.GetName() + return w + }, + reader: rw, + repo: testRepo, + wantErr: true, + wantErrIs: errors.NotUnique, + }, + { + name: "success", + setup: func() *servers.Worker { + w := servers.NewWorker(scope.Global.String()) + w.Name = "success" + return w + }, + reader: rw, + repo: testRepo, + }, + // This case must follow the one above it. + { + name: "unique name violation with pki worker", + setup: func() *servers.Worker { + w := servers.NewWorker(scope.Global.String()) + w.Name = "success" + return w + }, + reader: rw, + repo: testRepo, + wantErr: true, + wantErrIs: errors.NotUnique, + }, { name: "success-with-fetch-node-req", setup: func() *servers.Worker { w := servers.NewWorker(scope.Global.String()) + w.Name = "success-with-fetch-node-req" return w }, reader: rw, @@ -893,28 +928,13 @@ func TestRepository_UpdateWorker(t *testing.T) { repo, err := servers.NewRepository(rw, rw, kmsCache) require.NoError(t, err) - setCases := []struct { + pkiCases := []struct { name string modifyWorker func(*testing.T, *servers.Worker) path []string assertGot func(*testing.T, *servers.Worker) wantErr bool }{ - { - name: "update address", - modifyWorker: func(t *testing.T, w *servers.Worker) { - t.Helper() - w.Address = "foo" - }, - path: []string{"address"}, - assertGot: func(t *testing.T, w *servers.Worker) { - t.Helper() - assert.Equal(t, "foo", w.GetAddress()) - assert.Equal(t, uint32(2), w.GetVersion()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) - assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) - }, - }, { name: "update name", modifyWorker: func(t *testing.T, w *servers.Worker) { @@ -926,7 +946,7 @@ func TestRepository_UpdateWorker(t *testing.T) { t.Helper() assert.Equal(t, "foo", w.GetName()) assert.Equal(t, uint32(2), w.GetVersion()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) + assert.Nil(t, w.GetLastStatusTime()) assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) }, }, @@ -941,39 +961,18 @@ func TestRepository_UpdateWorker(t *testing.T) { t.Helper() assert.Equal(t, "foo", w.GetDescription()) assert.Equal(t, uint32(2), w.GetVersion()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) + assert.Nil(t, w.GetLastStatusTime()) assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) }, }, - { - name: "update worker reported name", - modifyWorker: func(t *testing.T, w *servers.Worker) { - t.Helper() - w.WorkerReportedName = "foo" - }, - path: []string{"WorkerReportedName"}, - wantErr: true, - }, - { - name: "update worker reported name and name", - modifyWorker: func(t *testing.T, w *servers.Worker) { - t.Helper() - w.WorkerReportedName = "foo" - w.Name = "another" - }, - path: []string{"WorkerReportedName", "Name"}, - wantErr: true, - }, - { - name: "Clear worker reported name", - modifyWorker: func(t *testing.T, w *servers.Worker) {}, - path: []string{"WorkerReportedName"}, - wantErr: true, - }, } - for _, tt := range setCases { + for _, tt := range pkiCases { t.Run(tt.name, func(t *testing.T) { - wkr := servers.TestWorker(t, conn, wrapper) + wkr := servers.TestPkiWorker(t, conn, wrapper) + defer func() { + _, err := repo.DeleteWorker(ctx, wkr.GetPublicId()) + require.NoError(t, err) + }() tt.modifyWorker(t, wkr) got, _, err := repo.UpdateWorker(ctx, wkr, 1, tt.path) if tt.wantErr { @@ -994,20 +993,6 @@ func TestRepository_UpdateWorker(t *testing.T) { assertGot func(*testing.T, *servers.Worker) wantErr bool }{ - { - name: "clear address", - modifyWorker: func(t *testing.T, w *servers.Worker) { - t.Helper() - w.Address = "" - }, - path: []string{"address"}, - assertGot: func(t *testing.T, w *servers.Worker) { - t.Helper() - assert.Empty(t, w.GetAddress()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) - assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) - }, - }, { name: "clear name", modifyWorker: func(t *testing.T, w *servers.Worker) { @@ -1018,7 +1003,7 @@ func TestRepository_UpdateWorker(t *testing.T) { assertGot: func(t *testing.T, w *servers.Worker) { t.Helper() assert.Empty(t, w.GetName()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) + assert.Nil(t, w.GetLastStatusTime()) assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) }, }, @@ -1032,18 +1017,17 @@ func TestRepository_UpdateWorker(t *testing.T) { assertGot: func(t *testing.T, w *servers.Worker) { t.Helper() assert.Empty(t, w.GetDescription()) - assert.Equal(t, w.GetLastStatusTime().AsTime(), w.GetCreateTime().AsTime()) + assert.Nil(t, w.GetLastStatusTime()) assert.Greater(t, w.GetUpdateTime().AsTime(), w.GetCreateTime().AsTime()) }, }, } for _, tt := range clearCases { t.Run(tt.name, func(t *testing.T) { - wkr := servers.TestWorker(t, conn, wrapper) + wkr := servers.TestPkiWorker(t, conn, wrapper) wkr.Name = tt.name wkr.Description = tt.name - wkr.Address = tt.name - wkr, _, err := repo.UpdateWorker(ctx, wkr, 1, []string{"name", "description", "address"}) + wkr, _, err := repo.UpdateWorker(ctx, wkr, 1, []string{"name", "description"}) require.NoError(t, err) tt.modifyWorker(t, wkr) @@ -1059,9 +1043,9 @@ func TestRepository_UpdateWorker(t *testing.T) { } t.Run("version is wrong", func(t *testing.T) { - wkr := servers.TestWorker(t, conn, wrapper) - wkr.Address = "version is wrong" - result, numUpdated, err := repo.UpdateWorker(ctx, wkr, 2, []string{"address"}) + wkr := servers.TestPkiWorker(t, conn, wrapper) + wkr.Name = "version is wrong" + result, numUpdated, err := repo.UpdateWorker(ctx, wkr, 2, []string{"name"}) require.NoError(t, err) assert.Zero(t, numUpdated) assert.Equal(t, wkr.GetUpdateTime().AsTime(), result.GetUpdateTime().AsTime()) @@ -1082,21 +1066,41 @@ func TestRepository_UpdateWorker(t *testing.T) { }, { name: "empty path", - input: servers.TestWorker(t, conn, wrapper), + input: servers.TestPkiWorker(t, conn, wrapper), version: 1, wantErr: errors.T(errors.EmptyFieldMask), }, { name: "0 version", - input: servers.TestWorker(t, conn, wrapper), + input: servers.TestPkiWorker(t, conn, wrapper), path: []string{"name"}, version: 0, wantErr: errors.T(errors.InvalidParameter), }, + { + name: "changing kms name", + input: func() *servers.Worker { + w := servers.TestKmsWorker(t, conn, wrapper) + w.Name = "some change" + return w + }(), path: []string{"name"}, + version: 1, + wantErr: errors.T(errors.NotSpecificIntegrity), + }, + { + name: "clearing kms name", + input: func() *servers.Worker { + w := servers.TestKmsWorker(t, conn, wrapper) + w.Name = "" + return w + }(), path: []string{"name"}, + version: 1, + wantErr: errors.T(errors.NotSpecificIntegrity), + }, { name: "no public id", input: func() *servers.Worker { - w := servers.TestWorker(t, conn, wrapper) + w := servers.TestPkiWorker(t, conn, wrapper) w.PublicId = "" return w }(), @@ -1106,7 +1110,7 @@ func TestRepository_UpdateWorker(t *testing.T) { }, { name: "unrecognized path", - input: servers.TestWorker(t, conn, wrapper), + input: servers.TestPkiWorker(t, conn, wrapper), path: []string{"UnrecognizedField"}, version: 1, wantErr: errors.T(errors.InvalidFieldMask), @@ -1114,7 +1118,7 @@ func TestRepository_UpdateWorker(t *testing.T) { { name: "not found worker", input: func() *servers.Worker { - w := servers.TestWorker(t, conn, wrapper) + w := servers.TestPkiWorker(t, conn, wrapper) w.PublicId = "w_notfoundworker" return w }(), @@ -1125,11 +1129,11 @@ func TestRepository_UpdateWorker(t *testing.T) { { name: "duplicate name", input: func() *servers.Worker { - w1 := servers.TestWorker(t, conn, wrapper) + w1 := servers.TestPkiWorker(t, conn, wrapper) w1.Name = "somenamethatijustmadeup" w1, _, err := repo.UpdateWorker(ctx, w1, w1.Version, []string{"name"}, nil) require.NoError(t, err) - w2 := servers.TestWorker(t, conn, wrapper) + w2 := servers.TestPkiWorker(t, conn, wrapper) w2.Name = w1.Name return w2 }(), diff --git a/internal/servers/repository_workerauth_test.go b/internal/servers/repository_workerauth_test.go index 95b85853d..162eca4b9 100644 --- a/internal/servers/repository_workerauth_test.go +++ b/internal/servers/repository_workerauth_test.go @@ -146,7 +146,7 @@ func TestStoreWorkerAuth(t *testing.T) { require.NoError(err) require.NotNil(wrapper) - worker := TestWorker(t, conn, wrapper) + worker := TestPkiWorker(t, conn, wrapper) rw := db.New(conn) rootStorage, err := NewRepositoryStorage(ctx, rw, rw, kmsCache) @@ -266,7 +266,7 @@ func TestStoreNodeInformationTx(t *testing.T) { // Create struct to pass in with workerId that will be passed along to // storage - testWorker := TestWorker(t, conn, testWrapper) + testWorker := TestPkiWorker(t, conn, testWrapper) testState, err := AttachWorkerIdToState(testCtx, testWorker.PublicId) require.NoError(t, err) diff --git a/internal/servers/servers.pb.go b/internal/servers/servers.pb.go index 842ba9bd4..edf1bd10d 100644 --- a/internal/servers/servers.pb.go +++ b/internal/servers/servers.pb.go @@ -86,6 +86,8 @@ type ServerWorkerStatus struct { PublicId string `protobuf:"bytes,10,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" class:"public"` // @gotags: `class:"public"` // Name of the resource (optional) Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty" class:"public"` // @gotags: `class:"public"` + // Description of the resource (optional) + Description string `protobuf:"bytes,25,opt,name=description,proto3" json:"description,omitempty" class:"public"` // @gotags: `class:"public"` // Address for the worker. This must be set. Address string `protobuf:"bytes,30,opt,name=address,proto3" json:"address,omitempty" class:"public"` // @gotags: `class:"public"` // Tags for workers @@ -140,6 +142,13 @@ func (x *ServerWorkerStatus) GetName() string { return "" } +func (x *ServerWorkerStatus) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + func (x *ServerWorkerStatus) GetAddress() string { if x != nil { return x.Address @@ -171,21 +180,23 @@ var file_controller_servers_v1_servers_proto_rawDesc = []byte{ 0x54, 0x61, 0x67, 0x50, 0x61, 0x69, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, - 0xaa, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0xcc, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x12, 0x32, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x28, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x50, 0x61, 0x69, 0x72, 0x52, - 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, - 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x42, 0x38, 0x5a, 0x36, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, - 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3b, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x19, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x12, 0x32, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x28, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x67, 0x50, 0x61, 0x69, + 0x72, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, + 0x64, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x42, 0x38, + 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, + 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, + 0x3b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/servers/store/worker.pb.go b/internal/servers/store/worker.pb.go index 3420bc49f..9ab200250 100644 --- a/internal/servers/store/worker.pb.go +++ b/internal/servers/store/worker.pb.go @@ -52,19 +52,12 @@ type Worker struct { // version allows optimistic locking of the resource. // @inject_tag: `gorm:"default:null"` Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"` - // Name of the resource (optional) - // @inject_tag: `gorm:"default:null"` - WorkerReportedName string `protobuf:"bytes,90,opt,name=worker_reported_name,json=workerReportedName,proto3" json:"worker_reported_name,omitempty" gorm:"default:null"` - // Address for the worker. This must be set when the worker has received - // at least 1 status update fromt he worker daemon. - // @inject_tag: `gorm:"default:null"` - WorkerReportedAddress string `protobuf:"bytes,100,opt,name=worker_reported_address,json=workerReportedAddress,proto3" json:"worker_reported_address,omitempty" gorm:"default:null"` // The last_status_time is the last time a worker daemon sent a status update. // @inject_tag: `gorm:"default:null"` LastStatusTime *timestamp.Timestamp `protobuf:"bytes,110,opt,name=last_status_time,json=lastStatusTime,proto3" json:"last_status_time,omitempty" gorm:"default:null"` - // keyId reported by a PKI worker (optional) - // @inject_tag: `gorm:"default:null"` - WorkerReportedKeyId string `protobuf:"bytes,120,opt,name=worker_reported_key_id,json=workerReportedKeyId,proto3" json:"worker_reported_key_id,omitempty" gorm:"default:null"` + // The type of the worker, denoted by how it authenticates: pki or kms. + // @inject_tag: `gorm:"not_null"` + Type string `protobuf:"bytes,130,opt,name=type,proto3" json:"type,omitempty" gorm:"not_null"` } func (x *Worker) Reset() { @@ -155,20 +148,6 @@ func (x *Worker) GetVersion() uint32 { return 0 } -func (x *Worker) GetWorkerReportedName() string { - if x != nil { - return x.WorkerReportedName - } - return "" -} - -func (x *Worker) GetWorkerReportedAddress() string { - if x != nil { - return x.WorkerReportedAddress - } - return "" -} - func (x *Worker) GetLastStatusTime() *timestamp.Timestamp { if x != nil { return x.LastStatusTime @@ -176,9 +155,9 @@ func (x *Worker) GetLastStatusTime() *timestamp.Timestamp { return nil } -func (x *Worker) GetWorkerReportedKeyId() string { +func (x *Worker) GetType() string { if x != nil { - return x.WorkerReportedKeyId + return x.Type } return "" } @@ -278,7 +257,7 @@ var file_controller_storage_servers_store_v1_worker_proto_rawDesc = []byte{ 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x83, 0x05, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xe1, 0x03, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, @@ -287,49 +266,39 @@ var file_controller_storage_servers_store_v1_worker_proto_rawDesc = []byte{ 0x6e, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, - 0x28, 0x20, 0x01, 0x28, 0x09, 0x42, 0x16, 0xc2, 0xdd, 0x29, 0x12, 0x0a, 0x07, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x12, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x07, 0x61, - 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, - 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, - 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x46, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x30, 0x0a, 0x14, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, - 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x5a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x17, 0x77, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x15, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, - 0x54, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x33, 0x0a, 0x16, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, - 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, - 0x78, 0x20, 0x01, 0x28, 0x09, 0x52, 0x13, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x22, 0x68, 0x0a, 0x09, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, - 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, - 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, - 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x4b, + 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x32, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, + 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x46, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x54, 0x0a, + 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x69, 0x6d, + 0x65, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x6c, 0x61, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x54, + 0x69, 0x6d, 0x65, 0x12, 0x13, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x82, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x68, 0x0a, 0x09, 0x57, 0x6f, 0x72, 0x6b, + 0x65, 0x72, 0x54, 0x61, 0x67, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x1e, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x42, 0x3c, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, + 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x73, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/internal/servers/testing.go b/internal/servers/testing.go index 9314cc51e..8e5a6ee05 100644 --- a/internal/servers/testing.go +++ b/internal/servers/testing.go @@ -2,18 +2,25 @@ package servers import ( "context" - "math/rand" + "crypto/rand" + mathRand "math/rand" "strings" "testing" "time" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/db/timestamp" + "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/servers/store" "github.com/hashicorp/boundary/internal/types/scope" wrapping "github.com/hashicorp/go-kms-wrapping/v2" + "github.com/hashicorp/nodeenrollment" + "github.com/hashicorp/nodeenrollment/registration" + "github.com/hashicorp/nodeenrollment/rotation" + "github.com/hashicorp/nodeenrollment/storage/file" + "github.com/hashicorp/nodeenrollment/types" "github.com/stretchr/testify/require" "google.golang.org/protobuf/types/known/timestamppb" ) @@ -51,15 +58,16 @@ func TestRootCertificate(ctx context.Context, t *testing.T, conn *db.DB, kmsKey privateKey: populateBytes(defaultLength), } - cert, err := newRootCertificate(ctx, rand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp, + cert, err := newRootCertificate(ctx, mathRand.Uint64(), populateBytes(defaultLength), beforeTimestamp, afterTimestamp, rootCertKeys, kmsKey, CurrentState) err = rw.Create(ctx, cert) require.NoError(t, err) return cert } -func TestWorkerAuth(ctx context.Context, t *testing.T, conn *db.DB, worker *Worker, kmsKey string) *WorkerAuth { +func TestWorkerAuth(t *testing.T, conn *db.DB, worker *Worker, kmsKey string) *WorkerAuth { t.Helper() + ctx := context.Background() rw := db.New(conn) wSignPubKey := populateBytes(defaultLength) wEncPubKey := populateBytes(defaultLength) @@ -81,30 +89,34 @@ func TestWorkerAuth(ctx context.Context, t *testing.T, conn *db.DB, worker *Work return workerAuth } -// TestWorker inserts a worker into the db to satisfy foreign key constraints. -// The worker provided fields are auto generated. WithName, WithDescription, -// and WithAddress are applied to the resource name, description and address if -// present. -func TestWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...Option) *Worker { +// TestKmsWorker inserts a worker into the db to satisfy foreign key constraints. +// The worker provided fields are auto generated. if WithName is not present a +// random name will be generated and assigned to the worker. +func TestKmsWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...Option) *Worker { t.Helper() rw := db.New(conn) kms := kms.TestKms(t, conn, wrapper) serversRepo, err := NewRepository(rw, rw, kms) require.NoError(t, err) ctx := context.Background() + opts := getOpts(opt...) namePart, err := newWorkerId(ctx) require.NoError(t, err) name := "test-worker-" + strings.ToLower(namePart) - id, err := newWorkerId(ctx) - require.NoError(t, err) - wrk := NewWorkerForStatus(scope.Global.String(), + if opts.withName != "" { + name = opts.withName + } + address := "127.0.0.1" + if opts.withAddress != "" { + address = opts.withAddress + } + wrk := NewWorker(scope.Global.String(), WithName(name), - WithAddress("127.0.0.1")) - wrk, err = serversRepo.UpsertWorkerStatus(ctx, wrk, WithPublicId(id)) + WithAddress(address)) + wrk, err = serversRepo.UpsertWorkerStatus(ctx, wrk) require.NoError(t, err) require.NotNil(t, wrk) - opts := getOpts(opt...) if len(opts.withWorkerTags) > 0 { var tags []interface{} @@ -113,24 +125,16 @@ func TestWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...Opti WorkerId: wrk.GetPublicId(), Key: t.Key, Value: t.Value, - Source: "api", + Source: "configuration", }) } require.NoError(t, rw.CreateItems(ctx, tags)) } var mask []string - if opts.withName != "" { - wrk.Name = opts.withName - mask = append(mask, "name") - } if opts.withDescription != "" { wrk.Description = opts.withDescription mask = append(mask, "description") } - if opts.withAddress != "" { - wrk.Address = opts.withAddress - mask = append(mask, "address") - } if len(mask) > 0 { var n int wrk, n, err = serversRepo.UpdateWorker(ctx, wrk, wrk.Version, mask) @@ -138,6 +142,72 @@ func TestWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...Opti require.Equal(t, 1, n) require.NotNil(t, wrk) } - + wrk, err = serversRepo.LookupWorker(ctx, wrk.GetPublicId()) + require.NoError(t, err) + return wrk +} + +// TestPkiWorker inserts a worker into the db to satisfy foreign key constraints. +// The worker provided fields are auto generated. WithName and WithDescription, +// are applied to the resource name, description if present. WithTestPkiWorkerAuthorizedKeyId +// can be used to make the PkiWorker authorized in which case the string pointer +// passed to WithTestPkiWorkerAuthorizedKeyId is set to the key id. +func TestPkiWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...Option) *Worker { + t.Helper() + rw := db.New(conn) + kmsCache := kms.TestKms(t, conn, wrapper) + serversRepo, err := NewRepository(rw, rw, kmsCache) + require.NoError(t, err) + ctx := context.Background() + opts := getOpts(opt...) + + require.NoError(t, err) + wrk := NewWorker(scope.Global.String(), + opt...) + wrk, err = serversRepo.CreateWorker(ctx, wrk, opt...) + require.NoError(t, err) + require.NotNil(t, wrk) + + if len(opts.withWorkerTags) > 0 { + var tags []interface{} + for _, t := range opts.withWorkerTags { + tags = append(tags, &store.WorkerTag{ + WorkerId: wrk.GetPublicId(), + Key: t.Key, + Value: t.Value, + Source: "configuration", + }) + } + require.NoError(t, rw.CreateItems(ctx, tags)) + } + if opts.withTestPkiWorkerAuthorized { + err = kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)) + // We always try to create root global scope keys, but if it already exists, just continue... + require.True(t, err == nil || errors.IsUniqueError(err), err) + rootStorage, err := NewRepositoryStorage(ctx, rw, rw, kmsCache) + require.NoError(t, err) + _, err = rotation.RotateRootCertificates(ctx, rootStorage) + require.NoError(t, err) + // Create struct to pass in with workerId that will be passed along to storage + state, err := AttachWorkerIdToState(ctx, wrk.PublicId) + require.NoError(t, err) + + // This happens on the worker + fileStorage, err := file.New(ctx) + require.NoError(t, err) + nodeCreds, err := types.NewNodeCredentials(ctx, fileStorage) + require.NoError(t, err) + // Create request using worker id + fetchReq, err := nodeCreds.CreateFetchNodeCredentialsRequest(ctx) + require.NoError(t, err) + registeredNode, err := registration.AuthorizeNode(ctx, rootStorage, fetchReq, nodeenrollment.WithState(state)) + require.NoError(t, err) + + if opts.withTestPkiWorkerKeyId != nil { + *opts.withTestPkiWorkerKeyId = registeredNode.Id + } + } + wrk, err = serversRepo.LookupWorker(ctx, wrk.GetPublicId()) + require.NoError(t, err) return wrk } diff --git a/internal/servers/testing_test.go b/internal/servers/testing_test.go index c12687450..bcbcb7364 100644 --- a/internal/servers/testing_test.go +++ b/internal/servers/testing_test.go @@ -11,7 +11,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestTestWorker(t *testing.T) { +func TestTestKmsWorker(t *testing.T) { conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) const ( @@ -19,7 +19,7 @@ func TestTestWorker(t *testing.T) { description = "test description" address = "test address" ) - tWorker := TestWorker(t, conn, wrapper, WithName(name), WithDescription(description), WithAddress(address)) + tWorker := TestKmsWorker(t, conn, wrapper, WithName(name), WithDescription(description), WithAddress(address)) assert.NotNil(t, tWorker) assert.True(t, strings.HasPrefix(tWorker.GetPublicId(), WorkerPrefix)) @@ -29,7 +29,36 @@ func TestTestWorker(t *testing.T) { require.NoError(t, rw.LookupById(context.Background(), lkpWorker)) assert.NotNil(t, lkpWorker) assert.NotNil(t, lkpWorker.GetLastStatusTime()) + assert.Equal(t, KmsWorkerType.String(), lkpWorker.GetType()) assert.Equal(t, name, lkpWorker.GetName()) assert.Equal(t, description, lkpWorker.GetDescription()) assert.Equal(t, address, lkpWorker.GetAddress()) } + +func TestTestPkiWorker(t *testing.T) { + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + const ( + name = "test name" + description = "test description" + ) + tWorker := TestPkiWorker(t, conn, wrapper, WithName(name), WithDescription(description)) + assert.NotNil(t, tWorker) + assert.True(t, strings.HasPrefix(tWorker.GetPublicId(), WorkerPrefix)) + + lkpWorker := NewWorker(scope.Global.String()) + lkpWorker.PublicId = tWorker.GetPublicId() + rw := db.New(conn) + require.NoError(t, rw.LookupById(context.Background(), lkpWorker)) + assert.NotNil(t, lkpWorker) + assert.Equal(t, PkiWorkerType.String(), lkpWorker.GetType()) + assert.Equal(t, name, lkpWorker.GetName()) + assert.Equal(t, description, lkpWorker.GetDescription()) + assert.Nil(t, lkpWorker.GetLastStatusTime()) + + var keyId string + authorizedWorker := TestPkiWorker(t, conn, wrapper, WithTestPkiWorkerAuthorizedKeyId(&keyId)) + assert.NotNil(t, authorizedWorker) + assert.True(t, strings.HasPrefix(authorizedWorker.GetPublicId(), WorkerPrefix)) + assert.NotEmpty(t, keyId) +} diff --git a/internal/servers/worker.go b/internal/servers/worker.go index a80383508..8f7986e19 100644 --- a/internal/servers/worker.go +++ b/internal/servers/worker.go @@ -12,6 +12,26 @@ import ( "google.golang.org/protobuf/types/known/structpb" ) +type WorkerType string + +const ( + UnknownWorkerType WorkerType = "unknown" + KmsWorkerType WorkerType = "kms" + PkiWorkerType WorkerType = "pki" +) + +func (t WorkerType) Valid() bool { + switch t { + case KmsWorkerType, PkiWorkerType: + return true + } + return false +} + +func (t WorkerType) String() string { + return string(t) +} + type workerAuthWorkerId struct { WorkerId string `mapstructure:"worker_id"` } @@ -40,6 +60,13 @@ type Worker struct { activeConnectionCount uint32 `gorm:"-"` apiTags []*Tag `gorm:"-"` configTags []*Tag `gorm:"-"` + + // inputTags is not specified to be api or config tags and is not intended + // to be read by clients. Since config tags and api tags are applied in + // mutually exclusive contexts, inputTags is interpreted to be one or the + // other based on the context in which the worker is passed. As such + // inputTags should only be read when performing mutations on the database. + inputTags []*Tag `gorm:"-"` } // NewWorker returns a new Worker. Valid options are WithName, WithDescription @@ -54,24 +81,7 @@ func NewWorker(scopeId string, opt ...Option) *Worker { Description: opts.withDescription, Address: opts.withAddress, }, - apiTags: opts.withWorkerTags, - } -} - -// NewWorkerForStatus returns a new Worker usable for status updates. -// Valid options are WithName, WithAddress, and WithWorkerTags, all of which -// are assigned to the worker reported variations of these fields. -// All other options are ignored. -func NewWorkerForStatus(scopeId string, opt ...Option) *Worker { - opts := getOpts(opt...) - return &Worker{ - Worker: &store.Worker{ - ScopeId: scopeId, - WorkerReportedName: opts.withName, - WorkerReportedAddress: opts.withAddress, - WorkerReportedKeyId: opts.withKeyId, - }, - configTags: opts.withWorkerTags, + inputTags: opts.withWorkerTags, } } @@ -100,19 +110,13 @@ func (w *Worker) clone() *Worker { cWorker.configTags = append(cWorker.configTags, &Tag{Key: t.Key, Value: t.Value}) } } - return cWorker -} - -// CanonicalAddress returns the actual address boundary believes should be used -// to communicate with this worker. This will be the worker resource's address -// unless it is not set in which case it will use address the worker provides -// in its connection status updates. If neither is available, an empty string -// is returned. -func (w *Worker) CanonicalAddress() string { - if w.GetAddress() != "" { - return w.GetAddress() + if w.inputTags != nil { + cWorker.inputTags = make([]*Tag, 0, len(w.inputTags)) + for _, t := range w.inputTags { + cWorker.inputTags = append(cWorker.inputTags, &Tag{Key: t.Key, Value: t.Value}) + } } - return w.GetWorkerReportedAddress() + return cWorker } // ActiveConnectionCount is the current number of sessions this worker is handling @@ -138,15 +142,6 @@ func (w *Worker) CanonicalTags() map[string][]string { return tags } -// GetApiTags returns the tags for this worker which has been set by the api. -func (w *Worker) GetApiTags() map[string][]string { - tags := make(map[string][]string) - for _, t := range w.apiTags { - tags[t.Key] = append(tags[t.Key], t.Value) - } - return tags -} - // GetConfigTags returns the tags for this worker which has been set through // the worker daemon's configuration file. func (w *Worker) GetConfigTags() map[string][]string { @@ -183,32 +178,28 @@ type workerAggregate struct { UpdateTime *timestamp.Timestamp Address string Version uint32 + Type string ApiTags string ActiveConnectionCount uint32 // Config Fields - WorkerReportedName string - WorkerReportedAddress string - LastStatusTime *timestamp.Timestamp - WorkerReportedKeyId string - WorkerConfigTags string + LastStatusTime *timestamp.Timestamp + WorkerConfigTags string } func (a *workerAggregate) toWorker(ctx context.Context) (*Worker, error) { const op = "servers.(workerAggregate).toWorker" worker := &Worker{ Worker: &store.Worker{ - PublicId: a.PublicId, - Name: a.Name, - Description: a.Description, - Address: a.Address, - CreateTime: a.CreateTime, - UpdateTime: a.UpdateTime, - ScopeId: a.ScopeId, - Version: a.Version, - WorkerReportedAddress: a.WorkerReportedAddress, - WorkerReportedName: a.WorkerReportedName, - LastStatusTime: a.LastStatusTime, - WorkerReportedKeyId: a.WorkerReportedKeyId, + PublicId: a.PublicId, + Name: a.Name, + Description: a.Description, + Address: a.Address, + CreateTime: a.CreateTime, + UpdateTime: a.UpdateTime, + ScopeId: a.ScopeId, + Version: a.Version, + LastStatusTime: a.LastStatusTime, + Type: a.Type, }, activeConnectionCount: a.ActiveConnectionCount, } diff --git a/internal/servers/worker_tags_test.go b/internal/servers/worker_tags_test.go index 679832e6a..db371cd43 100644 --- a/internal/servers/worker_tags_test.go +++ b/internal/servers/worker_tags_test.go @@ -15,7 +15,7 @@ func TestWorkerTags_Create(t *testing.T) { wrapper := db.TestWrapper(t) rw := db.New(conn) - worker := TestWorker(t, conn, wrapper) + worker := TestKmsWorker(t, conn, wrapper) tests := []struct { name string diff --git a/internal/servers/worker_test.go b/internal/servers/worker_test.go index 4e6d26a2d..7c80297f5 100644 --- a/internal/servers/worker_test.go +++ b/internal/servers/worker_test.go @@ -5,31 +5,27 @@ import ( "fmt" "strings" "testing" + "time" "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/internal/db" + "github.com/hashicorp/boundary/internal/db/timestamp" "github.com/hashicorp/boundary/internal/iam" "github.com/hashicorp/boundary/internal/servers/store" "github.com/hashicorp/boundary/internal/types/scope" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/testing/protocmp" + "google.golang.org/protobuf/types/known/timestamppb" ) -func TestWorkerCanonicalAddress(t *testing.T) { - worker := NewWorkerForStatus(scope.Global.String(), WithAddress("status")) - assert.Equal(t, "status", worker.CanonicalAddress()) - worker.Address = "worker" - assert.Equal(t, "worker", worker.CanonicalAddress()) -} - func TestWorkerCanonicalTags(t *testing.T) { - w := NewWorker(scope.Global.String(), - WithWorkerTags( - &Tag{Key: "key", Value: "apis unique"}, - &Tag{Key: "key", Value: "shared"}, - &Tag{Key: "key2", Value: "apis key2 unique"}, - )) + w := NewWorker(scope.Global.String()) + w.apiTags = []*Tag{ + {Key: "key", Value: "apis unique"}, + {Key: "key", Value: "shared"}, + {Key: "key2", Value: "apis key2 unique"}, + } w.configTags = []*Tag{ {Key: "key", Value: "configs unique"}, {Key: "key", Value: "shared"}, @@ -57,33 +53,36 @@ func TestWorkerAggregate(t *testing.T) { return got } - // Worker without a status - { + t.Run("kms worker", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) + id = strings.ToLower(id) w := NewWorker(scope.Global.String(), WithName(id), WithAddress("address")) + w.Type = KmsWorkerType.String() w.PublicId = id require.NoError(t, rw.Create(ctx, w)) got := getAggWorker(id) + assert.Equal(t, KmsWorkerType.String(), got.GetType()) assert.Equal(t, id, got.GetPublicId()) assert.Equal(t, scope.Global.String(), got.GetScopeId()) assert.Equal(t, id, got.GetName()) assert.Equal(t, "address", got.GetAddress()) assert.Equal(t, uint32(1), got.GetVersion()) - assert.Nil(t, got.GetLastStatusTime()) + assert.NotNil(t, got.GetLastStatusTime()) assert.Empty(t, got.CanonicalTags()) - } + }) // Worker with status - { + t.Run("Worker with status", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) - w := NewWorkerForStatus(scope.Global.String(), + w := NewWorker(scope.Global.String(), WithAddress("address"), WithName(strings.ToLower(id))) + w.Type = KmsWorkerType.String() w.PublicId = id require.NoError(t, rw.Create(ctx, w)) @@ -91,19 +90,19 @@ func TestWorkerAggregate(t *testing.T) { assert.Equal(t, id, got.GetPublicId()) assert.Equal(t, uint32(1), got.GetVersion()) assert.NotNil(t, got.GetLastStatusTime()) - assert.Equal(t, strings.ToLower(id), got.GetWorkerReportedName()) - assert.Equal(t, "address", got.GetWorkerReportedAddress()) - } + assert.Equal(t, strings.ToLower(id), got.GetName()) + assert.Equal(t, "address", got.GetAddress()) + }) - // Worker with a config tag - { + t.Run("Worker with a config tag", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) - ws := NewWorkerForStatus(scope.Global.String(), + w := NewWorker(scope.Global.String(), WithAddress("address"), WithName(strings.ToLower(id))) - ws.PublicId = id - require.NoError(t, rw.Create(ctx, ws)) + w.Type = KmsWorkerType.String() + w.PublicId = id + require.NoError(t, rw.Create(ctx, w)) require.NoError(t, rw.Create(ctx, &store.WorkerTag{ WorkerId: id, @@ -118,17 +117,17 @@ func TestWorkerAggregate(t *testing.T) { assert.NotNil(t, got.GetLastStatusTime()) assert.Empty(t, got.apiTags) assert.Equal(t, got.configTags, []*Tag{{Key: "key", Value: "val"}}) - } + }) - // Worker with many config tag - { + t.Run("Worker with many config tag", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) - ws := NewWorkerForStatus(scope.Global.String(), + w := NewWorker(scope.Global.String(), WithAddress("address"), WithName(strings.ToLower(id))) - ws.PublicId = id - require.NoError(t, rw.Create(ctx, ws)) + w.Type = KmsWorkerType.String() + w.PublicId = id + require.NoError(t, rw.Create(ctx, w)) require.NoError(t, rw.Create(ctx, &store.WorkerTag{ WorkerId: id, Key: "key", @@ -156,17 +155,17 @@ func TestWorkerAggregate(t *testing.T) { {Key: "key", Value: "val2"}, {Key: "key2", Value: "val2"}, }) - } + }) - // Worker with an api tag - { + t.Run("Worker with an api tag", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) - ws := NewWorkerForStatus(scope.Global.String(), + w := NewWorker(scope.Global.String(), WithAddress("address"), WithName(strings.ToLower(id))) - ws.PublicId = id - require.NoError(t, rw.Create(ctx, ws)) + w.Type = KmsWorkerType.String() + w.PublicId = id + require.NoError(t, rw.Create(ctx, w)) require.NoError(t, rw.Create(ctx, &store.WorkerTag{ WorkerId: id, @@ -181,17 +180,18 @@ func TestWorkerAggregate(t *testing.T) { assert.NotNil(t, got.GetLastStatusTime()) assert.Empty(t, got.GetConfigTags()) assert.Equal(t, got.apiTags, []*Tag{{Key: "key", Value: "val"}}) - } + }) // Worker with mix of tag sources - { + t.Run("Worker with mix of tag sources", func(t *testing.T) { id, err := newWorkerId(ctx) require.NoError(t, err) - ws := NewWorkerForStatus(scope.Global.String(), + w := NewWorker(scope.Global.String(), WithAddress("address"), WithName(strings.ToLower(id))) - ws.PublicId = id - require.NoError(t, rw.Create(ctx, ws)) + w.Type = KmsWorkerType.String() + w.PublicId = id + require.NoError(t, rw.Create(ctx, w)) require.NoError(t, rw.Create(ctx, &store.WorkerTag{ WorkerId: id, Key: "key", @@ -220,7 +220,7 @@ func TestWorkerAggregate(t *testing.T) { assert.ElementsMatch(t, got.configTags, []*Tag{ {Key: "key", Value: "val"}, }) - } + }) } func TestWorker_Update(t *testing.T) { @@ -245,260 +245,213 @@ func TestWorker_Update(t *testing.T) { wantUpdateError bool }{ { - name: "base update with base", + name: "kms update address", initial: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with base", + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "kms update address", + Address: "kms update address", }, }, update: Worker{ Worker: &store.Worker{ - Description: "base update with base updated", + Address: "updated kms update address", }, }, - mask: []string{"Description"}, + mask: []string{"Address"}, assert: func(t *testing.T, init, up *Worker) { t.Helper() - assert.Equal(t, "base update with base updated", up.Description) + assert.Equal(t, "kms update address", up.Name) + assert.Equal(t, "updated kms update address", up.Address) + assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) + assert.Equal(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) + }, + }, + { + name: "kms update name", + initial: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "kms update name", + Address: "kms update name", + }, + }, + update: Worker{ + Worker: &store.Worker{ + Name: "updated kms update name", + }, + }, + mask: []string{"Name"}, + wantUpdateError: true, + }, + { + name: "kms clear name", + initial: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "kms clear name", + Address: "kms clear name", + }, + }, + update: Worker{ + Worker: &store.Worker{}, + }, + nullMask: []string{"Name"}, + wantUpdateError: true, + }, + { + name: "pki update address", + initial: Worker{ + Worker: &store.Worker{ + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki update address", + }, + }, + update: Worker{ + Worker: &store.Worker{ + Address: "updated pki update address", + }, + }, + mask: []string{"Address"}, + assert: func(t *testing.T, init, up *Worker) { + t.Helper() + assert.Equal(t, "pki update address", up.Name) + assert.Equal(t, "updated pki update address", up.Address) + assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) + assert.Equal(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) + }, + }, + { + name: "pki update name", + initial: Worker{ + Worker: &store.Worker{ + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki update name", + }, + }, + update: Worker{ + Worker: &store.Worker{ + Name: "updated pki update name", + }, + }, + mask: []string{"Name"}, + assert: func(t *testing.T, init, up *Worker) { + t.Helper() + assert.Equal(t, "updated pki update name", up.Name) assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, uint32(2), up.Version) assert.Nil(t, up.GetLastStatusTime()) }, }, { - name: "base update with worker reported address and name", + name: "pki update description", initial: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki update description", }, }, update: Worker{ Worker: &store.Worker{ - WorkerReportedName: "base update with worker reported address and name", - WorkerReportedAddress: "base update with worker reported address and name", - }, - }, - mask: []string{"WorkerReportedAddress", "WorkerReportedName"}, - assert: func(t *testing.T, init, up *Worker) { - t.Helper() - assert.Equal(t, "base update with worker reported address and name", up.WorkerReportedAddress) - assert.Equal(t, "base update with worker reported address and name", up.WorkerReportedName) - assert.Equal(t, uint32(1), up.Version) - assert.NotNil(t, up.GetLastStatusTime()) - assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) - }, - }, - { - name: "base update with worker reported address and keyId", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedKeyId: "base update with worker reported address and keyId", - WorkerReportedAddress: "base update with worker reported address and keyId", - }, - }, - mask: []string{"WorkerReportedAddress", "WorkerReportedKeyId"}, - assert: func(t *testing.T, init, up *Worker) { - t.Helper() - assert.Equal(t, "base update with worker reported address and keyId", up.WorkerReportedAddress) - assert.Equal(t, "base update with worker reported address and keyId", up.WorkerReportedKeyId) - assert.Equal(t, uint32(1), up.Version) - assert.NotNil(t, up.GetLastStatusTime()) - assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) - }, - }, - { - name: "base update with worker reported address", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedAddress: "base update with worker reported address", - }, - }, - mask: []string{"WorkerReportedAddress"}, - wantUpdateError: true, - }, - { - // If any status fields are set then worker reported address must - // be set. - name: "base update with worker reported name", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedName: "base update with worker reported name", - }, - }, - mask: []string{"WorkerReportedName"}, - wantUpdateError: true, - }, - { - // If any status fields are set then worker reported address must - // be set. - name: "base update with worker reported keyId", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedKeyId: "base update with worker reported keyId", - }, - }, - mask: []string{"WorkerReportedKeyId"}, - wantUpdateError: true, - }, - { - name: "base update with worker reported fields", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Description: "base update with status", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedName: "base update with worker reported fields", - WorkerReportedAddress: "base update with worker reported fields", - }, - }, - mask: []string{"WorkerReportedName", "WorkerReportedAddress"}, - assert: func(t *testing.T, init, up *Worker) { - t.Helper() - assert.Equal(t, "base update with worker reported fields", up.WorkerReportedAddress) - assert.Equal(t, "base update with worker reported fields", up.WorkerReportedName) - assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, uint32(1), up.Version) - assert.NotNil(t, up.GetLastStatusTime()) - assert.Equal(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) - }, - }, - { - name: "worker reported update with base", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "worker reported update with base", - WorkerReportedName: "worker reported update with base", - }, - }, - update: Worker{ - Worker: &store.Worker{ - Description: "worker reported update with base", + Description: "updated pki update description", }, }, mask: []string{"Description"}, assert: func(t *testing.T, init, up *Worker) { t.Helper() - assert.Equal(t, "worker reported update with base", up.Description) + assert.Equal(t, "pki update description", up.Name) + assert.Equal(t, "updated pki update description", up.Description) assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, uint32(2), up.Version) - assert.NotNil(t, up.GetLastStatusTime()) - assert.Equal(t, init.GetLastStatusTime(), up.GetLastStatusTime()) + assert.Nil(t, up.GetLastStatusTime()) }, }, { - name: "worker reported update name to unprintable", + name: "pki clear address", initial: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "worker reported update name to unprintable", - WorkerReportedName: "worker reported update name to unprintable", - }, - }, - update: Worker{ - Worker: &store.Worker{ - WorkerReportedName: "unprintable \u0008 name", - }, - }, - mask: []string{"WorkerReportedName"}, - wantUpdateError: true, - }, - { - name: "worker reported clearing address", - initial: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "worker reported clearing address", - WorkerReportedName: "worker reported clearing address", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki clear address", + Address: "pki clear address", + LastStatusTime: ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(time.Hour))}, }, }, update: Worker{ Worker: &store.Worker{}, }, - nullMask: []string{"WorkerReportedAddress"}, + nullMask: []string{"Address"}, wantUpdateError: true, }, { - name: "worker reported updating worker reported", + name: "pki clear name", initial: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "start", - WorkerReportedName: "start", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki clear name", + Address: "pki clear name", + LastStatusTime: ×tamp.Timestamp{Timestamp: timestamppb.New(time.Now().Add(time.Hour))}, }, }, update: Worker{ - Worker: &store.Worker{ - WorkerReportedAddress: "worker reported updating worker reported", - }, + Worker: &store.Worker{}, }, - mask: []string{"WorkerReportedAddress"}, + nullMask: []string{"Name"}, assert: func(t *testing.T, init, up *Worker) { t.Helper() - assert.Equal(t, "worker reported updating worker reported", up.GetWorkerReportedAddress()) - assert.NotNil(t, up.GetLastStatusTime()) - assert.Greater(t, up.GetLastStatusTime().AsTime(), init.GetLastStatusTime().AsTime()) - // We don't modify the worker version while operating only on the worker fields + assert.Empty(t, up.Name) assert.Greater(t, up.GetUpdateTime().AsTime(), up.GetCreateTime().AsTime()) - assert.Equal(t, uint32(1), up.Version) + assert.Greater(t, up.GetLastStatusTime().AsTime(), up.GetUpdateTime().AsTime()) + assert.Less(t, up.GetLastStatusTime().AsTime(), time.Now().Add(time.Hour)) }, }, { - name: "worker reported clearing worker reported name", + name: "pki update name to capital", initial: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "worker reported clearing worker reported name", - WorkerReportedName: "worker reported clearing worker reported name", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki update name to capital", }, }, update: Worker{ - Worker: &store.Worker{}, + Worker: &store.Worker{ + Name: "PKI Update Name To Capital", + }, }, - nullMask: []string{"WorkerReportedName"}, + mask: []string{"Name"}, + wantUpdateError: true, + }, + { + name: "pki update name to unprintable", + initial: Worker{ + Worker: &store.Worker{ + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "worker reported update name to unprintable", + }, + }, + update: Worker{ + Worker: &store.Worker{ + Name: "unprintable \u0008 name", + }, + }, + mask: []string{"Name"}, wantUpdateError: true, }, } @@ -544,9 +497,88 @@ func TestWorker_Create(t *testing.T) { want wanted }{ { - name: "base", + name: "kms base", in: Worker{ Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Address: "address", + Name: "kms base", + Description: "kms base", + }, + }, + want: wanted{lastStatusUpdated: true}, + }, + { + name: "kms with no name field", + in: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Address: "address", + }, + }, + want: wanted{createError: true}, + }, + { + name: "kms with no address field", + in: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "kms with no address field", + }, + }, + want: wanted{createError: true}, + }, + { + name: "kms with upper case name", + in: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "With Upper Case Worker Reported Name", + Address: "address", + }, + }, + want: wanted{createError: true}, + }, + { + name: "kms with unprintable worker reported name", + in: Worker{ + Worker: &store.Worker{ + Type: KmsWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "unprintable \u0008 worker reported name", + Address: "address", + }, + }, + want: wanted{createError: true}, + }, + // PKI workers are not created in a way that should set the address + // or the last_status_time. + { + name: "pki base", + in: Worker{ + Worker: &store.Worker{ + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "pki base", + }, + }, + want: wanted{}, + }, + { + name: "pki with no name field", + in: Worker{ + Worker: &store.Worker{ + Type: PkiWorkerType.String(), ScopeId: scope.Global.String(), PublicId: newId(), }, @@ -554,134 +586,42 @@ func TestWorker_Create(t *testing.T) { want: wanted{}, }, { - name: "with non status fields", + name: "pki with address field", in: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Name: "with non status fields", - Description: "with non status fields", - Address: "address", - }, - }, - want: wanted{}, - }, - { - name: "with upper case worker reported name", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedName: "With Upper Case Worker Reported Name", - WorkerReportedAddress: "address", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Address: "address", }, }, want: wanted{createError: true}, }, { - name: "with unprintable worker reported name", + name: "pki with upper case name", in: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedName: "unprintable \u0008 worker reported name", - WorkerReportedAddress: "address", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "PKI With Upper Case Worker Reported Name", + Address: "address", }, }, want: wanted{createError: true}, }, { - name: "with status fields", + name: "pki with unprintable worker reported name", in: Worker{ Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedName: "with non status fields", - WorkerReportedAddress: "with non status fields", + Type: PkiWorkerType.String(), + ScopeId: scope.Global.String(), + PublicId: newId(), + Name: "unprintable \u0008 worker reported name", + Address: "address", }, }, - want: wanted{ - lastStatusUpdated: true, - }, - }, - { - name: "with worker reported address", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedAddress: "with worker reported address", - }, - }, - want: wanted{ - createError: true, - }, - }, - { - // The worker reported address is a required field if any of the - // worker reported fields are set. - name: "with worker reported name", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - WorkerReportedName: "with worker reported name", - }, - }, - want: wanted{ - createError: true, - }, - }, - { - name: "non status fields with worker reported fields", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Name: "non status fields with worker reported fields", - Description: "non status fields with worker reported fields", - Address: "address", - WorkerReportedAddress: "non status fields with worker reported fields", - WorkerReportedName: "non status fields with worker reported fields", - }, - }, - want: wanted{ - lastStatusUpdated: true, - }, - }, - { - // The worker reported address is a required field if any of the - // worker reported fields are set. - name: "non status fields with worker reported name", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Name: "non status fields with worker reported name", - Description: "non status fields with worker reported name", - Address: "address", - WorkerReportedName: "non status fields with worker reported name", - }, - }, - want: wanted{ - createError: true, - }, - }, - { - name: "non status fields with worker reported address", - in: Worker{ - Worker: &store.Worker{ - ScopeId: scope.Global.String(), - PublicId: newId(), - Name: "non status fields with worker reported address", - Description: "non status fields with worker reported address", - Address: "address", - WorkerReportedAddress: "non status fields with worker reported address", - }, - }, - want: wanted{ - createError: true, - }, + want: wanted{createError: true}, }, } for _, tc := range cases { @@ -711,7 +651,6 @@ func TestWorker_New(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) - rw := db.New(conn) org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) @@ -721,10 +660,9 @@ func TestWorker_New(t *testing.T) { } tests := []struct { - name string - args args - want *Worker - wantCreateErr bool + name string + args args + want *Worker }{ { name: "missing-scope-id", @@ -732,7 +670,6 @@ func TestWorker_New(t *testing.T) { want: &Worker{ Worker: &store.Worker{}, }, - wantCreateErr: true, }, { name: "global-scope-id", @@ -755,7 +692,6 @@ func TestWorker_New(t *testing.T) { ScopeId: org.GetPublicId(), }, }, - wantCreateErr: true, }, { name: "project-scope-id", @@ -767,7 +703,6 @@ func TestWorker_New(t *testing.T) { ScopeId: prj.GetPublicId(), }, }, - wantCreateErr: true, }, { name: "with name", @@ -829,7 +764,7 @@ func TestWorker_New(t *testing.T) { Worker: &store.Worker{ ScopeId: scope.Global.String(), }, - apiTags: []*Tag{ + inputTags: []*Tag{ { Key: "key", Value: "val", @@ -845,20 +780,6 @@ func TestWorker_New(t *testing.T) { assert := assert.New(t) got := NewWorker(tt.args.scopeId, tt.args.opts...) assert.Empty(cmp.Diff(tt.want, got.clone(), protocmp.Transform())) - - id, err := newWorkerId(context.Background()) - assert.NoError(err) - - tt.want.PublicId = id - got.PublicId = id - - err2 := rw.Create(context.Background(), got) - if tt.wantCreateErr { - assert.Error(err2) - } else { - assert.NoError(err2) - assert.Equal(uint32(1), got.Version) - } }) } } diff --git a/internal/servers/workerauth_store_test.go b/internal/servers/workerauth_store_test.go index fdbe415d6..4bddd2ca4 100644 --- a/internal/servers/workerauth_store_test.go +++ b/internal/servers/workerauth_store_test.go @@ -291,7 +291,7 @@ func TestWorkerAuthStore(t *testing.T) { testKey, err := databaseWrapper.KeyId(ctx) require.NoError(t, err) - worker := TestWorker(t, conn, wrapper) + worker := TestPkiWorker(t, conn, wrapper) wSignPubKey := populateBytes(defaultLength) wEncPubKey := populateBytes(defaultLength) @@ -430,8 +430,8 @@ func TestWorkerCertBundle(t *testing.T) { wrapper := db.TestWrapper(t) testKey := TestKmsKey(ctx, t, conn, wrapper) - worker := TestWorker(t, conn, wrapper) - workerAuth := TestWorkerAuth(ctx, t, conn, worker, testKey) + worker := TestPkiWorker(t, conn, wrapper) + workerAuth := TestWorkerAuth(t, conn, worker, testKey) rootCA := TestRootCertificate(ctx, t, conn, testKey) certBundle := populateBytes(defaultLength) diff --git a/internal/session/job_session_cleanup_test.go b/internal/session/job_session_cleanup_test.go index b261506dc..837567c74 100644 --- a/internal/session/job_session_cleanup_test.go +++ b/internal/session/job_session_cleanup_test.go @@ -45,8 +45,8 @@ func TestSessionConnectionCleanupJob(t *testing.T) { // Create two "workers". One will remain untouched while the other "goes // away and comes back" (worker 2). - worker1 := servers.TestWorker(t, conn, wrapper) - worker2 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) + worker2 := servers.TestKmsWorker(t, conn, wrapper) // Create a few sessions on each, activate, and authorize a connection var connIds []string @@ -109,9 +109,10 @@ func TestSessionConnectionCleanupJob(t *testing.T) { // Push an upsert to the first worker so that its status has been // updated. - _, err = serversRepo.UpsertWorkerStatus(ctx, servers.NewWorkerForStatus(scope.Global.String(), - servers.WithName(worker1.GetWorkerReportedName()), - servers.WithAddress(worker1.GetWorkerReportedAddress()))) + _, err = serversRepo.UpsertWorkerStatus(ctx, servers.NewWorker(scope.Global.String(), + servers.WithName(worker1.GetName()), + servers.WithAddress(worker1.GetAddress())), + servers.WithPublicId(worker1.GetPublicId())) require.NoError(err) // Run the job. @@ -198,10 +199,10 @@ func TestCloseConnectionsForDeadWorkers(t *testing.T) { // firstly, the last worker will have no connections at all, and we will be // closing the others in stages to test multiple servers being closed at // once. - worker1 := servers.TestWorker(t, conn, wrapper) - worker2 := servers.TestWorker(t, conn, wrapper) - worker3 := servers.TestWorker(t, conn, wrapper) - worker4 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) + worker2 := servers.TestKmsWorker(t, conn, wrapper) + worker3 := servers.TestKmsWorker(t, conn, wrapper) + worker4 := servers.TestKmsWorker(t, conn, wrapper) // Create sessions on the first three, activate, and authorize connections var worker1ConnIds, worker2ConnIds, worker3ConnIds []string @@ -292,11 +293,9 @@ func TestCloseConnectionsForDeadWorkers(t *testing.T) { // the most up-to-date fields. updateServer := func(t *testing.T, w *servers.Worker) *servers.Worker { t.Helper() - // The worker provided name will derive the WorkerId every time - // UpsertWorkerStatus is called. Setting the Worker Id on the caller - // side is an error. + pubId := w.GetPublicId() w.PublicId = "" - wkr, err := serversRepo.UpsertWorkerStatus(ctx, w) + wkr, err := serversRepo.UpsertWorkerStatus(ctx, w, servers.WithPublicId(pubId)) require.NoError(err) return wkr } @@ -465,7 +464,7 @@ func TestCloseWorkerlessConnections(t *testing.T) { } // Setup deleted worker connections - deletedWorker := servers.TestWorker(t, conn, wrapper) + deletedWorker := servers.TestKmsWorker(t, conn, wrapper) dActiveConn := createConnection(deletedWorker.GetPublicId()) dClosedConn := createConnection(deletedWorker.GetPublicId()) connRepo.closeConnections(ctx, []CloseWith{{ @@ -478,7 +477,7 @@ func TestCloseWorkerlessConnections(t *testing.T) { require.NoError(err) // Non deleted worker case - activeWorker := servers.TestWorker(t, conn, wrapper) + activeWorker := servers.TestKmsWorker(t, conn, wrapper) activeConn := createConnection(activeWorker.GetPublicId()) closedConn := createConnection(activeWorker.GetPublicId()) connRepo.closeConnections(ctx, []CloseWith{{ diff --git a/internal/session/repository_connection_test.go b/internal/session/repository_connection_test.go index 200df8272..df43a59c9 100644 --- a/internal/session/repository_connection_test.go +++ b/internal/session/repository_connection_test.go @@ -359,8 +359,8 @@ func TestRepository_orphanedConnections(t *testing.T) { // Create two "workers". One will remain untouched while the other "goes // away and comes back" (worker 2). - worker1 := servers.TestWorker(t, conn, wrapper) - worker2 := servers.TestWorker(t, conn, wrapper) + worker1 := servers.TestKmsWorker(t, conn, wrapper) + worker2 := servers.TestKmsWorker(t, conn, wrapper) // Create a few sessions on each, activate, and authorize a connection var connIds []string diff --git a/internal/session/service_authorize_connection_test.go b/internal/session/service_authorize_connection_test.go index 6261bfb06..e0d3cf739 100644 --- a/internal/session/service_authorize_connection_test.go +++ b/internal/session/service_authorize_connection_test.go @@ -36,7 +36,7 @@ func TestService_AuthorizeConnection(t *testing.T) { composedOf.ExpirationTime = exp } s := TestSession(t, conn, wrapper, composedOf) - srv := servers.TestWorker(t, conn, wrapper) + srv := servers.TestKmsWorker(t, conn, wrapper) testServer = srv.PublicId tofu := TestTofu(t) _, _, err := repo.ActivateSession(context.Background(), s.PublicId, s.Version, tofu) diff --git a/internal/session/service_worker_status_report_test.go b/internal/session/service_worker_status_report_test.go index 706c2db56..4cf5a608b 100644 --- a/internal/session/service_worker_status_report_test.go +++ b/internal/session/service_worker_status_report_test.go @@ -14,7 +14,6 @@ import ( "github.com/hashicorp/boundary/internal/session" "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/internal/target/tcp" - "github.com/hashicorp/boundary/internal/types/scope" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -28,12 +27,11 @@ func TestWorkerStatusReport(t *testing.T) { org, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper)) serverRepo, _ := servers.NewRepository(rw, rw, kms) - serverRepo.UpsertController(ctx, &store.Controller{ + _, err := serverRepo.UpsertController(ctx, &store.Controller{ PrivateId: "test_controller1", Address: "127.0.0.1", }) - serverRepo.UpsertWorkerStatus(ctx, servers.NewWorkerForStatus(scope.Global.String(), - servers.WithAddress("127.0.0.1"))) + require.NoError(t, err) repo, err := session.NewRepository(rw, rw, kms) require.NoError(t, err) @@ -66,7 +64,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "No Sessions", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) return testCase{ worker: worker, req: []session.StateReport{}, @@ -77,7 +75,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "No Sessions already canceled", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), @@ -109,7 +107,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "Still Active", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), @@ -143,7 +141,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "SessionClosed", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), @@ -183,7 +181,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "MultipleSessionsClosed", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), @@ -250,7 +248,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "OrphanedConnection", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), @@ -301,7 +299,7 @@ func TestWorkerStatusReport(t *testing.T) { { name: "MultipleSessionsAndOrphanedConnections", caseFn: func(t *testing.T) testCase { - worker := servers.TestWorker(t, conn, wrapper) + worker := servers.TestKmsWorker(t, conn, wrapper) sess := session.TestSession(t, conn, wrapper, session.ComposedOf{ UserId: uId, HostId: h.GetPublicId(), diff --git a/internal/session/testing_test.go b/internal/session/testing_test.go index f344ae896..1403a3296 100644 --- a/internal/session/testing_test.go +++ b/internal/session/testing_test.go @@ -74,7 +74,7 @@ func Test_TestWorker(t *testing.T) { require := require.New(t) conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) - w := servers.TestWorker(t, conn, wrapper) + w := servers.TestKmsWorker(t, conn, wrapper) require.NotNil(w) } diff --git a/sdk/pbs/controller/api/resources/workers/worker.pb.go b/sdk/pbs/controller/api/resources/workers/worker.pb.go index cdead7367..1091456e8 100644 --- a/sdk/pbs/controller/api/resources/workers/worker.pb.go +++ b/sdk/pbs/controller/api/resources/workers/worker.pb.go @@ -25,73 +25,6 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) -// WorkerProvidedConfiguration contains configuration values reported by the worker daemon. -type WorkerProvidedConfiguration struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // Output only. The address the worker daemon reports itself as reachable at. - Address string `protobuf:"bytes,10,opt,name=address,proto3" json:"address,omitempty"` - // Output only. The name the worker daemon reports itself having. - Name string `protobuf:"bytes,20,opt,name=name,proto3" json:"name,omitempty"` - // Output only. The tags reporteed by the worker daemon. - Tags map[string]*structpb.ListValue `protobuf:"bytes,40,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` -} - -func (x *WorkerProvidedConfiguration) Reset() { - *x = WorkerProvidedConfiguration{} - if protoimpl.UnsafeEnabled { - mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *WorkerProvidedConfiguration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WorkerProvidedConfiguration) ProtoMessage() {} - -func (x *WorkerProvidedConfiguration) ProtoReflect() protoreflect.Message { - mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use WorkerProvidedConfiguration.ProtoReflect.Descriptor instead. -func (*WorkerProvidedConfiguration) Descriptor() ([]byte, []int) { - return file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP(), []int{0} -} - -func (x *WorkerProvidedConfiguration) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *WorkerProvidedConfiguration) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *WorkerProvidedConfiguration) GetTags() map[string]*structpb.ListValue { - if x != nil { - return x.Tags - } - return nil -} - // Worker contains all fields related to a Worker resource type Worker struct { state protoimpl.MessageState @@ -104,9 +37,11 @@ type Worker struct { ScopeId string `protobuf:"bytes,20,opt,name=scope_id,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. Scope information for this resource. Scope *scopes.ScopeInfo `protobuf:"bytes,30,opt,name=scope,proto3" json:"scope,omitempty"` - // Optional name for identification purposes. + // Optional name for identification purposes. Can only be set through the API + // for `pki`-type workers; read-only for `kms`-type workers. Name *wrapperspb.StringValue `protobuf:"bytes,40,opt,name=name,proto3" json:"name,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` - // Optional user-set description for identification purposes. + // Optional user-set description for identification purposes. Can only be set + // through the API for `pki`-type workers; read-only for `kms`-type workers. Description *wrapperspb.StringValue `protobuf:"bytes,50,opt,name=description,proto3" json:"description,omitempty" class:"sensitive"` // @gotags: `class:"sensitive"` // Output only. The time this resource was created. CreatedTime *timestamppb.Timestamp `protobuf:"bytes,60,opt,name=created_time,proto3" json:"created_time,omitempty" class:"public"` // @gotags: `class:"public"` @@ -115,23 +50,17 @@ type Worker struct { // Version is used in mutation requests, after the initial creation, to ensure this resource has not changed. // The mutation will fail if the version does not match the latest known good version. Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"` - // The address that this worker is reachable at. - Address *wrapperspb.StringValue `protobuf:"bytes,90,opt,name=address,proto3" json:"address,omitempty" class:"public"` // @gotags: `class:"public"` - // Output only. This is the address used by authorized session. The value - // is the same as the address field if set. Otherwise it uses the address the - // worker reports. - CanonicalAddress string `protobuf:"bytes,100,opt,name=canonical_address,proto3" json:"canonical_address,omitempty" class:"public"` // @gotags: `class:"public"` - // Output only. The tags attached to this worker. - Tags map[string]*structpb.ListValue `protobuf:"bytes,110,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: `class:"public"` - // Output only. The deduplicated union of the tags reported by the worker and - // the tags added through the user facing api. This is used when applying - // worker filters. + // Output only. The address that this worker is reachable at, as sourced from + // the worker's configuration file. + Address string `protobuf:"bytes,90,opt,name=address,proto3" json:"address,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The deduplicated union of the tags reported by the worker from + // its configuration and any tags added through other means. This is used + // when applying worker filters. CanonicalTags map[string]*structpb.ListValue `protobuf:"bytes,120,rep,name=canonical_tags,proto3" json:"canonical_tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: `class:"public"` + // Output only. The tags set in the worker's configuration file. + ConfigTags map[string]*structpb.ListValue `protobuf:"bytes,130,rep,name=config_tags,proto3" json:"config_tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3" class:"public"` // @gotags: `class:"public"` // Output only. The time this worker daemon last reported its status. - LastStatusTime *timestamppb.Timestamp `protobuf:"bytes,130,opt,name=last_status_time,proto3" json:"last_status_time,omitempty" class:"public"` // @gotags: `class:"public"` - // Output only. The set of information the worker daemon has reported about - // itself. - WorkerProvidedConfiguration *WorkerProvidedConfiguration `protobuf:"bytes,140,opt,name=worker_provided_configuration,proto3" json:"worker_provided_configuration,omitempty"` + LastStatusTime *timestamppb.Timestamp `protobuf:"bytes,140,opt,name=last_status_time,proto3" json:"last_status_time,omitempty" class:"public"` // @gotags: `class:"public"` // worker_generated_auth_token is input only. Supports the worker led node // enrollment flow where this credentials token is produced by a worker. This // token is a base58 encoded types.FetchNodeCredentialsRequest from @@ -139,6 +68,9 @@ type Worker struct { WorkerGeneratedAuthToken *wrapperspb.StringValue `protobuf:"bytes,150,opt,name=worker_generated_auth_token,proto3" json:"worker_generated_auth_token,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The number of connections that this worker is currently handling. ActiveConnectionCount *wrapperspb.UInt32Value `protobuf:"bytes,160,opt,name=active_connection_count,proto3" json:"active_connection_count,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The type of the worker, denoted by how it authenticates: `pki` + // or `kms`. + Type string `protobuf:"bytes,170,opt,name=type,proto3" json:"type,omitempty"` // Output only. The available actions on this resource for the requester. AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty" class:"public"` // @gotags: `class:"public"` } @@ -146,7 +78,7 @@ type Worker struct { func (x *Worker) Reset() { *x = Worker{} if protoimpl.UnsafeEnabled { - mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[1] + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -159,7 +91,7 @@ func (x *Worker) String() string { func (*Worker) ProtoMessage() {} func (x *Worker) ProtoReflect() protoreflect.Message { - mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[1] + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[0] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -172,7 +104,7 @@ func (x *Worker) ProtoReflect() protoreflect.Message { // Deprecated: Use Worker.ProtoReflect.Descriptor instead. func (*Worker) Descriptor() ([]byte, []int) { - return file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP(), []int{1} + return file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP(), []int{0} } func (x *Worker) GetId() string { @@ -231,27 +163,13 @@ func (x *Worker) GetVersion() uint32 { return 0 } -func (x *Worker) GetAddress() *wrapperspb.StringValue { +func (x *Worker) GetAddress() string { if x != nil { return x.Address } - return nil -} - -func (x *Worker) GetCanonicalAddress() string { - if x != nil { - return x.CanonicalAddress - } return "" } -func (x *Worker) GetTags() map[string]*structpb.ListValue { - if x != nil { - return x.Tags - } - return nil -} - func (x *Worker) GetCanonicalTags() map[string]*structpb.ListValue { if x != nil { return x.CanonicalTags @@ -259,16 +177,16 @@ func (x *Worker) GetCanonicalTags() map[string]*structpb.ListValue { return nil } -func (x *Worker) GetLastStatusTime() *timestamppb.Timestamp { +func (x *Worker) GetConfigTags() map[string]*structpb.ListValue { if x != nil { - return x.LastStatusTime + return x.ConfigTags } return nil } -func (x *Worker) GetWorkerProvidedConfiguration() *WorkerProvidedConfiguration { +func (x *Worker) GetLastStatusTime() *timestamppb.Timestamp { if x != nil { - return x.WorkerProvidedConfiguration + return x.LastStatusTime } return nil } @@ -287,6 +205,13 @@ func (x *Worker) GetActiveConnectionCount() *wrapperspb.UInt32Value { return nil } +func (x *Worker) GetType() string { + if x != nil { + return x.Type + } + return "" +} + func (x *Worker) GetAuthorizedActions() []string { if x != nil { return x.AuthorizedActions @@ -314,83 +239,53 @@ var file_controller_api_resources_workers_v1_worker_proto_rawDesc = []byte{ 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x22, 0x80, 0x02, 0x0a, 0x1b, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x12, 0x5e, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x28, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x4a, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, - 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe5, 0x0a, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, - 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, - 0x65, 0x12, 0x46, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, - 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, - 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, - 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, - 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0c, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x52, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x1a, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x12, - 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, - 0x73, 0x73, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2c, 0x0a, 0x11, 0x63, - 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x18, 0x64, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, - 0x6c, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x49, 0x0a, 0x04, 0x74, 0x61, 0x67, - 0x73, 0x18, 0x6e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, - 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, - 0x74, 0x61, 0x67, 0x73, 0x12, 0x66, 0x0a, 0x0e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, - 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x78, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x63, + 0x74, 0x6f, 0x22, 0xa3, 0x09, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x0e, 0x0a, + 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, + 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x46, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, 0x01, + 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, 0xc2, + 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, + 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x66, + 0x0a, 0x0e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, + 0x18, 0x78, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x54, 0x61, 0x67, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, + 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x5e, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x5f, 0x74, 0x61, 0x67, 0x73, 0x18, 0x82, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2e, - 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, - 0x63, 0x61, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0e, 0x63, 0x61, - 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x10, - 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x82, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x87, 0x01, 0x0a, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x8c, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x1d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x76, 0x31, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x8c, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, + 0x61, 0x73, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x5f, 0x0a, 0x1b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x96, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, @@ -402,27 +297,29 @@ var file_controller_api_resources_workers_v1_worker_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x17, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x12, 0x61, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x53, 0x0a, 0x09, 0x54, 0x61, - 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, - 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, + 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x13, 0x0a, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x18, 0xaa, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2f, + 0x0a, 0x12, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xac, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x5c, 0x0a, 0x12, 0x43, 0x61, 0x6e, 0x6f, 0x6e, 0x69, 0x63, 0x61, 0x6c, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x50, 0x5a, - 0x4e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, - 0x64, 0x6b, 0x2f, 0x70, 0x62, 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, - 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x59, 0x0a, + 0x0f, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x30, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x42, 0x50, 0x5a, 0x4e, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x62, + 0x73, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, + 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, + 0x72, 0x73, 0x3b, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -437,41 +334,35 @@ func file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP() []byte return file_controller_api_resources_workers_v1_worker_proto_rawDescData } -var file_controller_api_resources_workers_v1_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_controller_api_resources_workers_v1_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_controller_api_resources_workers_v1_worker_proto_goTypes = []interface{}{ - (*WorkerProvidedConfiguration)(nil), // 0: controller.api.resources.workers.v1.WorkerProvidedConfiguration - (*Worker)(nil), // 1: controller.api.resources.workers.v1.Worker - nil, // 2: controller.api.resources.workers.v1.WorkerProvidedConfiguration.TagsEntry - nil, // 3: controller.api.resources.workers.v1.Worker.TagsEntry - nil, // 4: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry - (*scopes.ScopeInfo)(nil), // 5: controller.api.resources.scopes.v1.ScopeInfo - (*wrapperspb.StringValue)(nil), // 6: google.protobuf.StringValue - (*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp - (*wrapperspb.UInt32Value)(nil), // 8: google.protobuf.UInt32Value - (*structpb.ListValue)(nil), // 9: google.protobuf.ListValue + (*Worker)(nil), // 0: controller.api.resources.workers.v1.Worker + nil, // 1: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry + nil, // 2: controller.api.resources.workers.v1.Worker.ConfigTagsEntry + (*scopes.ScopeInfo)(nil), // 3: controller.api.resources.scopes.v1.ScopeInfo + (*wrapperspb.StringValue)(nil), // 4: google.protobuf.StringValue + (*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp + (*wrapperspb.UInt32Value)(nil), // 6: google.protobuf.UInt32Value + (*structpb.ListValue)(nil), // 7: google.protobuf.ListValue } var file_controller_api_resources_workers_v1_worker_proto_depIdxs = []int32{ - 2, // 0: controller.api.resources.workers.v1.WorkerProvidedConfiguration.tags:type_name -> controller.api.resources.workers.v1.WorkerProvidedConfiguration.TagsEntry - 5, // 1: controller.api.resources.workers.v1.Worker.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 6, // 2: controller.api.resources.workers.v1.Worker.name:type_name -> google.protobuf.StringValue - 6, // 3: controller.api.resources.workers.v1.Worker.description:type_name -> google.protobuf.StringValue - 7, // 4: controller.api.resources.workers.v1.Worker.created_time:type_name -> google.protobuf.Timestamp - 7, // 5: controller.api.resources.workers.v1.Worker.updated_time:type_name -> google.protobuf.Timestamp - 6, // 6: controller.api.resources.workers.v1.Worker.address:type_name -> google.protobuf.StringValue - 3, // 7: controller.api.resources.workers.v1.Worker.tags:type_name -> controller.api.resources.workers.v1.Worker.TagsEntry - 4, // 8: controller.api.resources.workers.v1.Worker.canonical_tags:type_name -> controller.api.resources.workers.v1.Worker.CanonicalTagsEntry - 7, // 9: controller.api.resources.workers.v1.Worker.last_status_time:type_name -> google.protobuf.Timestamp - 0, // 10: controller.api.resources.workers.v1.Worker.worker_provided_configuration:type_name -> controller.api.resources.workers.v1.WorkerProvidedConfiguration - 6, // 11: controller.api.resources.workers.v1.Worker.worker_generated_auth_token:type_name -> google.protobuf.StringValue - 8, // 12: controller.api.resources.workers.v1.Worker.active_connection_count:type_name -> google.protobuf.UInt32Value - 9, // 13: controller.api.resources.workers.v1.WorkerProvidedConfiguration.TagsEntry.value:type_name -> google.protobuf.ListValue - 9, // 14: controller.api.resources.workers.v1.Worker.TagsEntry.value:type_name -> google.protobuf.ListValue - 9, // 15: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry.value:type_name -> google.protobuf.ListValue - 16, // [16:16] is the sub-list for method output_type - 16, // [16:16] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 3, // 0: controller.api.resources.workers.v1.Worker.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 4, // 1: controller.api.resources.workers.v1.Worker.name:type_name -> google.protobuf.StringValue + 4, // 2: controller.api.resources.workers.v1.Worker.description:type_name -> google.protobuf.StringValue + 5, // 3: controller.api.resources.workers.v1.Worker.created_time:type_name -> google.protobuf.Timestamp + 5, // 4: controller.api.resources.workers.v1.Worker.updated_time:type_name -> google.protobuf.Timestamp + 1, // 5: controller.api.resources.workers.v1.Worker.canonical_tags:type_name -> controller.api.resources.workers.v1.Worker.CanonicalTagsEntry + 2, // 6: controller.api.resources.workers.v1.Worker.config_tags:type_name -> controller.api.resources.workers.v1.Worker.ConfigTagsEntry + 5, // 7: controller.api.resources.workers.v1.Worker.last_status_time:type_name -> google.protobuf.Timestamp + 4, // 8: controller.api.resources.workers.v1.Worker.worker_generated_auth_token:type_name -> google.protobuf.StringValue + 6, // 9: controller.api.resources.workers.v1.Worker.active_connection_count:type_name -> google.protobuf.UInt32Value + 7, // 10: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry.value:type_name -> google.protobuf.ListValue + 7, // 11: controller.api.resources.workers.v1.Worker.ConfigTagsEntry.value:type_name -> google.protobuf.ListValue + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_controller_api_resources_workers_v1_worker_proto_init() } @@ -481,18 +372,6 @@ func file_controller_api_resources_workers_v1_worker_proto_init() { } if !protoimpl.UnsafeEnabled { file_controller_api_resources_workers_v1_worker_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkerProvidedConfiguration); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_controller_api_resources_workers_v1_worker_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Worker); i { case 0: return &v.state @@ -511,7 +390,7 @@ func file_controller_api_resources_workers_v1_worker_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_resources_workers_v1_worker_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 3, NumExtensions: 0, NumServices: 0, }, diff --git a/testing/dbtest/session_list_benchmarks_dump_generation_test.go b/testing/dbtest/session_list_benchmarks_dump_generation_test.go index daccd5945..2b7beb032 100644 --- a/testing/dbtest/session_list_benchmarks_dump_generation_test.go +++ b/testing/dbtest/session_list_benchmarks_dump_generation_test.go @@ -22,7 +22,6 @@ import ( "github.com/hashicorp/boundary/internal/session" "github.com/hashicorp/boundary/internal/target" "github.com/hashicorp/boundary/internal/target/tcp" - "github.com/hashicorp/boundary/internal/types/scope" "github.com/hashicorp/boundary/testing/dbtest" "github.com/stretchr/testify/require" "golang.org/x/sync/errgroup" @@ -130,11 +129,7 @@ func TestGenerateSessionBenchmarkTemplateDumps(t *testing.T) { require.NoError(err) connRepo, err := session.NewConnectionRepository(ctx, rw, rw, kms) require.NoError(err) - serversRepo, err := servers.NewRepository(rw, rw, kms) - require.NoError(err) - _, err = serversRepo.UpsertWorkerStatus(ctx, servers.NewWorkerForStatus(scope.Global.String(), - servers.WithAddress("127.0.0.1"))) - require.NoError(err) + _ = servers.TestKmsWorker(t, conn, wrap) usersStart := time.Now() t.Logf("Populating %d users", scenario.users)