diff --git a/api/workers/worker.gen.go b/api/workers/worker.gen.go index 8e343a9c3b..b116f06677 100644 --- a/api/workers/worker.gen.go +++ b/api/workers/worker.gen.go @@ -31,6 +31,7 @@ type Worker struct { Type string `json:"type,omitempty"` ApiTags map[string][]string `json:"api_tags,omitempty"` ReleaseVersion string `json:"release_version,omitempty"` + DirectlyConnectedDownstreamWorkers []string `json:"directly_connected_downstream_workers,omitempty"` AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response diff --git a/globals/fields.go b/globals/fields.go index d8cecbe783..63ad052300 100644 --- a/globals/fields.go +++ b/globals/fields.go @@ -93,4 +93,5 @@ const ( KeyVersionIdField = "key_version_id" CompletedCountField = "completed_count" TotalCountField = "total_count" + DirectlyConnectedDownstreamWorkers = "directly_connected_downstream_workers" ) diff --git a/internal/cmd/commands/workerscmd/funcs.go b/internal/cmd/commands/workerscmd/funcs.go index dbcd79f917..a184210278 100644 --- a/internal/cmd/commands/workerscmd/funcs.go +++ b/internal/cmd/commands/workerscmd/funcs.go @@ -225,6 +225,11 @@ func (c *Command) printListTable(items []*workers.Worker) string { fmt.Sprintf(" Last Status Time: %s", item.LastStatusTime.Format(time.RFC1123)), ) } + if len(item.DirectlyConnectedDownstreamWorkers) > 0 { + output = append(output, + " Directly Connected Downstream Workers:", + base.WrapSlice(6, item.DirectlyConnectedDownstreamWorkers)) + } if len(item.AuthorizedActions) > 0 { output = append(output, @@ -331,6 +336,14 @@ func printItemTable(item *workers.Worker, resp *api.Response) string { } } + if len(item.DirectlyConnectedDownstreamWorkers) > 0 { + ret = append(ret, + "", + " Directly Connected Downstream Workers:", + base.WrapSlice(4, item.DirectlyConnectedDownstreamWorkers), + ) + } + if len(item.AuthorizedActions) > 0 { ret = append(ret, "", diff --git a/internal/daemon/controller/handler.go b/internal/daemon/controller/handler.go index c6fa0f3d6c..d8d18c0597 100644 --- a/internal/daemon/controller/handler.go +++ b/internal/daemon/controller/handler.go @@ -247,7 +247,8 @@ func (c *Controller) registerGrpcServices(s *grpc.Server) error { services.RegisterCredentialLibraryServiceServer(s, cl) } if _, ok := currentServices[services.WorkerService_ServiceDesc.ServiceName]; !ok { - ws, err := workers.NewService(c.baseContext, c.ServersRepoFn, c.IamRepoFn, c.WorkerAuthRepoStorageFn) + ws, err := workers.NewService(c.baseContext, c.ServersRepoFn, c.IamRepoFn, c.WorkerAuthRepoStorageFn, + c.downstreamWorkers) if err != nil { return fmt.Errorf("failed to create worker handler service: %w", err) } diff --git a/internal/daemon/controller/handlers/workers/worker_service.go b/internal/daemon/controller/handlers/workers/worker_service.go index d1365f5a1a..ba9f653f70 100644 --- a/internal/daemon/controller/handlers/workers/worker_service.go +++ b/internal/daemon/controller/handlers/workers/worker_service.go @@ -61,6 +61,9 @@ var ( action.ReadCertificateAuthority, action.ReinitializeCertificateAuthority, } + // downstreamWorkers returns a list of worker ids which are directly + // connected downstream of the provided worker. + downstreamWorkers = emptyDownstreamWorkers ) func init() { @@ -70,6 +73,10 @@ func init() { } } +func emptyDownstreamWorkers(context.Context, string, common.Downstreamers) []string { + return nil +} + // Service handles request as described by the pbs.WorkerServiceServer interface. type Service struct { pbs.UnsafeWorkerServiceServer @@ -77,13 +84,14 @@ type Service struct { repoFn common.ServersRepoFactory workerAuthFn common.WorkerAuthRepoStorageFactory iamRepoFn common.IamRepoFactory + downstreams common.Downstreamers } var _ pbs.WorkerServiceServer = (*Service)(nil) // NewService returns a worker service which handles worker related requests to boundary. func NewService(ctx context.Context, repo common.ServersRepoFactory, iamRepoFn common.IamRepoFactory, - workerAuthFn common.WorkerAuthRepoStorageFactory, + workerAuthFn common.WorkerAuthRepoStorageFactory, ds common.Downstreamers, ) (Service, error) { const op = "workers.NewService" if repo == nil { @@ -95,7 +103,7 @@ func NewService(ctx context.Context, repo common.ServersRepoFactory, iamRepoFn c if workerAuthFn == nil { return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing worker auth repository") } - return Service{repoFn: repo, iamRepoFn: iamRepoFn, workerAuthFn: workerAuthFn}, nil + return Service{repoFn: repo, iamRepoFn: iamRepoFn, workerAuthFn: workerAuthFn, downstreams: ds}, nil } // ListWorkers implements the interface pbs.WorkerServiceServer. @@ -161,7 +169,7 @@ func (s Service) ListWorkers(ctx context.Context, req *pbs.ListWorkersRequest) ( outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authorizedActions)) } - item, err := toProto(ctx, item, outputOpts...) + item, err := s.toProto(ctx, item, outputOpts...) if err != nil { return nil, err } @@ -203,7 +211,7 @@ func (s Service) GetWorker(ctx context.Context, req *pbs.GetWorkerRequest) (*pbs outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, w.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, w, outputOpts...) + item, err := s.toProto(ctx, w, outputOpts...) if err != nil { return nil, err } @@ -288,7 +296,7 @@ func (s Service) createCommon(ctx context.Context, in *pb.Worker, act action.Typ outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, created.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, created, outputOpts...) + item, err := s.toProto(ctx, created, outputOpts...) if err != nil { return nil, err } @@ -342,7 +350,7 @@ func (s Service) UpdateWorker(ctx context.Context, req *pbs.UpdateWorkerRequest) outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, w.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, w, outputOpts...) + item, err := s.toProto(ctx, w, outputOpts...) if err != nil { return nil, err } @@ -378,7 +386,7 @@ func (s Service) AddWorkerTags(ctx context.Context, req *pbs.AddWorkerTagsReques if outputFields.Has(globals.AuthorizedActionsField) { outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, w.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, w, outputOpts...) + item, err := s.toProto(ctx, w, outputOpts...) if err != nil { return nil, err } @@ -414,7 +422,7 @@ func (s Service) SetWorkerTags(ctx context.Context, req *pbs.SetWorkerTagsReques if outputFields.Has(globals.AuthorizedActionsField) { outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, w.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, w, outputOpts...) + item, err := s.toProto(ctx, w, outputOpts...) if err != nil { return nil, err } @@ -450,7 +458,7 @@ func (s Service) RemoveWorkerTags(ctx context.Context, req *pbs.RemoveWorkerTags if outputFields.Has(globals.AuthorizedActionsField) { outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, w.GetPublicId(), IdActions).Strings())) } - item, err := toProto(ctx, w, outputOpts...) + item, err := s.toProto(ctx, w, outputOpts...) if err != nil { return nil, err } @@ -751,7 +759,7 @@ func certificateAuthorityToProto(in *types.RootCertificates) *pb.CertificateAuth return &pb.CertificateAuthority{Certs: certs} } -func toProto(ctx context.Context, in *server.Worker, opt ...handlers.Option) (*pb.Worker, error) { +func (s Service) toProto(ctx context.Context, in *server.Worker, opt ...handlers.Option) (*pb.Worker, error) { const op = "workers.toProto" opts := handlers.GetOpts(opt...) if opts.WithOutputFields == nil { @@ -766,6 +774,9 @@ func toProto(ctx context.Context, in *server.Worker, opt ...handlers.Option) (*p if outputFields.Has(globals.ScopeIdField) { out.ScopeId = in.GetScopeId() } + if outputFields.Has(globals.DirectlyConnectedDownstreamWorkers) { + out.DirectlyConnectedDownstreamWorkers = downstreamWorkers(ctx, in.GetPublicId(), s.downstreams) + } if outputFields.Has(globals.DescriptionField) && in.GetDescription() != "" { out.Description = wrapperspb.String(in.GetDescription()) } diff --git a/internal/daemon/controller/handlers/workers/worker_service_test.go b/internal/daemon/controller/handlers/workers/worker_service_test.go index eb3be18926..21c23ed77f 100644 --- a/internal/daemon/controller/handlers/workers/worker_service_test.go +++ b/internal/daemon/controller/handlers/workers/worker_service_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/hashicorp/boundary/globals" "github.com/hashicorp/boundary/internal/daemon/controller/auth" + "github.com/hashicorp/boundary/internal/daemon/controller/common" "github.com/hashicorp/boundary/internal/daemon/controller/handlers" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" @@ -87,6 +88,14 @@ func TestGet(t *testing.T) { repoFn := func() (*server.Repository, error) { return repo, nil } + oldDownstramFn := downstreamWorkers + t.Cleanup(func() { + downstreamWorkers = oldDownstramFn + }) + connectedDownstreams := []string{"first", "second", "third"} + downstreamWorkers = func(_ context.Context, id string, _ common.Downstreamers) []string { + return connectedDownstreams + } workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) require.NoError(t, err) @@ -123,7 +132,8 @@ func TestGet(t *testing.T) { ConfigTags: map[string]*structpb.ListValue{ "key": structListValue(t, "val"), }, - Type: KmsWorkerType, + Type: KmsWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, } var pkiWorkerKeyId string @@ -164,7 +174,8 @@ func TestGet(t *testing.T) { ConfigTags: map[string]*structpb.ListValue{ "config": structListValue(t, "test"), }, - Type: PkiWorkerType, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, } cases := []struct { @@ -207,7 +218,7 @@ func TestGet(t *testing.T) { } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { - s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Couldn't create new worker service.") got, err := s.GetWorker(auth.DisabledAuthTestContext(iamRepoFn, tc.scopeId), tc.req) @@ -235,6 +246,14 @@ func TestList(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, rw, kms) } + oldDownstramFn := downstreamWorkers + t.Cleanup(func() { + downstreamWorkers = oldDownstramFn + }) + connectedDownstreams := []string{"first", "second", "third"} + downstreamWorkers = func(_ context.Context, id string, _ common.Downstreamers) []string { + return connectedDownstreams + } workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) require.NoError(t, err) @@ -248,19 +267,20 @@ func TestList(t *testing.T) { 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()), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - Address: w.GetAddress(), - Type: KmsWorkerType, - LastStatusTime: w.GetLastStatusTime().GetTimestamp(), - ReleaseVersion: w.ReleaseVersion, + 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()), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + Address: w.GetAddress(), + Type: KmsWorkerType, + LastStatusTime: w.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: w.ReleaseVersion, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }) } @@ -268,19 +288,20 @@ func TestList(t *testing.T) { for i := 0; i < 10; i++ { w := server.TestPkiWorker(t, conn, wrap, server.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"}, - CreatedTime: w.CreateTime.GetTimestamp(), - UpdatedTime: w.UpdateTime.GetTimestamp(), - Version: w.GetVersion(), - Name: wrapperspb.String(w.GetName()), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - AuthorizedActions: testAuthorizedActions, - Address: w.GetAddress(), - Type: PkiWorkerType, - LastStatusTime: w.GetLastStatusTime().GetTimestamp(), - ReleaseVersion: w.ReleaseVersion, + 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()), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + AuthorizedActions: testAuthorizedActions, + Address: w.GetAddress(), + Type: PkiWorkerType, + LastStatusTime: w.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: w.ReleaseVersion, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }) } @@ -330,7 +351,7 @@ func TestList(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { assert, require := assert.New(t), require.New(t) - s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err, "Couldn't create new worker service.") // Test with a non-anon user @@ -383,7 +404,7 @@ func TestDelete(t *testing.T) { return workerAuthRepo, nil } - s, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") w := server.TestKmsWorker(t, conn, wrap) @@ -433,7 +454,6 @@ func TestDelete(t *testing.T) { } func TestUpdate(t *testing.T) { - t.Parallel() conn, _ := db.TestSetup(t, "postgres") wrapper := db.TestWrapper(t) kms := kms.TestKms(t, conn, wrapper) @@ -455,6 +475,14 @@ func TestUpdate(t *testing.T) { workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { return workerAuthRepo, nil } + oldDownstramFn := downstreamWorkers + t.Cleanup(func() { + downstreamWorkers = oldDownstramFn + }) + connectedDownstreams := []string{"first", "second", "third"} + downstreamWorkers = func(_ context.Context, id string, _ common.Downstreamers) []string { + return connectedDownstreams + } wkr := server.TestPkiWorker(t, conn, wrapper, server.WithName("default"), @@ -473,7 +501,7 @@ func TestUpdate(t *testing.T) { toMerge := &pbs.UpdateWorkerRequest{ Id: wkr.GetPublicId(), } - workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err) expectedScope := &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"} @@ -496,16 +524,17 @@ 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"), - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("name"), + Description: wrapperspb.String("desc"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -522,16 +551,17 @@ 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"), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("name"), + Description: wrapperspb.String("desc"), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -591,15 +621,16 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Description: wrapperspb.String("default"), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Description: wrapperspb.String("default"), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -615,15 +646,16 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("default"), - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("default"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -640,16 +672,17 @@ 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"), - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("updated"), + Description: wrapperspb.String("default"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -666,16 +699,17 @@ func TestUpdate(t *testing.T) { }, res: &pbs.UpdateWorkerResponse{ Item: &pb.Worker{ - Id: wkr.GetPublicId(), - ScopeId: wkr.GetScopeId(), - Scope: expectedScope, - Name: wrapperspb.String("default"), - ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, - Description: wrapperspb.String("notignored"), - CreatedTime: wkr.GetCreateTime().GetTimestamp(), - LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), - AuthorizedActions: testAuthorizedActions, - Type: PkiWorkerType, + Id: wkr.GetPublicId(), + ScopeId: wkr.GetScopeId(), + Scope: expectedScope, + Name: wrapperspb.String("default"), + ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, + Description: wrapperspb.String("notignored"), + CreatedTime: wkr.GetCreateTime().GetTimestamp(), + LastStatusTime: wkr.GetLastStatusTime().GetTimestamp(), + AuthorizedActions: testAuthorizedActions, + Type: PkiWorkerType, + DirectlyConnectedDownstreamWorkers: connectedDownstreams, }, }, }, @@ -850,7 +884,6 @@ 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) @@ -880,7 +913,7 @@ func TestUpdate_KMS(t *testing.T) { toMerge := &pbs.UpdateWorkerRequest{ Id: wkr.GetPublicId(), } - workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err) cases := []struct { @@ -936,7 +969,6 @@ func TestUpdate_KMS(t *testing.T) { } func TestUpdate_BadVersion(t *testing.T) { - t.Parallel() ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") rw := db.New(conn) @@ -961,7 +993,7 @@ func TestUpdate_BadVersion(t *testing.T) { return repo, nil } - workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Failed to create a new host set service.") wkr := server.TestPkiWorker(t, conn, wrapper) @@ -980,7 +1012,6 @@ func TestUpdate_BadVersion(t *testing.T) { } func TestCreateWorkerLed(t *testing.T) { - t.Parallel() conn, _ := db.TestSetup(t, "postgres") testRootWrapper := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, testRootWrapper) @@ -1000,7 +1031,7 @@ func TestCreateWorkerLed(t *testing.T) { return workerAuthRepo, nil } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") // Get an initial set of authorized node credentials @@ -1252,7 +1283,7 @@ func TestCreateWorkerLed(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, &db.Db{}, testKms) } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1285,7 +1316,7 @@ func TestCreateWorkerLed(t *testing.T) { return server.NewRepository(rw, rw, testKms) } } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1366,7 +1397,6 @@ func TestCreateWorkerLed(t *testing.T) { } func TestCreateControllerLed(t *testing.T) { - t.Parallel() conn, _ := db.TestSetup(t, "postgres") testRootWrapper := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, testRootWrapper) @@ -1386,7 +1416,7 @@ func TestCreateControllerLed(t *testing.T) { return rootStorage, nil } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") // Get an initial set of authorized node credentials @@ -1600,7 +1630,7 @@ func TestCreateControllerLed(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, &db.Db{}, testKms) } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1632,7 +1662,7 @@ func TestCreateControllerLed(t *testing.T) { return server.NewRepository(rw, rw, testKms) } } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn, nil) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1714,7 +1744,6 @@ func TestCreateControllerLed(t *testing.T) { } func TestService_AddWorkerTags(t *testing.T) { - t.Parallel() ctx := context.Background() assert, require := assert.New(t), require.New(t) @@ -1735,7 +1764,7 @@ func TestService_AddWorkerTags(t *testing.T) { workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { return workerAuthRepo, nil } - s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -1864,7 +1893,6 @@ func TestService_AddWorkerTags(t *testing.T) { } func TestService_SetWorkerTags(t *testing.T) { - t.Parallel() assert, require := assert.New(t), require.New(t) ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") @@ -1884,7 +1912,7 @@ func TestService_SetWorkerTags(t *testing.T) { workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { return workerAuthRepo, nil } - s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -2016,7 +2044,6 @@ func TestService_SetWorkerTags(t *testing.T) { } func TestService_RemoveWorkerTags(t *testing.T) { - t.Parallel() assert, require := assert.New(t), require.New(t) ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") @@ -2036,7 +2063,7 @@ func TestService_RemoveWorkerTags(t *testing.T) { workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { return workerAuthRepo, nil } - s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -2209,7 +2236,6 @@ func TestService_RemoveWorkerTags(t *testing.T) { } func TestReadCertificateAuthority(t *testing.T) { - t.Parallel() require, assert := require.New(t), assert.New(t) ctx := context.Background() wrapper := db.TestWrapper(t) @@ -2236,7 +2262,7 @@ func TestReadCertificateAuthority(t *testing.T) { _, err = rotation.RotateRootCertificates(ctx, workerAuthRepo) require.NoError(err) - testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err, "Error when getting new worker service.") tests := []struct { @@ -2286,7 +2312,6 @@ func TestReadCertificateAuthority(t *testing.T) { } func TestReinitializeCertificateAuthority(t *testing.T) { - t.Parallel() require, assert := require.New(t), assert.New(t) ctx := context.Background() wrapper := db.TestWrapper(t) @@ -2313,7 +2338,7 @@ func TestReinitializeCertificateAuthority(t *testing.T) { _, err = rotation.RotateRootCertificates(ctx, workerAuthRepo) require.NoError(err) - testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn, nil) require.NoError(err, "Error when getting new worker service.") tests := []struct { diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index 3fd7c4d2bf..7da1d4d7ae 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -5971,6 +5971,14 @@ "description": "Output only. The version of the Boundary binary the worker is running.", "readOnly": true }, + "directly_connected_downstream_workers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Output only. The ids of the workers directly connected to this worker.", + "readOnly": true + }, "authorized_actions": { "type": "array", "items": { diff --git a/internal/proto/controller/api/resources/workers/v1/worker.proto b/internal/proto/controller/api/resources/workers/v1/worker.proto index 5b02357f48..4ef5e474bf 100644 --- a/internal/proto/controller/api/resources/workers/v1/worker.proto +++ b/internal/proto/controller/api/resources/workers/v1/worker.proto @@ -89,6 +89,9 @@ message Worker { // Output only. The version of the Boundary binary the worker is running. string release_version = 190 [json_name = "release_version"]; // @gotags: `class:"public"` + // Output only. The ids of the workers directly connected to this worker. + repeated string directly_connected_downstream_workers = 200 [json_name = "directly_connected_downstream_workers"]; // @gotags: `class:"public"` + // 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/sdk/pbs/controller/api/resources/workers/worker.pb.go b/sdk/pbs/controller/api/resources/workers/worker.pb.go index 5b79b50a2f..8b8d4a7b11 100644 --- a/sdk/pbs/controller/api/resources/workers/worker.pb.go +++ b/sdk/pbs/controller/api/resources/workers/worker.pb.go @@ -78,6 +78,8 @@ type Worker struct { ApiTags map[string]*structpb.ListValue `protobuf:"bytes,180,rep,name=api_tags,proto3" json:"api_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 version of the Boundary binary the worker is running. ReleaseVersion string `protobuf:"bytes,190,opt,name=release_version,proto3" json:"release_version,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The ids of the workers directly connected to this worker. + DirectlyConnectedDownstreamWorkers []string `protobuf:"bytes,200,rep,name=directly_connected_downstream_workers,proto3" json:"directly_connected_downstream_workers,omitempty" class:"public"` // @gotags: `class:"public"` // 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"` } @@ -240,6 +242,13 @@ func (x *Worker) GetReleaseVersion() string { return "" } +func (x *Worker) GetDirectlyConnectedDownstreamWorkers() []string { + if x != nil { + return x.DirectlyConnectedDownstreamWorkers + } + return nil +} + func (x *Worker) GetAuthorizedActions() []string { if x != nil { return x.AuthorizedActions @@ -389,7 +398,7 @@ 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, 0xf2, 0x0b, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x0e, 0x0a, + 0x74, 0x6f, 0x22, 0xc9, 0x0c, 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, @@ -464,52 +473,57 @@ var file_controller_api_resources_workers_v1_worker_proto_rawDesc = []byte{ 0x52, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x29, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0xbe, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 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, 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, 0x1a, - 0x56, 0x0a, 0x0c, 0x41, 0x70, 0x69, 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, 0xcf, 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, - 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x14, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, - 0x32, 0x35, 0x36, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, - 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 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, 0x0d, 0x6e, 0x6f, 0x74, 0x42, 0x65, 0x66, - 0x6f, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x5f, 0x61, - 0x66, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x25, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, + 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, + 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x18, 0xc8, + 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x25, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x5f, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x73, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 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, 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, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x6e, 0x6f, 0x74, - 0x41, 0x66, 0x74, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x5e, 0x0a, 0x14, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x12, 0x46, 0x0a, 0x05, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x30, 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, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x52, 0x05, 0x63, 0x65, 0x72, 0x74, 0x73, 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, + 0x66, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x56, 0x0a, 0x0c, 0x41, 0x70, 0x69, 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, 0xcf, + 0x01, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x2a, + 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x73, 0x68, 0x61, + 0x32, 0x35, 0x36, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x53, 0x68, 0x61, 0x32, 0x35, 0x36, 0x12, 0x42, 0x0a, 0x0f, 0x6e, 0x6f, + 0x74, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x1e, 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, + 0x0d, 0x6e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x40, + 0x0a, 0x0e, 0x6e, 0x6f, 0x74, 0x5f, 0x61, 0x66, 0x74, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, + 0x18, 0x28, 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, 0x6e, 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, + 0x22, 0x5e, 0x0a, 0x14, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x05, 0x63, 0x65, 0x72, 0x74, + 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 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, 0x43, 0x65, + 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x05, 0x63, 0x65, 0x72, 0x74, 0x73, + 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 (