From 18dff62b7b07414b188a3e5b3f841035028f90b6 Mon Sep 17 00:00:00 2001 From: Irena Rindos Date: Thu, 8 Sep 2022 13:19:21 -0400 Subject: [PATCH] Merge BYOW GA branch to main (#2398) * feat(workers): Add ability to read and reinitialize cert authority (#2312) * feat(workers): Return Release Version on worker list and read (#2377) * feat(cli): Read and reinitialize worker certificate authority (#2387) --- CHANGELOG.md | 4 + api/workers/certificate.gen.go | 13 + api/workers/certificate_authority.gen.go | 25 + api/workers/certificate_authority_actions.go | 95 +++ api/workers/worker.gen.go | 1 + globals/fields.go | 1 + internal/api/genapi/input.go | 53 +- internal/api/genapi/templates.go | 27 +- internal/cmd/commands.go | 17 + .../workerscmd/certificate-authority.go | 223 ++++++ internal/cmd/commands/workerscmd/funcs.go | 8 + .../daemon/cluster/handlers/worker_service.go | 3 +- internal/daemon/controller/controller.go | 2 +- internal/daemon/controller/handler.go | 2 +- .../handlers/scopes/scope_service_test.go | 2 + .../handlers/workers/worker_service.go | 135 +++- .../handlers/workers/worker_service_test.go | 265 ++++++- internal/daemon/worker/status.go | 15 +- .../oss/postgres/34/04_views.up.sql | 1 + .../01_server_worker_release_version.up.sql | 57 ++ internal/gen/controller.swagger.json | 109 +++ .../api/services/worker_service.pb.go | 659 +++++++++++++----- .../api/services/worker_service.pb.gw.go | 192 +++++ .../api/services/worker_service_grpc.pb.go | 76 ++ internal/gen/controller/servers/servers.pb.go | 26 +- internal/perms/acl_test.go | 4 +- .../api/resources/workers/v1/worker.proto | 21 + .../api/services/v1/worker_service.proto | 38 + .../proto/controller/servers/v1/servers.proto | 3 + .../storage/servers/store/v1/worker.proto | 4 + internal/server/job/rotate_roots_job.go | 2 +- internal/server/options.go | 8 + internal/server/options_test.go | 6 + internal/server/repository_worker.go | 4 +- internal/server/repository_worker_test.go | 13 +- internal/server/repository_workerauth.go | 7 +- internal/server/repository_workerauth_test.go | 10 +- internal/server/root_certificate.go | 8 +- internal/server/service_reinitialize_roots.go | 29 + .../server/service_reinitialize_roots_test.go | 84 +++ internal/server/service_rotate_roots.go | 19 +- internal/server/service_rotate_roots_test.go | 29 +- internal/server/store/worker.pb.go | 39 +- internal/server/testing.go | 6 +- internal/server/worker.go | 11 +- internal/server/worker_test.go | 3 + internal/server/workerauth_store_test.go | 4 +- internal/types/action/action.go | 207 +++--- internal/types/resource/resource.go | 3 +- .../api/resources/workers/worker.pb.go | 290 ++++++-- 50 files changed, 2401 insertions(+), 462 deletions(-) create mode 100644 api/workers/certificate.gen.go create mode 100644 api/workers/certificate_authority.gen.go create mode 100644 api/workers/certificate_authority_actions.go create mode 100644 internal/cmd/commands/workerscmd/certificate-authority.go create mode 100644 internal/db/schema/migrations/oss/postgres/51/01_server_worker_release_version.up.sql create mode 100644 internal/server/service_reinitialize_roots.go create mode 100644 internal/server/service_reinitialize_roots_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index ca2c5538a..54ef95d9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ## Next +### New and Improved +* Workers: Added the ability to read and reinitialize the Worker certificate authority ([PR1](https://github.com/hashicorp/boundary/pull/2312), [PR2](https://github.com/hashicorp/boundary/pull/2387)) +* Workers: Return the worker Boundary binary version on worker list and read ([PR](https://github.com/hashicorp/boundary/pull/2377)) + ## 0.10.4 (Unreleased) ### New and Improved diff --git a/api/workers/certificate.gen.go b/api/workers/certificate.gen.go new file mode 100644 index 000000000..6527a3277 --- /dev/null +++ b/api/workers/certificate.gen.go @@ -0,0 +1,13 @@ +// Code generated by "make api"; DO NOT EDIT. +package workers + +import ( + "time" +) + +type Certificate struct { + Id string `json:"id,omitempty"` + PublicKeySha256 string `json:"public_key_sha256,omitempty"` + NotBeforeTime time.Time `json:"not_before_time,omitempty"` + NotAfterTime time.Time `json:"not_after_time,omitempty"` +} diff --git a/api/workers/certificate_authority.gen.go b/api/workers/certificate_authority.gen.go new file mode 100644 index 000000000..eb14c28b2 --- /dev/null +++ b/api/workers/certificate_authority.gen.go @@ -0,0 +1,25 @@ +// Code generated by "make api"; DO NOT EDIT. +package workers + +import ( + "github.com/hashicorp/boundary/api" +) + +type CertificateAuthority struct { + Certs []*Certificate `json:"certs,omitempty"` + + response *api.Response +} + +type CertificateAuthorityReadResult struct { + Item *CertificateAuthority + response *api.Response +} + +func (n CertificateAuthorityReadResult) GetItem() *CertificateAuthority { + return n.Item +} + +func (n CertificateAuthorityReadResult) GetResponse() *api.Response { + return n.response +} diff --git a/api/workers/certificate_authority_actions.go b/api/workers/certificate_authority_actions.go new file mode 100644 index 000000000..dd3e403f9 --- /dev/null +++ b/api/workers/certificate_authority_actions.go @@ -0,0 +1,95 @@ +package workers + +import ( + "context" + "fmt" + "net/url" +) + +type CertificateAuthorityReinitializeResult = CertificateAuthorityReadResult + +func (c *Client) ReinitializeCA(ctx context.Context, scopeId string, opt ...Option) (*CertificateAuthorityReinitializeResult, error) { + if scopeId == "" { + return nil, fmt.Errorf("empty scopeId value passed into ReinitializeCA request") + } + + opts, apiOpts := getOpts(opt...) + + if c.client == nil { + return nil, fmt.Errorf("nil client") + } + opts.queryMap["scope_id"] = scopeId + + req, err := c.client.NewRequest(ctx, "POST", "workers:reinitialize-certificate-authority", nil, apiOpts...) + if err != nil { + return nil, fmt.Errorf("error creating ReinitializeCA request: %w", err) + } + + if len(opts.queryMap) > 0 { + q := url.Values{} + for k, v := range opts.queryMap { + q.Add(k, v) + } + req.URL.RawQuery = q.Encode() + } + + resp, err := c.client.Do(req) + if err != nil { + return nil, fmt.Errorf("error performing client request during ReinitializeCA call: %w", err) + } + + target := new(CertificateAuthorityReinitializeResult) + target.Item = new(CertificateAuthority) + apiErr, err := resp.Decode(target.Item) + if err != nil { + return nil, fmt.Errorf("error decoding ReinitializeCA response: %w", err) + } + if apiErr != nil { + return nil, apiErr + } + target.response = resp + return target, nil +} + +func (c *Client) ReadCA(ctx context.Context, scopeId string, opt ...Option) (*CertificateAuthorityReadResult, error) { + if scopeId == "" { + return nil, fmt.Errorf("empty scopeId value passed into ReadCA request") + } + + opts, apiOpts := getOpts(opt...) + opts.queryMap["scope_id"] = scopeId + + if c.client == nil { + return nil, fmt.Errorf("nil client") + } + + req, err := c.client.NewRequest(ctx, "GET", "workers:read-certificate-authority", nil, apiOpts...) + if err != nil { + return nil, fmt.Errorf("error creating ReadCA request: %w", err) + } + + if len(opts.queryMap) > 0 { + q := url.Values{} + for k, v := range opts.queryMap { + q.Add(k, v) + } + req.URL.RawQuery = q.Encode() + } + + resp, err := c.client.Do(req) + if err != nil { + return nil, fmt.Errorf("error performing client request during ReadCA call: %w", err) + } + + target := new(CertificateAuthorityReadResult) + target.Item = new(CertificateAuthority) + apiErr, err := resp.Decode(target.Item) + if err != nil { + return nil, fmt.Errorf("error decoding ReadCA response: %w", err) + } + if apiErr != nil { + return nil, apiErr + } + target.response = resp + return target, nil +} diff --git a/api/workers/worker.gen.go b/api/workers/worker.gen.go index ba7bf15ad..8e343a9c3 100644 --- a/api/workers/worker.gen.go +++ b/api/workers/worker.gen.go @@ -30,6 +30,7 @@ type Worker struct { ActiveConnectionCount uint32 `json:"active_connection_count,omitempty"` Type string `json:"type,omitempty"` ApiTags map[string][]string `json:"api_tags,omitempty"` + ReleaseVersion string `json:"release_version,omitempty"` AuthorizedActions []string `json:"authorized_actions,omitempty"` response *api.Response diff --git a/globals/fields.go b/globals/fields.go index af5a47556..edaf5f902 100644 --- a/globals/fields.go +++ b/globals/fields.go @@ -85,4 +85,5 @@ const ( WorkerProvidedConfigurationField = "worker_provided_configuration" ActiveConnectionCountField = "active_connection_count" ControllerGeneratedActivationToken = "controller_generated_activation_token" + ReleaseVersionField = "release_version" ) diff --git a/internal/api/genapi/input.go b/internal/api/genapi/input.go index f33f0cce3..3936022ea 100644 --- a/internal/api/genapi/input.go +++ b/internal/api/genapi/input.go @@ -25,6 +25,14 @@ import ( "google.golang.org/protobuf/proto" ) +const ( + ReadResponseType = "read" + UpdateResponseType = "update" + CreateResponseType = "create" + ListResponseType = "list" + DeleteResponseType = "delete" +) + type sliceSubtypeInfo struct { SliceType string VarName string @@ -109,7 +117,7 @@ type structInfo struct { fieldOverrides []fieldInfo // createResponseTypes controls for which structs response types are created - createResponseTypes bool + createResponseTypes []string // fieldFilter is a set of field names that will not result in generated API // fields @@ -175,7 +183,7 @@ var inputStructs = []*structInfo{ }, }, versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // User related resources @@ -203,7 +211,7 @@ var inputStructs = []*structInfo{ }, pluralResourceName: "users", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // Group related resources @@ -231,7 +239,7 @@ var inputStructs = []*structInfo{ }, pluralResourceName: "groups", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // Role related resources @@ -273,7 +281,7 @@ var inputStructs = []*structInfo{ }, pluralResourceName: "roles", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // Auth Methods related resources @@ -332,7 +340,7 @@ var inputStructs = []*structInfo{ }, pluralResourceName: "auth-methods", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // Accounts @@ -368,7 +376,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "accounts", parentTypeName: "auth-method", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, // Managed Groups { @@ -400,7 +408,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "managed-groups", parentTypeName: "auth-method", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, // Auth Tokens { @@ -413,7 +421,7 @@ var inputStructs = []*structInfo{ listTemplate, }, pluralResourceName: "auth-tokens", - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, // Credentials @@ -459,7 +467,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "credential-stores", parentTypeName: "scope", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, fieldOverrides: []fieldInfo{ { @@ -501,7 +509,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "credential-libraries", parentTypeName: "credential-store", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, { inProto: &credentials.UsernamePasswordAttributes{}, @@ -574,7 +582,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "credentials", parentTypeName: "credential-store", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, // Host related resources @@ -625,7 +633,7 @@ var inputStructs = []*structInfo{ }, pluralResourceName: "host-catalogs", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, { @@ -642,7 +650,7 @@ var inputStructs = []*structInfo{ pluralResourceName: "hosts", parentTypeName: "host-catalog", versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, { inProto: &hosts.StaticHostAttributes{}, @@ -673,7 +681,7 @@ var inputStructs = []*structInfo{ }, }, versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, }, { inProto: &targets.HostSet{}, @@ -807,7 +815,7 @@ var inputStructs = []*structInfo{ }, }, versionEnabled: true, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, }, { @@ -835,10 +843,19 @@ var inputStructs = []*structInfo{ }, }, pluralResourceName: "sessions", - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, fieldFilter: []string{"private_key"}, recursiveListing: true, }, + { + inProto: &workers.Certificate{}, + outFile: "workers/certificate.gen.go", + }, + { + inProto: &workers.CertificateAuthority{}, + outFile: "workers/certificate_authority.gen.go", + createResponseTypes: []string{ReadResponseType}, + }, { inProto: &workers.Worker{}, outFile: "workers/worker.gen.go", @@ -890,7 +907,7 @@ var inputStructs = []*structInfo{ VarName: "apiTags", }, }, - createResponseTypes: true, + createResponseTypes: []string{CreateResponseType, ReadResponseType, UpdateResponseType, DeleteResponseType, ListResponseType}, recursiveListing: true, versionEnabled: true, }, diff --git a/internal/api/genapi/templates.go b/internal/api/genapi/templates.go index d67f11f96..53eb935ae 100644 --- a/internal/api/genapi/templates.go +++ b/internal/api/genapi/templates.go @@ -10,6 +10,7 @@ import ( "strings" "text/template" + "github.com/hashicorp/go-secure-stdlib/strutil" "github.com/iancoleman/strcase" ) @@ -46,7 +47,7 @@ type templateInput struct { SliceSubtypes map[string]sliceSubtypeInfo ExtraFields []fieldInfo VersionEnabled bool - CreateResponseTypes bool + CreateResponseTypes []string RecursiveListing bool } @@ -570,7 +571,15 @@ func (c *Client) {{ $fullName }}(ctx context.Context, id string, version uint32, {{ end }} `)) -var structTemplate = template.Must(template.New("").Parse( +func hasResponseType(types []string, typ string) bool { + return strutil.StrListContains(types, typ) +} + +var structTemplate = template.Must(template.New("").Funcs( + template.FuncMap{ + "hasResponseType": hasResponseType, + }, +).Parse( fmt.Sprint(`// Code generated by "make api"; DO NOT EDIT. package {{ .Package }} @@ -587,14 +596,14 @@ import ( type {{ .Name }} struct { {{ range .Fields }} {{ .Name }} {{ .FieldType }} `, "`json:\"{{ .ProtoName }},omitempty\"`", `{{ end }} -{{ if .CreateResponseTypes }} +{{ if ( not ( eq ( len ( .CreateResponseTypes ) ) 0 ) )}} response *api.Response {{ else if ( eq .Name "Error" ) }} response *Response {{ end }} } -{{ if .CreateResponseTypes }} +{{ if ( hasResponseType .CreateResponseTypes "read" ) }} type {{ .Name }}ReadResult struct { Item *{{ .Name }} response *api.Response @@ -607,10 +616,11 @@ func (n {{ .Name }}ReadResult) GetItem() *{{ .Name }} { func (n {{ .Name }}ReadResult) GetResponse() *api.Response { return n.response } +{{ end }} +{{ if ( hasResponseType .CreateResponseTypes "create" ) }} type {{ .Name }}CreateResult = {{ .Name }}ReadResult {{ end }} +{{ if ( hasResponseType .CreateResponseTypes "update" ) }} type {{ .Name }}UpdateResult = {{ .Name }}ReadResult {{ end }} -type {{ .Name }}CreateResult = {{ .Name }}ReadResult -type {{ .Name }}UpdateResult = {{ .Name }}ReadResult - +{{ if ( hasResponseType .CreateResponseTypes "delete" ) }} type {{ .Name }}DeleteResult struct { response *api.Response } @@ -623,7 +633,8 @@ func (n {{ .Name }}DeleteResult) GetItem() interface{} { func (n {{ .Name }}DeleteResult) GetResponse() *api.Response { return n.response } - +{{ end }} +{{ if ( hasResponseType .CreateResponseTypes "list" ) }} type {{ .Name }}ListResult struct { Items []*{{ .Name }} response *api.Response diff --git a/internal/cmd/commands.go b/internal/cmd/commands.go index d0f53a2ea..be5b704f0 100644 --- a/internal/cmd/commands.go +++ b/internal/cmd/commands.go @@ -1162,6 +1162,23 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) { Func: "remove-worker-tags", }, nil }, + "workers certificate-authority": func() (cli.Command, error) { + return &workerscmd.WorkerCACommand{ + Command: base.NewCommand(ui), + }, nil + }, + "workers certificate-authority read": func() (cli.Command, error) { + return &workerscmd.WorkerCACommand{ + Command: base.NewCommand(ui), + Func: "read", + }, nil + }, + "workers certificate-authority reinitialize": func() (cli.Command, error) { + return &workerscmd.WorkerCACommand{ + Command: base.NewCommand(ui), + Func: "reinitialize", + }, nil + }, } for _, fn := range extraCommandsFuncs { diff --git a/internal/cmd/commands/workerscmd/certificate-authority.go b/internal/cmd/commands/workerscmd/certificate-authority.go new file mode 100644 index 000000000..cafec32ae --- /dev/null +++ b/internal/cmd/commands/workerscmd/certificate-authority.go @@ -0,0 +1,223 @@ +package workerscmd + +import ( + "errors" + "fmt" + + "github.com/hashicorp/boundary/api" + "github.com/hashicorp/boundary/api/workers" + "github.com/hashicorp/boundary/internal/cmd/base" + "github.com/hashicorp/boundary/internal/cmd/common" + "github.com/hashicorp/go-secure-stdlib/strutil" + "github.com/mitchellh/cli" + "github.com/mitchellh/go-wordwrap" + "github.com/posener/complete" +) + +var ( + _ cli.Command = (*WorkerCACommand)(nil) + _ cli.CommandAutocomplete = (*WorkerCACommand)(nil) +) + +type WorkerCACommand struct { + *base.Command + + Func string +} + +func (c *WorkerCACommand) Synopsis() string { + switch c.Func { + case "read": + return wordwrap.WrapString("Read the certificate authority used to authorize Boundary workers", base.TermWidth) + case "reinitialize": + return wordwrap.WrapString("Reinitialize the certificate authority used to authorize Boundary workers", base.TermWidth) + } + return wordwrap.WrapString("Manage the certificate authority used to authorize Boundary workers", base.TermWidth) +} + +var flagsCertificateAuthority = map[string][]string{ + "reinitialize": {"scope-id"}, + "read": {"scope-id"}, +} + +func (c *WorkerCACommand) Help() string { + switch c.Func { + case "read": + return base.WrapForHelpText([]string{ + "Usage: boundary workers certificate-authority read", + "", + " Read the certificate authority used to authorize Boundary workers:", + "", + ` $ boundary workers certificate-authority read`, + "", + "", + }) + c.Flags().Help() + case "reinitialize": + return base.WrapForHelpText([]string{ + "Usage: boundary workers certificate-authority reinitialize", + "", + " Reinitialize the certificate authority used to authorize Boundary workers:", + "", + ` $ boundary workers certificate-authority reinitialize`, + "", + "", + }) + c.Flags().Help() + } + return base.WrapForHelpText([]string{ + "Usage: boundary workers certificate-authority [options]", + "", + " This command allows for management of the certificate authority used to authorize Boundary workers. Example:", + "", + " Read the current certificate authority:", + "", + ` $ boundary workers certificate-authority read`, + "", + " Please see the certificate-authority subcommand help for detailed usage information.", + "", + "", + }) +} + +func (c *WorkerCACommand) Flags() *base.FlagSets { + set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat) + f := set.NewFlagSet("Worker Certificate Authority Options") + common.PopulateCommonFlags(c.Command, f, "certificate authority", flagsCertificateAuthority, c.Func) + + return set +} + +func (c *WorkerCACommand) AutocompleteArgs() complete.Predictor { + initFlags() + return complete.PredictAnything +} + +func (c *WorkerCACommand) AutocompleteFlags() complete.Flags { + initFlags() + return c.Flags().Completions() +} + +func (c *WorkerCACommand) checkFuncError(err error) int { + if err == nil { + return 0 + } + if apiErr := api.AsServerError(err); apiErr != nil { + c.PrintApiError(apiErr, fmt.Sprintf("Error from controller when performing certificate authority %s", c.Func)) + return base.CommandApiError + } + c.PrintCliError(fmt.Errorf("Error trying to %s certificate authority : %s", c.Func, err.Error())) + return base.CommandCliError +} + +func (c *WorkerCACommand) printListTable(item *workers.CertificateAuthority) string { + if item == nil { + return "No certificate authority found" + } + + var output []string + output = []string{ + "", + "Worker certificate authority information:", + } + + for k, ca := range item.Certs { + if k > 0 { + output = append(output, "") + } + if ca.Id != "" { + output = append(output, + fmt.Sprintf(" ID: %s", ca.Id), + ) + } else { + output = append(output, + fmt.Sprintf(" ID: %s", "(not available)"), + ) + } + if ca.PublicKeySha256 != "" { + output = append(output, + fmt.Sprintf(" Public Key Sha256: %s", ca.PublicKeySha256), + ) + } + if !ca.NotBeforeTime.IsZero() { + output = append(output, + fmt.Sprintf(" Not Before Time: %s", ca.NotBeforeTime), + ) + } + if !ca.NotAfterTime.IsZero() { + output = append(output, + fmt.Sprintf(" Not After Time: %s", ca.NotAfterTime), + ) + } + } + return base.WrapForHelpText(output) +} + +func (c *WorkerCACommand) Run(args []string) int { + initFlags() + f := c.Flags() + + if err := f.Parse(args); err != nil { + c.PrintCliError(err) + return base.CommandUserError + } + + if strutil.StrListContains(flagsMap[c.Func], "scope-id") { + switch c.Func { + + case "read": + case "reinitialize": + if c.FlagScopeId == "" { + c.PrintCliError(errors.New("Scope ID must be passed in via -scope-id or BOUNDARY_SCOPE_ID")) + return base.CommandUserError + } + + } + } + + client, err := c.Client() + if c.WrapperCleanupFunc != nil { + defer func() { + if err := c.WrapperCleanupFunc(); err != nil { + c.PrintCliError(fmt.Errorf("Error cleaning kms wrapper: %w", err)) + } + }() + } + if err != nil { + c.PrintCliError(fmt.Errorf("Error creating API client: %w", err)) + return base.CommandCliError + } + workersClient := workers.NewClient(client) + + var resp *api.Response + var item *workers.CertificateAuthority + + switch c.Func { + case "": + return cli.RunResultHelp + case "read": + readResult, err := workersClient.ReadCA(c.Context, c.FlagScopeId) + if exitCode := c.checkFuncError(err); exitCode > 0 { + return exitCode + } + resp = readResult.GetResponse() + item = readResult.GetItem() + case "reinitialize": + reinitializeResult, err := workersClient.ReinitializeCA(c.Context, c.FlagScopeId) + if exitCode := c.checkFuncError(err); exitCode > 0 { + return exitCode + } + resp = reinitializeResult.GetResponse() + item = reinitializeResult.GetItem() + } + + switch base.Format(c.UI) { + case "table": + c.UI.Output(c.printListTable(item)) + + case "json": + if ok := c.PrintJsonItem(resp); !ok { + return base.CommandCliError + } + } + + return base.CommandSuccess +} diff --git a/internal/cmd/commands/workerscmd/funcs.go b/internal/cmd/commands/workerscmd/funcs.go index cb8027760..2fb5a3646 100644 --- a/internal/cmd/commands/workerscmd/funcs.go +++ b/internal/cmd/commands/workerscmd/funcs.go @@ -215,6 +215,11 @@ func (c *Command) printListTable(items []*workers.Worker) string { fmt.Sprintf(" Address: %s", item.Address), ) } + if item.ReleaseVersion != "" { + output = append(output, + fmt.Sprintf(" ReleaseVersion: %s", item.ReleaseVersion), + ) + } if !item.LastStatusTime.IsZero() { output = append(output, fmt.Sprintf(" Last Status Time: %s", item.LastStatusTime.Format(time.RFC1123)), @@ -258,6 +263,9 @@ func printItemTable(item *workers.Worker, resp *api.Response) string { if item.Address != "" { nonAttributeMap["Address"] = item.Address } + if item.ReleaseVersion != "" { + nonAttributeMap["Release Version"] = item.ReleaseVersion + } if !item.LastStatusTime.IsZero() { nonAttributeMap["Last Status Time"] = item.LastStatusTime } diff --git a/internal/daemon/cluster/handlers/worker_service.go b/internal/daemon/cluster/handlers/worker_service.go index 50fc98af8..3b2ae393b 100644 --- a/internal/daemon/cluster/handlers/worker_service.go +++ b/internal/daemon/cluster/handlers/worker_service.go @@ -96,7 +96,8 @@ func (ws *workerServiceServer) Status(ctx context.Context, req *pbs.StatusReques server.WithName(wStat.GetName()), server.WithDescription(wStat.GetDescription()), server.WithAddress(wStat.GetAddress()), - server.WithWorkerTags(workerTags...)) + server.WithWorkerTags(workerTags...), + server.WithReleaseVersion(wStat.ReleaseVersion)) opts := []server.Option{server.WithUpdateTags(req.GetUpdateTags())} if wStat.GetPublicId() != "" { opts = append(opts, server.WithPublicId(wStat.GetPublicId())) diff --git a/internal/daemon/controller/controller.go b/internal/daemon/controller/controller.go index ef2123fdc..1c9447466 100644 --- a/internal/daemon/controller/controller.go +++ b/internal/daemon/controller/controller.go @@ -352,7 +352,7 @@ func New(ctx context.Context, conf *Config) (*Controller, error) { if err != nil { return nil, fmt.Errorf("unable to instantiate worker auth repository: %w", err) } - err = server.RotateRoots(ctx, serversRepo) + _, err = server.RotateRoots(ctx, serversRepo) if err != nil { return nil, fmt.Errorf("unable to ensure worker auth roots exist: %w", err) } diff --git a/internal/daemon/controller/handler.go b/internal/daemon/controller/handler.go index 4d8292215..257acc161 100644 --- a/internal/daemon/controller/handler.go +++ b/internal/daemon/controller/handler.go @@ -226,7 +226,7 @@ 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) + ws, err := workers.NewService(c.baseContext, c.ServersRepoFn, c.IamRepoFn, c.WorkerAuthRepoStorageFn) if err != nil { return fmt.Errorf("failed to create worker handler service: %w", err) } diff --git a/internal/daemon/controller/handlers/scopes/scope_service_test.go b/internal/daemon/controller/handlers/scopes/scope_service_test.go index cb38906f4..6bbe79d9e 100644 --- a/internal/daemon/controller/handlers/scopes/scope_service_test.go +++ b/internal/daemon/controller/handlers/scopes/scope_service_test.go @@ -100,6 +100,8 @@ var globalAuthorizedCollectionActions = map[string]*structpb.ListValue{ structpb.NewStringValue("create:controller-led"), structpb.NewStringValue("create:worker-led"), structpb.NewStringValue("list"), + structpb.NewStringValue("read-certificate-authority"), + structpb.NewStringValue("reinitialize-certificate-authority"), }, }, } diff --git a/internal/daemon/controller/handlers/workers/worker_service.go b/internal/daemon/controller/handlers/workers/worker_service.go index 215a6b582..ea2d4c956 100644 --- a/internal/daemon/controller/handlers/workers/worker_service.go +++ b/internal/daemon/controller/handlers/workers/worker_service.go @@ -2,6 +2,8 @@ package workers import ( "context" + "crypto/sha256" + "encoding/hex" "fmt" "strings" @@ -56,6 +58,8 @@ var ( action.CreateControllerLed, action.CreateWorkerLed, action.List, + action.ReadCertificateAuthority, + action.ReinitializeCertificateAuthority, } ) @@ -70,14 +74,17 @@ func init() { type Service struct { pbs.UnsafeWorkerServiceServer - repoFn common.ServersRepoFactory - iamRepoFn common.IamRepoFactory + repoFn common.ServersRepoFactory + workerAuthFn common.WorkerAuthRepoStorageFactory + iamRepoFn common.IamRepoFactory } 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) (Service, error) { +func NewService(ctx context.Context, repo common.ServersRepoFactory, iamRepoFn common.IamRepoFactory, + workerAuthFn common.WorkerAuthRepoStorageFactory, +) (Service, error) { const op = "workers.NewService" if repo == nil { return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing server repository") @@ -85,7 +92,10 @@ func NewService(ctx context.Context, repo common.ServersRepoFactory, iamRepoFn c if iamRepoFn == nil { return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing iam repository") } - return Service{repoFn: repo, iamRepoFn: iamRepoFn}, nil + if workerAuthFn == nil { + return Service{}, errors.New(ctx, errors.InvalidParameter, op, "missing worker auth repository") + } + return Service{repoFn: repo, iamRepoFn: iamRepoFn, workerAuthFn: workerAuthFn}, nil } // ListWorkers implements the interface pbs.WorkerServiceServer. @@ -448,6 +458,54 @@ func (s Service) RemoveWorkerTags(ctx context.Context, req *pbs.RemoveWorkerTags return &pbs.RemoveWorkerTagsResponse{Item: item}, nil } +// ReadCertificateAuthority will list the next and current certificates for the worker certificate authority +func (s Service) ReadCertificateAuthority(ctx context.Context, req *pbs.ReadCertificateAuthorityRequest) (*pbs.ReadCertificateAuthorityResponse, error) { + const op = "workers.(Service).ReadCertificateAuthority" + if err := validateReadCaRequest(req); err != nil { + return nil, err + } + + authResults := s.authResult(ctx, req.GetScopeId(), action.ReadCertificateAuthority) + if authResults.Error != nil { + return nil, authResults.Error + } + + caProto, err := s.listCertificateAuthorityFromRepo(ctx) + if err != nil { + return nil, err + } + + ca := certificateAuthorityToProto(caProto) + return &pbs.ReadCertificateAuthorityResponse{Item: ca}, nil +} + +// ReinitializeCertificateAuthority will delete and regenerate the next and current certificates for the worker certificate authority +func (s Service) ReinitializeCertificateAuthority(ctx context.Context, req *pbs.ReinitializeCertificateAuthorityRequest) (*pbs.ReinitializeCertificateAuthorityResponse, error) { + const op = "workers.(Service).ReinitializeCertificateAuthority" + if err := validateReinitCaRequest(req); err != nil { + return nil, err + } + + authResults := s.authResult(ctx, req.GetScopeId(), action.ReinitializeCertificateAuthority) + if authResults.Error != nil { + return nil, authResults.Error + } + + repo, err := s.workerAuthFn() + if err != nil { + return nil, err + } + + rootCerts, err := server.ReinitializeRoots(ctx, repo) + if err != nil { + return nil, err + } + + ca := certificateAuthorityToProto(rootCerts) + + return &pbs.ReinitializeCertificateAuthorityResponse{Item: ca}, nil +} + func (s Service) listFromRepo(ctx context.Context, scopeIds []string) ([]*server.Worker, error) { repo, err := s.repoFn() if err != nil { @@ -633,7 +691,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. var parentId string opts := []auth.Option{auth.WithType(resource.Worker), auth.WithAction(a)} switch a { - case action.List, action.CreateWorkerLed, action.CreateControllerLed: + case action.List, action.CreateWorkerLed, action.CreateControllerLed, action.ReadCertificateAuthority, action.ReinitializeCertificateAuthority: parentId = id default: w, err := repo.LookupWorker(ctx, id) @@ -652,6 +710,47 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. return auth.Verify(ctx, opts...) } +func (s Service) listCertificateAuthorityFromRepo(ctx context.Context) (*types.RootCertificates, error) { + repo, err := s.workerAuthFn() + if err != nil { + return nil, err + } + + certs := &types.RootCertificates{Id: server.CaId} + err = repo.Load(ctx, certs) + if err != nil { + return nil, err + } + + return certs, nil +} + +func certificateAuthorityToProto(in *types.RootCertificates) *pb.CertificateAuthority { + certs := make([]*pb.Certificate, 0) + + current := in.GetCurrent() + currentSha := sha256.Sum256(current.PublicKeyPkix) + currentCert := &pb.Certificate{ + Id: string(server.CurrentState), + PublicKeySha256: hex.EncodeToString(currentSha[:]), + NotBeforeTime: current.NotBefore, + NotAfterTime: current.NotAfter, + } + certs = append(certs, currentCert) + + next := in.GetNext() + nextSha := sha256.Sum256(next.PublicKeyPkix) + nextCert := &pb.Certificate{ + Id: string(server.NextState), + PublicKeySha256: hex.EncodeToString(nextSha[:]), + NotBeforeTime: next.NotBefore, + NotAfterTime: next.NotAfter, + } + certs = append(certs, nextCert) + + return &pb.CertificateAuthority{Certs: certs} +} + func toProto(ctx context.Context, in *server.Worker, opt ...handlers.Option) (*pb.Worker, error) { const op = "workers.toProto" opts := handlers.GetOpts(opt...) @@ -679,6 +778,9 @@ func toProto(ctx context.Context, in *server.Worker, opt ...handlers.Option) (*p if outputFields.Has(globals.UpdatedTimeField) { out.UpdatedTime = in.GetUpdateTime().GetTimestamp() } + if outputFields.Has(globals.ReleaseVersionField) { + out.ReleaseVersion = in.GetReleaseVersion() + } if outputFields.Has(globals.VersionField) { out.Version = in.GetVersion() } @@ -990,3 +1092,26 @@ func validateRemoveTagsRequest(req *pbs.RemoveWorkerTagsRequest) error { } return nil } + +func validateReadCaRequest(req *pbs.ReadCertificateAuthorityRequest) error { + badFields := map[string]string{} + if req.GetScopeId() != scope.Global.String() { + badFields["scope_id"] = "Must be 'global' when reading." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Error in provided request.", badFields) + } + return nil +} + +func validateReinitCaRequest(req *pbs.ReinitializeCertificateAuthorityRequest) error { + badFields := map[string]string{} + if req.GetScopeId() != scope.Global.String() { + badFields["scope_id"] = "Must be 'global' when reinitializing certs." + } + if len(badFields) > 0 { + return handlers.InvalidArgumentErrorf("Error in provided request.", badFields) + } + + return nil +} diff --git a/internal/daemon/controller/handlers/workers/worker_service_test.go b/internal/daemon/controller/handlers/workers/worker_service_test.go index 7da8bc177..d4c6acff1 100644 --- a/internal/daemon/controller/handlers/workers/worker_service_test.go +++ b/internal/daemon/controller/handlers/workers/worker_service_test.go @@ -73,6 +73,7 @@ func equalTags(t *testing.T, expected map[string]*structpb.ListValue, actual map } func TestGet(t *testing.T) { + ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") wrap := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, wrap) @@ -87,6 +88,12 @@ func TestGet(t *testing.T) { return repo, nil } + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + kmsWorker := server.TestKmsWorker(t, conn, wrap, server.WithName("test kms worker names"), server.WithDescription("test kms worker description"), @@ -109,6 +116,7 @@ func TestGet(t *testing.T) { ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, AuthorizedActions: strutil.StrListDelete(kmsAuthzActions, action.Update.String()), LastStatusTime: kmsWorker.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: kmsWorker.ReleaseVersion, CanonicalTags: map[string]*structpb.ListValue{ "key": structListValue(t, "val"), }, @@ -149,6 +157,7 @@ func TestGet(t *testing.T) { AuthorizedActions: testAuthorizedActions, ActiveConnectionCount: &wrapperspb.UInt32Value{Value: 0}, LastStatusTime: pkiWorker.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: pkiWorker.ReleaseVersion, CanonicalTags: map[string]*structpb.ListValue{ "config": structListValue(t, "test"), }, @@ -198,7 +207,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) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Couldn't create new worker service.") got, err := s.GetWorker(auth.DisabledAuthTestContext(iamRepoFn, tc.scopeId), tc.req) @@ -214,6 +223,7 @@ func TestGet(t *testing.T) { } func TestList(t *testing.T) { + ctx := context.Background() conn, _ := db.TestSetup(t, "postgres") wrap := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, wrap) @@ -226,6 +236,12 @@ func TestList(t *testing.T) { return server.NewRepository(rw, rw, kms) } + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + var wantKmsWorkers []*pb.Worker for i := 0; i < 10; i++ { w := server.TestKmsWorker(t, conn, wrap, server.WithName(fmt.Sprintf("kms-worker%d", i))) @@ -244,6 +260,7 @@ func TestList(t *testing.T) { Address: w.GetAddress(), Type: KmsWorkerType, LastStatusTime: w.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: w.ReleaseVersion, }) } @@ -263,6 +280,7 @@ func TestList(t *testing.T) { Address: w.GetAddress(), Type: PkiWorkerType, LastStatusTime: w.GetLastStatusTime().GetTimestamp(), + ReleaseVersion: w.ReleaseVersion, }) } @@ -312,7 +330,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) + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(err, "Couldn't create new worker service.") // Test with a non-anon user @@ -359,7 +377,13 @@ func TestDelete(t *testing.T) { } ctx := context.Background() - s, err := NewService(ctx, repoFn, iamRepoFn) + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + + s, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Error when getting new worker service.") w := server.TestKmsWorker(t, conn, wrap) @@ -426,6 +450,12 @@ func TestUpdate(t *testing.T) { return repo, nil } + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + wkr := server.TestPkiWorker(t, conn, wrapper, server.WithName("default"), server.WithDescription("default")) @@ -443,7 +473,7 @@ func TestUpdate(t *testing.T) { toMerge := &pbs.UpdateWorkerRequest{ Id: wkr.GetPublicId(), } - workerService, err := NewService(ctx, repoFn, iamRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err) expectedScope := &scopes.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"} @@ -837,6 +867,12 @@ func TestUpdate_KMS(t *testing.T) { return repo, nil } + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + wkr := server.TestKmsWorker(t, conn, wrapper, server.WithName("default"), server.WithDescription("default")) @@ -844,7 +880,7 @@ func TestUpdate_KMS(t *testing.T) { toMerge := &pbs.UpdateWorkerRequest{ Id: wkr.GetPublicId(), } - workerService, err := NewService(ctx, repoFn, iamRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err) cases := []struct { @@ -901,7 +937,9 @@ 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) wrapper := db.TestWrapper(t) kms := kms.TestKms(t, conn, wrapper) @@ -909,18 +947,21 @@ func TestUpdate_BadVersion(t *testing.T) { iamRepoFn := func() (*iam.Repository, error) { return iamRepo, nil } + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } _, proj := iam.TestScopes(t, iamRepo) - rw := db.New(conn) repo, err := server.NewRepository(rw, rw, kms) require.NoError(t, err, "Couldn't create new worker repo.") repoFn := func() (*server.Repository, error) { return repo, nil } - ctx := context.Background() - workerService, err := NewService(ctx, repoFn, iamRepoFn) + workerService, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Failed to create a new host set service.") wkr := server.TestPkiWorker(t, conn, wrapper) @@ -951,9 +992,15 @@ func TestCreateWorkerLed(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, rw, testKms) } - testCtx := context.Background() - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + testCtx := context.Background() + workerAuthRepo, err := server.NewRepositoryStorage(testCtx, rw, rw, testKms) + require.NoError(t, err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Error when getting new worker service.") // Get an initial set of authorized node credentials @@ -1205,7 +1252,7 @@ func TestCreateWorkerLed(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, &db.Db{}, testKms) } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1238,7 +1285,7 @@ func TestCreateWorkerLed(t *testing.T) { return server.NewRepository(rw, rw, testKms) } } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1333,12 +1380,16 @@ func TestCreateControllerLed(t *testing.T) { } testCtx := context.Background() - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + rootStorage, err := server.NewRepositoryStorage(testCtx, rw, rw, testKms) + require.NoError(t, err) + authRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return rootStorage, nil + } + + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) require.NoError(t, err, "Error when getting new worker service.") // Get an initial set of authorized node credentials - rootStorage, err := server.NewRepositoryStorage(testCtx, rw, rw, testKms) - require.NoError(t, err) _, err = rotation.RotateRootCertificates(testCtx, rootStorage) require.NoError(t, err) @@ -1549,7 +1600,7 @@ func TestCreateControllerLed(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, &db.Db{}, testKms) } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1581,7 +1632,7 @@ func TestCreateControllerLed(t *testing.T) { return server.NewRepository(rw, rw, testKms) } } - testSrv, err := NewService(testCtx, repoFn, iamRepoFn) + testSrv, err := NewService(testCtx, repoFn, iamRepoFn, authRepoFn) require.NoError(t, err, "Error when getting new worker service.") return testSrv }(), @@ -1664,6 +1715,7 @@ func TestCreateControllerLed(t *testing.T) { func TestService_AddWorkerTags(t *testing.T) { t.Parallel() + ctx := context.Background() assert, require := assert.New(t), require.New(t) conn, _ := db.TestSetup(t, "postgres") @@ -1678,7 +1730,12 @@ func TestService_AddWorkerTags(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, rw, testKms) } - s, err := NewService(context.Background(), repoFn, iamRepoFn) + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, testKms) + require.NoError(err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -1809,7 +1866,7 @@ 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") wrapper := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, wrapper) @@ -1822,7 +1879,12 @@ func TestService_SetWorkerTags(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, rw, testKms) } - s, err := NewService(context.Background(), repoFn, iamRepoFn) + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, testKms) + require.NoError(err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -1956,7 +2018,7 @@ 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") wrapper := db.TestWrapper(t) iamRepo := iam.TestRepo(t, conn, wrapper) @@ -1969,7 +2031,12 @@ func TestService_RemoveWorkerTags(t *testing.T) { repoFn := func() (*server.Repository, error) { return server.NewRepository(rw, rw, testKms) } - s, err := NewService(context.Background(), repoFn, iamRepoFn) + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, testKms) + require.NoError(err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + s, err := NewService(context.Background(), repoFn, iamRepoFn, workerAuthRepoFn) require.NoError(err) worker := server.TestKmsWorker(t, conn, wrapper) @@ -2140,3 +2207,157 @@ 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) + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + kmsCache := kms.TestKms(t, conn, wrapper) + + iamRepo := iam.TestRepo(t, conn, wrapper) + iamRepoFn := func() (*iam.Repository, error) { + return iamRepo, nil + } + + repoFn := func() (*server.Repository, error) { + return server.NewRepository(rw, rw, kmsCache) + } + + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kmsCache) + require.NoError(err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + + // Store CA and check that initial version updates + _, err = rotation.RotateRootCertificates(ctx, workerAuthRepo) + require.NoError(err) + + testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + require.NoError(err, "Error when getting new worker service.") + + tests := []struct { + name string + scopeId string + req *pbs.ReadCertificateAuthorityRequest + wantErr bool + wantErrIs error + wantErrContains string + }{ + { + name: "invalid-scope", + scopeId: scope.Global.String(), + req: &pbs.ReadCertificateAuthorityRequest{ + ScopeId: "invalid-scope", + }, + wantErr: true, + wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), + wantErrContains: "Must be 'global'", + }, + { + name: "success", + scopeId: scope.Global.String(), + req: &pbs.ReadCertificateAuthorityRequest{ + ScopeId: "global", + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := testSrv.ReadCertificateAuthority(auth.DisabledAuthTestContext(iamRepoFn, tc.scopeId), tc.req) + if tc.wantErr { + require.Error(err) + assert.Nil(got) + if tc.wantErrIs != nil { + assert.ErrorIs(err, tc.wantErrIs) + } + if tc.wantErrContains != "" { + assert.Contains(err.Error(), tc.wantErrContains) + } + return + } + require.NoError(err) + require.NotNil(got) + }) + } +} + +func TestReinitializeCertificateAuthority(t *testing.T) { + t.Parallel() + require, assert := require.New(t), assert.New(t) + ctx := context.Background() + wrapper := db.TestWrapper(t) + conn, _ := db.TestSetup(t, "postgres") + rw := db.New(conn) + kmsCache := kms.TestKms(t, conn, wrapper) + + iamRepo := iam.TestRepo(t, conn, wrapper) + iamRepoFn := func() (*iam.Repository, error) { + return iamRepo, nil + } + + repoFn := func() (*server.Repository, error) { + return server.NewRepository(rw, rw, kmsCache) + } + + workerAuthRepo, err := server.NewRepositoryStorage(ctx, rw, rw, kmsCache) + require.NoError(err) + workerAuthRepoFn := func() (*server.WorkerAuthRepositoryStorage, error) { + return workerAuthRepo, nil + } + + // Store CA and check that initial version updates + _, err = rotation.RotateRootCertificates(ctx, workerAuthRepo) + require.NoError(err) + + testSrv, err := NewService(ctx, repoFn, iamRepoFn, workerAuthRepoFn) + require.NoError(err, "Error when getting new worker service.") + + tests := []struct { + name string + scopeId string + req *pbs.ReinitializeCertificateAuthorityRequest + wantErr bool + wantErrIs error + wantErrContains string + }{ + { + name: "invalid-id", + scopeId: scope.Global.String(), + req: &pbs.ReinitializeCertificateAuthorityRequest{ + ScopeId: "bogus", + }, + wantErr: true, + wantErrIs: handlers.ApiErrorWithCode(codes.InvalidArgument), + wantErrContains: "Must be 'global'", + }, + { + name: "success", + scopeId: scope.Global.String(), + req: &pbs.ReinitializeCertificateAuthorityRequest{ + ScopeId: "global", + }, + }, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + got, err := testSrv.ReinitializeCertificateAuthority(auth.DisabledAuthTestContext(iamRepoFn, tc.scopeId), tc.req) + if tc.wantErr { + require.Error(err) + assert.Nil(got) + if tc.wantErrIs != nil { + assert.ErrorIs(err, tc.wantErrIs) + } + if tc.wantErrContains != "" { + assert.Contains(err.Error(), tc.wantErrContains) + } + return + } + require.NoError(err) + require.NotNil(got) + }) + } +} diff --git a/internal/daemon/worker/status.go b/internal/daemon/worker/status.go index 11b103b04..3598f3d78 100644 --- a/internal/daemon/worker/status.go +++ b/internal/daemon/worker/status.go @@ -7,6 +7,8 @@ import ( "math/rand" "time" + "github.com/hashicorp/boundary/version" + "github.com/hashicorp/boundary/internal/daemon/worker/common" "github.com/hashicorp/boundary/internal/daemon/worker/session" pb "github.com/hashicorp/boundary/internal/gen/controller/servers" @@ -159,15 +161,16 @@ func (w *Worker) sendWorkerStatus(cancelCtx context.Context, sessionManager sess event.WriteError(statusCtx, op, errors.New("worker name and keyId are both empty; one is needed to identify a worker"), event.WithInfoMsg("error making status request to controller")) } - + versionInfo := version.Get() result, err := client.Status(statusCtx, &pbs.StatusRequest{ Jobs: activeJobs, WorkerStatus: &pb.ServerWorkerStatus{ - Name: w.conf.RawConfig.Worker.Name, - Description: w.conf.RawConfig.Worker.Description, - 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, + ReleaseVersion: versionInfo.FullVersionNumber(false), }, UpdateTags: w.updateTags.Load(), }) diff --git a/internal/db/schema/migrations/oss/postgres/34/04_views.up.sql b/internal/db/schema/migrations/oss/postgres/34/04_views.up.sql index c67d3ee4a..e827d41cc 100644 --- a/internal/db/schema/migrations/oss/postgres/34/04_views.up.sql +++ b/internal/db/schema/migrations/oss/postgres/34/04_views.up.sql @@ -2,6 +2,7 @@ begin; -- worker_aggregate view allows the worker and configuration to be read at the -- same time. +-- Updated in 51/01_server_worker_release_version.up.sql create view server_worker_aggregate as with worker_config_tags(worker_id, source, tags) as ( select diff --git a/internal/db/schema/migrations/oss/postgres/51/01_server_worker_release_version.up.sql b/internal/db/schema/migrations/oss/postgres/51/01_server_worker_release_version.up.sql new file mode 100644 index 000000000..c40664df1 --- /dev/null +++ b/internal/db/schema/migrations/oss/postgres/51/01_server_worker_release_version.up.sql @@ -0,0 +1,57 @@ +begin; + +-- release_version can be null, but if provided it must be greater than 8 to account for +-- the 'Boundary' suffix +alter table server_worker + add column release_version text + constraint release_version_too_short + check (release_version = '' or length(trim(release_version)) >= 8); + +drop view server_worker_aggregate; + +-- Updates view created in 34/04_views.up.sql +create view server_worker_aggregate as +with worker_config_tags(worker_id, source, tags) as ( + select + ct.worker_id, + ct.source, + -- keys and tags can be any lowercase printable character so use uppercase characters as delimitors. + string_agg(distinct concat_ws('Y', ct.key, ct.value), 'Z') as tags + from server_worker_tag ct + group by ct.worker_id, ct.source +), + connection_count (worker_id, count) as ( + select + worker_id, + count(1) as count + from session_connection + where closed_reason is null + group by worker_id + ) +select + w.public_id, + w.scope_id, + w.description, + w.name, + w.address, + w.create_time, + w.update_time, + w.version, + w.last_status_time, + w.type, + w.release_version, + 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, + ct.tags as worker_config_tags +from server_worker w + left join worker_config_tags wt on + w.public_id = wt.worker_id and wt.source = 'api' + left join worker_config_tags ct on + w.public_id = ct.worker_id and ct.source = 'configuration' + left join connection_count as cc on + w.public_id = cc.worker_id; +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.'; + +commit; \ No newline at end of file diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index a236e45d5..d85d1b37a 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -4014,6 +4014,56 @@ "controller.api.services.v1.WorkerService" ] } + }, + "/v1/workers:read-certificate-authority": { + "get": { + "summary": "Retrieves root certificates used for worker authentication.", + "operationId": "WorkerService_ReadCertificateAuthority", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.workers.v1.CertificateAuthority" + } + } + }, + "parameters": [ + { + "name": "scope_id", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "controller.api.services.v1.WorkerService" + ] + } + }, + "/v1/workers:reinitialize-certificate-authority": { + "post": { + "summary": "Reinitializes root certificates used for worker authentication.", + "operationId": "WorkerService_ReinitializeCertificateAuthority", + "responses": { + "200": { + "description": "", + "schema": { + "$ref": "#/definitions/controller.api.resources.workers.v1.CertificateAuthority" + } + } + }, + "parameters": [ + { + "name": "scope_id", + "in": "query", + "required": false, + "type": "string" + } + ], + "tags": [ + "controller.api.services.v1.WorkerService" + ] + } } }, "definitions": { @@ -5738,6 +5788,44 @@ }, "title": "User contains all fields related to a User resource" }, + "controller.api.resources.workers.v1.Certificate": { + "type": "object", + "properties": { + "id": { + "type": "string", + "title": "Output only. The ID of the certificate", + "readOnly": true + }, + "public_key_sha256": { + "type": "string", + "title": "Output only. The public key of the cert authority", + "readOnly": true + }, + "not_before_time": { + "type": "string", + "format": "date-time", + "title": "Output only. The time before which this CA is invalid", + "readOnly": true + }, + "not_after_time": { + "type": "string", + "format": "date-time", + "title": "Output only. The time after which this CA is invalid", + "readOnly": true + } + } + }, + "controller.api.resources.workers.v1.CertificateAuthority": { + "type": "object", + "properties": { + "certs": { + "type": "array", + "items": { + "$ref": "#/definitions/controller.api.resources.workers.v1.Certificate" + } + } + } + }, "controller.api.resources.workers.v1.Worker": { "type": "object", "properties": { @@ -5844,6 +5932,11 @@ "description": "Output only. The api tags set for the worker.", "readOnly": true }, + "release_version": { + "type": "string", + "description": "Output only. The version of the Boundary binary the worker is running.", + "readOnly": true + }, "authorized_actions": { "type": "array", "items": { @@ -6523,6 +6616,22 @@ } } }, + "controller.api.services.v1.ReadCertificateAuthorityResponse": { + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.workers.v1.CertificateAuthority" + } + } + }, + "controller.api.services.v1.ReinitializeCertificateAuthorityResponse": { + "type": "object", + "properties": { + "item": { + "$ref": "#/definitions/controller.api.resources.workers.v1.CertificateAuthority" + } + } + }, "controller.api.services.v1.RemoveGroupMembersResponse": { "type": "object", "properties": { diff --git a/internal/gen/controller/api/services/worker_service.pb.go b/internal/gen/controller/api/services/worker_service.pb.go index 1c3ce5d1b..65f46df55 100644 --- a/internal/gen/controller/api/services/worker_service.pb.go +++ b/internal/gen/controller/api/services/worker_service.pb.go @@ -964,6 +964,194 @@ func (x *RemoveWorkerTagsResponse) GetItem() *workers.Worker { return nil } +type ReadCertificateAuthorityRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ScopeId string `protobuf:"bytes,1,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"` +} + +func (x *ReadCertificateAuthorityRequest) Reset() { + *x = ReadCertificateAuthorityRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReadCertificateAuthorityRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadCertificateAuthorityRequest) ProtoMessage() {} + +func (x *ReadCertificateAuthorityRequest) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[18] + 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 ReadCertificateAuthorityRequest.ProtoReflect.Descriptor instead. +func (*ReadCertificateAuthorityRequest) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_worker_service_proto_rawDescGZIP(), []int{18} +} + +func (x *ReadCertificateAuthorityRequest) GetScopeId() string { + if x != nil { + return x.ScopeId + } + return "" +} + +type ReadCertificateAuthorityResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *workers.CertificateAuthority `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *ReadCertificateAuthorityResponse) Reset() { + *x = ReadCertificateAuthorityResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReadCertificateAuthorityResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadCertificateAuthorityResponse) ProtoMessage() {} + +func (x *ReadCertificateAuthorityResponse) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[19] + 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 ReadCertificateAuthorityResponse.ProtoReflect.Descriptor instead. +func (*ReadCertificateAuthorityResponse) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_worker_service_proto_rawDescGZIP(), []int{19} +} + +func (x *ReadCertificateAuthorityResponse) GetItem() *workers.CertificateAuthority { + if x != nil { + return x.Item + } + return nil +} + +type ReinitializeCertificateAuthorityRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ScopeId string `protobuf:"bytes,1,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty" class:"public"` // @gotags: `class:"public"` +} + +func (x *ReinitializeCertificateAuthorityRequest) Reset() { + *x = ReinitializeCertificateAuthorityRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReinitializeCertificateAuthorityRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReinitializeCertificateAuthorityRequest) ProtoMessage() {} + +func (x *ReinitializeCertificateAuthorityRequest) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[20] + 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 ReinitializeCertificateAuthorityRequest.ProtoReflect.Descriptor instead. +func (*ReinitializeCertificateAuthorityRequest) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_worker_service_proto_rawDescGZIP(), []int{20} +} + +func (x *ReinitializeCertificateAuthorityRequest) GetScopeId() string { + if x != nil { + return x.ScopeId + } + return "" +} + +type ReinitializeCertificateAuthorityResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Item *workers.CertificateAuthority `protobuf:"bytes,1,opt,name=item,proto3" json:"item,omitempty"` +} + +func (x *ReinitializeCertificateAuthorityResponse) Reset() { + *x = ReinitializeCertificateAuthorityResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ReinitializeCertificateAuthorityResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReinitializeCertificateAuthorityResponse) ProtoMessage() {} + +func (x *ReinitializeCertificateAuthorityResponse) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_services_v1_worker_service_proto_msgTypes[21] + 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 ReinitializeCertificateAuthorityResponse.ProtoReflect.Descriptor instead. +func (*ReinitializeCertificateAuthorityResponse) Descriptor() ([]byte, []int) { + return file_controller_api_services_v1_worker_service_proto_rawDescGZIP(), []int{21} +} + +func (x *ReinitializeCertificateAuthorityResponse) GetItem() *workers.CertificateAuthority { + if x != nil { + return x.Item + } + return nil +} + var File_controller_api_services_v1_worker_service_proto protoreflect.FileDescriptor var file_controller_api_services_v1_worker_service_proto_rawDesc = []byte{ @@ -1112,122 +1300,182 @@ var file_controller_api_services_v1_worker_service_proto_rawDesc = []byte{ 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 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, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xda, 0x0d, 0x0a, 0x0d, 0x57, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, 0x01, 0x0a, - 0x09, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x63, 0x6f, 0x6e, + 0x72, 0x6b, 0x65, 0x72, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x3c, 0x0a, 0x1f, 0x52, 0x65, + 0x61, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x22, 0x71, 0x0a, 0x20, 0x52, 0x65, 0x61, 0x64, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 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, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x44, 0x0a, 0x27, 0x52, + 0x65, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, + 0x64, 0x22, 0x79, 0x0a, 0x28, 0x52, 0x65, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, + 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 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, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0x9b, 0x12, 0x0a, + 0x0d, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, + 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2c, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x92, 0x41, 0x17, 0x12, 0x15, 0x47, 0x65, - 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x2a, 0x92, 0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, - 0x6c, 0x6c, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x12, 0xca, - 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, - 0x65, 0x64, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x65, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, - 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x4c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x92, 0x41, 0x1a, - 0x12, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, - 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, - 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3a, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x3a, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x64, 0x3a, - 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xda, 0x01, 0x0a, 0x13, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x4c, 0x65, 0x64, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x38, 0x92, 0x41, 0x17, 0x12, 0x15, + 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x57, 0x6f, + 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31, + 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, + 0x65, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, - 0x72, 0x4c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x63, 0x6f, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x92, 0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, + 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2e, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, + 0x12, 0xca, 0x01, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, + 0x72, 0x4c, 0x65, 0x64, 0x12, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, + 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x4c, 0x65, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, + 0x65, 0x72, 0x4c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4e, 0x92, + 0x41, 0x1a, 0x12, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x2b, 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3a, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x3a, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x6c, 0x65, + 0x64, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xda, 0x01, + 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x4c, 0x65, 0x64, 0x12, 0x36, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x4c, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x65, 0x64, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x92, 0x41, 0x1a, 0x12, 0x18, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x57, 0x6f, + 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x21, 0x2f, 0x76, 0x31, + 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x3a, + 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x64, 0x3a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x4c, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x92, 0x41, 0x1a, 0x12, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x57, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2f, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x3a, 0x63, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2d, 0x6c, 0x65, 0x64, 0x3a, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x92, 0x41, - 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x57, 0x6f, 0x72, - 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, - 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x92, 0x41, - 0x13, 0x12, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x57, 0x6f, 0x72, - 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, 0x31, 0x2f, - 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xd0, 0x01, 0x0a, - 0x0d, 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x12, 0x30, - 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x57, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x57, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, + 0x92, 0x41, 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x57, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, + 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x2f, 0x2e, 0x63, 0x6f, + 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x57, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, + 0x92, 0x41, 0x13, 0x12, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x57, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, + 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xd0, + 0x01, 0x0a, 0x0d, 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, + 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, - 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x92, 0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, 0x20, 0x61, - 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, - 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, - 0xd1, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, - 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x64, 0x64, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5a, 0x92, 0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, + 0x20, 0x61, 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, + 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2e, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, + 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x77, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, + 0x6d, 0x12, 0xd1, 0x01, 0x0a, 0x0d, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, + 0x61, 0x67, 0x73, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5b, 0x92, 0x41, 0x27, 0x12, 0x25, 0x53, 0x65, 0x74, - 0x73, 0x20, 0x61, 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, - 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, 0x72, 0x6b, 0x65, - 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, - 0x74, 0x65, 0x6d, 0x12, 0xe1, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x57, 0x6f, - 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, - 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, - 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, - 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x62, 0x92, 0x41, 0x2b, 0x12, 0x29, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, - 0x73, 0x20, 0x61, 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, 0x72, 0x6b, - 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x22, 0x23, 0x2f, 0x76, 0x31, 0x2f, 0x77, - 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x01, - 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x42, 0x4d, 0x5a, 0x4b, 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, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, - 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, + 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5b, 0x92, 0x41, 0x27, 0x12, 0x25, 0x53, + 0x65, 0x74, 0x73, 0x20, 0x61, 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x22, 0x20, 0x2f, 0x76, 0x31, 0x2f, + 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, + 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, 0x3a, 0x01, 0x2a, 0x62, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xe1, 0x01, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x6e, + 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x57, 0x6f, + 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x76, 0x65, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x62, 0x92, 0x41, 0x2b, 0x12, 0x29, 0x52, 0x65, 0x6d, 0x6f, + 0x76, 0x65, 0x73, 0x20, 0x61, 0x70, 0x69, 0x20, 0x74, 0x61, 0x67, 0x73, 0x20, 0x66, 0x72, 0x6f, + 0x6d, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x57, 0x6f, + 0x72, 0x6b, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x22, 0x23, 0x2f, 0x76, 0x31, + 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, + 0x6d, 0x6f, 0x76, 0x65, 0x2d, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x2d, 0x74, 0x61, 0x67, 0x73, + 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x8b, 0x02, 0x0a, 0x18, 0x52, 0x65, + 0x61, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x3b, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x61, 0x64, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x74, 0x92, 0x41, 0x3d, 0x12, 0x3b, 0x52, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, + 0x73, 0x20, 0x72, 0x6f, 0x6f, 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x73, 0x20, 0x75, 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x6f, 0x72, + 0x6b, 0x65, 0x72, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2e, 0x12, 0x26, 0x2f, 0x76, 0x31, 0x2f, 0x77, + 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x73, 0x3a, 0x72, 0x65, 0x61, 0x64, 0x2d, 0x63, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xb0, 0x02, 0x0a, 0x20, 0x52, 0x65, 0x69, 0x6e, + 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x43, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x69, 0x6e, 0x69, 0x74, + 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x44, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x80, 0x01, 0x92, 0x41, 0x41, 0x12, 0x3f, 0x52, + 0x65, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x73, 0x20, 0x72, 0x6f, 0x6f, + 0x74, 0x20, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x75, + 0x73, 0x65, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x20, 0x61, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x36, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0x73, 0x3a, 0x72, 0x65, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x2d, 0x63, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2d, 0x61, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x42, 0x4d, 0x5a, 0x4b, 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, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, + 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -1242,75 +1490,86 @@ func file_controller_api_services_v1_worker_service_proto_rawDescGZIP() []byte { return file_controller_api_services_v1_worker_service_proto_rawDescData } -var file_controller_api_services_v1_worker_service_proto_msgTypes = make([]protoimpl.MessageInfo, 21) +var file_controller_api_services_v1_worker_service_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_controller_api_services_v1_worker_service_proto_goTypes = []interface{}{ - (*GetWorkerRequest)(nil), // 0: controller.api.services.v1.GetWorkerRequest - (*GetWorkerResponse)(nil), // 1: controller.api.services.v1.GetWorkerResponse - (*ListWorkersRequest)(nil), // 2: controller.api.services.v1.ListWorkersRequest - (*ListWorkersResponse)(nil), // 3: controller.api.services.v1.ListWorkersResponse - (*CreateWorkerLedRequest)(nil), // 4: controller.api.services.v1.CreateWorkerLedRequest - (*CreateWorkerLedResponse)(nil), // 5: controller.api.services.v1.CreateWorkerLedResponse - (*CreateControllerLedRequest)(nil), // 6: controller.api.services.v1.CreateControllerLedRequest - (*CreateControllerLedResponse)(nil), // 7: controller.api.services.v1.CreateControllerLedResponse - (*UpdateWorkerRequest)(nil), // 8: controller.api.services.v1.UpdateWorkerRequest - (*UpdateWorkerResponse)(nil), // 9: controller.api.services.v1.UpdateWorkerResponse - (*DeleteWorkerRequest)(nil), // 10: controller.api.services.v1.DeleteWorkerRequest - (*DeleteWorkerResponse)(nil), // 11: controller.api.services.v1.DeleteWorkerResponse - (*AddWorkerTagsRequest)(nil), // 12: controller.api.services.v1.AddWorkerTagsRequest - (*AddWorkerTagsResponse)(nil), // 13: controller.api.services.v1.AddWorkerTagsResponse - (*SetWorkerTagsRequest)(nil), // 14: controller.api.services.v1.SetWorkerTagsRequest - (*SetWorkerTagsResponse)(nil), // 15: controller.api.services.v1.SetWorkerTagsResponse - (*RemoveWorkerTagsRequest)(nil), // 16: controller.api.services.v1.RemoveWorkerTagsRequest - (*RemoveWorkerTagsResponse)(nil), // 17: controller.api.services.v1.RemoveWorkerTagsResponse - nil, // 18: controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry - nil, // 19: controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry - nil, // 20: controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry - (*workers.Worker)(nil), // 21: controller.api.resources.workers.v1.Worker - (*fieldmaskpb.FieldMask)(nil), // 22: google.protobuf.FieldMask - (*structpb.ListValue)(nil), // 23: google.protobuf.ListValue + (*GetWorkerRequest)(nil), // 0: controller.api.services.v1.GetWorkerRequest + (*GetWorkerResponse)(nil), // 1: controller.api.services.v1.GetWorkerResponse + (*ListWorkersRequest)(nil), // 2: controller.api.services.v1.ListWorkersRequest + (*ListWorkersResponse)(nil), // 3: controller.api.services.v1.ListWorkersResponse + (*CreateWorkerLedRequest)(nil), // 4: controller.api.services.v1.CreateWorkerLedRequest + (*CreateWorkerLedResponse)(nil), // 5: controller.api.services.v1.CreateWorkerLedResponse + (*CreateControllerLedRequest)(nil), // 6: controller.api.services.v1.CreateControllerLedRequest + (*CreateControllerLedResponse)(nil), // 7: controller.api.services.v1.CreateControllerLedResponse + (*UpdateWorkerRequest)(nil), // 8: controller.api.services.v1.UpdateWorkerRequest + (*UpdateWorkerResponse)(nil), // 9: controller.api.services.v1.UpdateWorkerResponse + (*DeleteWorkerRequest)(nil), // 10: controller.api.services.v1.DeleteWorkerRequest + (*DeleteWorkerResponse)(nil), // 11: controller.api.services.v1.DeleteWorkerResponse + (*AddWorkerTagsRequest)(nil), // 12: controller.api.services.v1.AddWorkerTagsRequest + (*AddWorkerTagsResponse)(nil), // 13: controller.api.services.v1.AddWorkerTagsResponse + (*SetWorkerTagsRequest)(nil), // 14: controller.api.services.v1.SetWorkerTagsRequest + (*SetWorkerTagsResponse)(nil), // 15: controller.api.services.v1.SetWorkerTagsResponse + (*RemoveWorkerTagsRequest)(nil), // 16: controller.api.services.v1.RemoveWorkerTagsRequest + (*RemoveWorkerTagsResponse)(nil), // 17: controller.api.services.v1.RemoveWorkerTagsResponse + (*ReadCertificateAuthorityRequest)(nil), // 18: controller.api.services.v1.ReadCertificateAuthorityRequest + (*ReadCertificateAuthorityResponse)(nil), // 19: controller.api.services.v1.ReadCertificateAuthorityResponse + (*ReinitializeCertificateAuthorityRequest)(nil), // 20: controller.api.services.v1.ReinitializeCertificateAuthorityRequest + (*ReinitializeCertificateAuthorityResponse)(nil), // 21: controller.api.services.v1.ReinitializeCertificateAuthorityResponse + nil, // 22: controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry + nil, // 23: controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry + nil, // 24: controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry + (*workers.Worker)(nil), // 25: controller.api.resources.workers.v1.Worker + (*fieldmaskpb.FieldMask)(nil), // 26: google.protobuf.FieldMask + (*workers.CertificateAuthority)(nil), // 27: controller.api.resources.workers.v1.CertificateAuthority + (*structpb.ListValue)(nil), // 28: google.protobuf.ListValue } var file_controller_api_services_v1_worker_service_proto_depIdxs = []int32{ - 21, // 0: controller.api.services.v1.GetWorkerResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 21, // 1: controller.api.services.v1.ListWorkersResponse.items:type_name -> controller.api.resources.workers.v1.Worker - 21, // 2: controller.api.services.v1.CreateWorkerLedRequest.item:type_name -> controller.api.resources.workers.v1.Worker - 21, // 3: controller.api.services.v1.CreateWorkerLedResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 21, // 4: controller.api.services.v1.CreateControllerLedRequest.item:type_name -> controller.api.resources.workers.v1.Worker - 21, // 5: controller.api.services.v1.CreateControllerLedResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 21, // 6: controller.api.services.v1.UpdateWorkerRequest.item:type_name -> controller.api.resources.workers.v1.Worker - 22, // 7: controller.api.services.v1.UpdateWorkerRequest.update_mask:type_name -> google.protobuf.FieldMask - 21, // 8: controller.api.services.v1.UpdateWorkerResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 18, // 9: controller.api.services.v1.AddWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry - 21, // 10: controller.api.services.v1.AddWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 19, // 11: controller.api.services.v1.SetWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry - 21, // 12: controller.api.services.v1.SetWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 20, // 13: controller.api.services.v1.RemoveWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry - 21, // 14: controller.api.services.v1.RemoveWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker - 23, // 15: controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue - 23, // 16: controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue - 23, // 17: controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue - 0, // 18: controller.api.services.v1.WorkerService.GetWorker:input_type -> controller.api.services.v1.GetWorkerRequest - 2, // 19: controller.api.services.v1.WorkerService.ListWorkers:input_type -> controller.api.services.v1.ListWorkersRequest - 4, // 20: controller.api.services.v1.WorkerService.CreateWorkerLed:input_type -> controller.api.services.v1.CreateWorkerLedRequest - 6, // 21: controller.api.services.v1.WorkerService.CreateControllerLed:input_type -> controller.api.services.v1.CreateControllerLedRequest - 8, // 22: controller.api.services.v1.WorkerService.UpdateWorker:input_type -> controller.api.services.v1.UpdateWorkerRequest - 10, // 23: controller.api.services.v1.WorkerService.DeleteWorker:input_type -> controller.api.services.v1.DeleteWorkerRequest - 12, // 24: controller.api.services.v1.WorkerService.AddWorkerTags:input_type -> controller.api.services.v1.AddWorkerTagsRequest - 14, // 25: controller.api.services.v1.WorkerService.SetWorkerTags:input_type -> controller.api.services.v1.SetWorkerTagsRequest - 16, // 26: controller.api.services.v1.WorkerService.RemoveWorkerTags:input_type -> controller.api.services.v1.RemoveWorkerTagsRequest - 1, // 27: controller.api.services.v1.WorkerService.GetWorker:output_type -> controller.api.services.v1.GetWorkerResponse - 3, // 28: controller.api.services.v1.WorkerService.ListWorkers:output_type -> controller.api.services.v1.ListWorkersResponse - 5, // 29: controller.api.services.v1.WorkerService.CreateWorkerLed:output_type -> controller.api.services.v1.CreateWorkerLedResponse - 7, // 30: controller.api.services.v1.WorkerService.CreateControllerLed:output_type -> controller.api.services.v1.CreateControllerLedResponse - 9, // 31: controller.api.services.v1.WorkerService.UpdateWorker:output_type -> controller.api.services.v1.UpdateWorkerResponse - 11, // 32: controller.api.services.v1.WorkerService.DeleteWorker:output_type -> controller.api.services.v1.DeleteWorkerResponse - 13, // 33: controller.api.services.v1.WorkerService.AddWorkerTags:output_type -> controller.api.services.v1.AddWorkerTagsResponse - 15, // 34: controller.api.services.v1.WorkerService.SetWorkerTags:output_type -> controller.api.services.v1.SetWorkerTagsResponse - 17, // 35: controller.api.services.v1.WorkerService.RemoveWorkerTags:output_type -> controller.api.services.v1.RemoveWorkerTagsResponse - 27, // [27:36] is the sub-list for method output_type - 18, // [18:27] is the sub-list for method input_type - 18, // [18:18] is the sub-list for extension type_name - 18, // [18:18] is the sub-list for extension extendee - 0, // [0:18] is the sub-list for field type_name + 25, // 0: controller.api.services.v1.GetWorkerResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 25, // 1: controller.api.services.v1.ListWorkersResponse.items:type_name -> controller.api.resources.workers.v1.Worker + 25, // 2: controller.api.services.v1.CreateWorkerLedRequest.item:type_name -> controller.api.resources.workers.v1.Worker + 25, // 3: controller.api.services.v1.CreateWorkerLedResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 25, // 4: controller.api.services.v1.CreateControllerLedRequest.item:type_name -> controller.api.resources.workers.v1.Worker + 25, // 5: controller.api.services.v1.CreateControllerLedResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 25, // 6: controller.api.services.v1.UpdateWorkerRequest.item:type_name -> controller.api.resources.workers.v1.Worker + 26, // 7: controller.api.services.v1.UpdateWorkerRequest.update_mask:type_name -> google.protobuf.FieldMask + 25, // 8: controller.api.services.v1.UpdateWorkerResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 22, // 9: controller.api.services.v1.AddWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry + 25, // 10: controller.api.services.v1.AddWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 23, // 11: controller.api.services.v1.SetWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry + 25, // 12: controller.api.services.v1.SetWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 24, // 13: controller.api.services.v1.RemoveWorkerTagsRequest.api_tags:type_name -> controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry + 25, // 14: controller.api.services.v1.RemoveWorkerTagsResponse.item:type_name -> controller.api.resources.workers.v1.Worker + 27, // 15: controller.api.services.v1.ReadCertificateAuthorityResponse.item:type_name -> controller.api.resources.workers.v1.CertificateAuthority + 27, // 16: controller.api.services.v1.ReinitializeCertificateAuthorityResponse.item:type_name -> controller.api.resources.workers.v1.CertificateAuthority + 28, // 17: controller.api.services.v1.AddWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue + 28, // 18: controller.api.services.v1.SetWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue + 28, // 19: controller.api.services.v1.RemoveWorkerTagsRequest.ApiTagsEntry.value:type_name -> google.protobuf.ListValue + 0, // 20: controller.api.services.v1.WorkerService.GetWorker:input_type -> controller.api.services.v1.GetWorkerRequest + 2, // 21: controller.api.services.v1.WorkerService.ListWorkers:input_type -> controller.api.services.v1.ListWorkersRequest + 4, // 22: controller.api.services.v1.WorkerService.CreateWorkerLed:input_type -> controller.api.services.v1.CreateWorkerLedRequest + 6, // 23: controller.api.services.v1.WorkerService.CreateControllerLed:input_type -> controller.api.services.v1.CreateControllerLedRequest + 8, // 24: controller.api.services.v1.WorkerService.UpdateWorker:input_type -> controller.api.services.v1.UpdateWorkerRequest + 10, // 25: controller.api.services.v1.WorkerService.DeleteWorker:input_type -> controller.api.services.v1.DeleteWorkerRequest + 12, // 26: controller.api.services.v1.WorkerService.AddWorkerTags:input_type -> controller.api.services.v1.AddWorkerTagsRequest + 14, // 27: controller.api.services.v1.WorkerService.SetWorkerTags:input_type -> controller.api.services.v1.SetWorkerTagsRequest + 16, // 28: controller.api.services.v1.WorkerService.RemoveWorkerTags:input_type -> controller.api.services.v1.RemoveWorkerTagsRequest + 18, // 29: controller.api.services.v1.WorkerService.ReadCertificateAuthority:input_type -> controller.api.services.v1.ReadCertificateAuthorityRequest + 20, // 30: controller.api.services.v1.WorkerService.ReinitializeCertificateAuthority:input_type -> controller.api.services.v1.ReinitializeCertificateAuthorityRequest + 1, // 31: controller.api.services.v1.WorkerService.GetWorker:output_type -> controller.api.services.v1.GetWorkerResponse + 3, // 32: controller.api.services.v1.WorkerService.ListWorkers:output_type -> controller.api.services.v1.ListWorkersResponse + 5, // 33: controller.api.services.v1.WorkerService.CreateWorkerLed:output_type -> controller.api.services.v1.CreateWorkerLedResponse + 7, // 34: controller.api.services.v1.WorkerService.CreateControllerLed:output_type -> controller.api.services.v1.CreateControllerLedResponse + 9, // 35: controller.api.services.v1.WorkerService.UpdateWorker:output_type -> controller.api.services.v1.UpdateWorkerResponse + 11, // 36: controller.api.services.v1.WorkerService.DeleteWorker:output_type -> controller.api.services.v1.DeleteWorkerResponse + 13, // 37: controller.api.services.v1.WorkerService.AddWorkerTags:output_type -> controller.api.services.v1.AddWorkerTagsResponse + 15, // 38: controller.api.services.v1.WorkerService.SetWorkerTags:output_type -> controller.api.services.v1.SetWorkerTagsResponse + 17, // 39: controller.api.services.v1.WorkerService.RemoveWorkerTags:output_type -> controller.api.services.v1.RemoveWorkerTagsResponse + 19, // 40: controller.api.services.v1.WorkerService.ReadCertificateAuthority:output_type -> controller.api.services.v1.ReadCertificateAuthorityResponse + 21, // 41: controller.api.services.v1.WorkerService.ReinitializeCertificateAuthority:output_type -> controller.api.services.v1.ReinitializeCertificateAuthorityResponse + 31, // [31:42] is the sub-list for method output_type + 20, // [20:31] is the sub-list for method input_type + 20, // [20:20] is the sub-list for extension type_name + 20, // [20:20] is the sub-list for extension extendee + 0, // [0:20] is the sub-list for field type_name } func init() { file_controller_api_services_v1_worker_service_proto_init() } @@ -1535,6 +1794,54 @@ func file_controller_api_services_v1_worker_service_proto_init() { return nil } } + file_controller_api_services_v1_worker_service_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReadCertificateAuthorityRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_worker_service_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReadCertificateAuthorityResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_worker_service_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReinitializeCertificateAuthorityRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_controller_api_services_v1_worker_service_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ReinitializeCertificateAuthorityResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -1542,7 +1849,7 @@ func file_controller_api_services_v1_worker_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_controller_api_services_v1_worker_service_proto_rawDesc, NumEnums: 0, - NumMessages: 21, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/gen/controller/api/services/worker_service.pb.gw.go b/internal/gen/controller/api/services/worker_service.pb.gw.go index 024944c47..ac0f002f9 100644 --- a/internal/gen/controller/api/services/worker_service.pb.gw.go +++ b/internal/gen/controller/api/services/worker_service.pb.gw.go @@ -543,6 +543,78 @@ func local_request_WorkerService_RemoveWorkerTags_0(ctx context.Context, marshal } +var ( + filter_WorkerService_ReadCertificateAuthority_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_WorkerService_ReadCertificateAuthority_0(ctx context.Context, marshaler runtime.Marshaler, client WorkerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ReadCertificateAuthorityRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WorkerService_ReadCertificateAuthority_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ReadCertificateAuthority(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_WorkerService_ReadCertificateAuthority_0(ctx context.Context, marshaler runtime.Marshaler, server WorkerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ReadCertificateAuthorityRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WorkerService_ReadCertificateAuthority_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ReadCertificateAuthority(ctx, &protoReq) + return msg, metadata, err + +} + +var ( + filter_WorkerService_ReinitializeCertificateAuthority_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_WorkerService_ReinitializeCertificateAuthority_0(ctx context.Context, marshaler runtime.Marshaler, client WorkerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ReinitializeCertificateAuthorityRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WorkerService_ReinitializeCertificateAuthority_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.ReinitializeCertificateAuthority(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_WorkerService_ReinitializeCertificateAuthority_0(ctx context.Context, marshaler runtime.Marshaler, server WorkerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ReinitializeCertificateAuthorityRequest + var metadata runtime.ServerMetadata + + if err := req.ParseForm(); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_WorkerService_ReinitializeCertificateAuthority_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.ReinitializeCertificateAuthority(ctx, &protoReq) + return msg, metadata, err + +} + // RegisterWorkerServiceHandlerServer registers the http handlers for service WorkerService to "mux". // UnaryRPC :call WorkerServiceServer directly. // StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. @@ -774,6 +846,56 @@ func RegisterWorkerServiceHandlerServer(ctx context.Context, mux *runtime.ServeM }) + mux.Handle("GET", pattern_WorkerService_ReadCertificateAuthority_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.WorkerService/ReadCertificateAuthority", runtime.WithHTTPPathPattern("/v1/workers:read-certificate-authority")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_WorkerService_ReadCertificateAuthority_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_WorkerService_ReadCertificateAuthority_0(annotatedContext, mux, outboundMarshaler, w, req, response_WorkerService_ReadCertificateAuthority_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_WorkerService_ReinitializeCertificateAuthority_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.WorkerService/ReinitializeCertificateAuthority", runtime.WithHTTPPathPattern("/v1/workers:reinitialize-certificate-authority")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_WorkerService_ReinitializeCertificateAuthority_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_WorkerService_ReinitializeCertificateAuthority_0(annotatedContext, mux, outboundMarshaler, w, req, response_WorkerService_ReinitializeCertificateAuthority_0{resp}, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1013,6 +1135,50 @@ func RegisterWorkerServiceHandlerClient(ctx context.Context, mux *runtime.ServeM }) + mux.Handle("GET", pattern_WorkerService_ReadCertificateAuthority_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.WorkerService/ReadCertificateAuthority", runtime.WithHTTPPathPattern("/v1/workers:read-certificate-authority")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_WorkerService_ReadCertificateAuthority_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_WorkerService_ReadCertificateAuthority_0(annotatedContext, mux, outboundMarshaler, w, req, response_WorkerService_ReadCertificateAuthority_0{resp}, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_WorkerService_ReinitializeCertificateAuthority_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.WorkerService/ReinitializeCertificateAuthority", runtime.WithHTTPPathPattern("/v1/workers:reinitialize-certificate-authority")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_WorkerService_ReinitializeCertificateAuthority_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_WorkerService_ReinitializeCertificateAuthority_0(annotatedContext, mux, outboundMarshaler, w, req, response_WorkerService_ReinitializeCertificateAuthority_0{resp}, mux.GetForwardResponseOptions()...) + + }) + return nil } @@ -1079,6 +1245,24 @@ func (m response_WorkerService_RemoveWorkerTags_0) XXX_ResponseBody() interface{ return response.Item } +type response_WorkerService_ReadCertificateAuthority_0 struct { + proto.Message +} + +func (m response_WorkerService_ReadCertificateAuthority_0) XXX_ResponseBody() interface{} { + response := m.Message.(*ReadCertificateAuthorityResponse) + return response.Item +} + +type response_WorkerService_ReinitializeCertificateAuthority_0 struct { + proto.Message +} + +func (m response_WorkerService_ReinitializeCertificateAuthority_0) XXX_ResponseBody() interface{} { + response := m.Message.(*ReinitializeCertificateAuthorityResponse) + return response.Item +} + var ( pattern_WorkerService_GetWorker_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "workers", "id"}, "")) @@ -1097,6 +1281,10 @@ var ( pattern_WorkerService_SetWorkerTags_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "workers", "id"}, "set-worker-tags")) pattern_WorkerService_RemoveWorkerTags_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "workers", "id"}, "remove-worker-tags")) + + pattern_WorkerService_ReadCertificateAuthority_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "workers"}, "read-certificate-authority")) + + pattern_WorkerService_ReinitializeCertificateAuthority_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "workers"}, "reinitialize-certificate-authority")) ) var ( @@ -1117,4 +1305,8 @@ var ( forward_WorkerService_SetWorkerTags_0 = runtime.ForwardResponseMessage forward_WorkerService_RemoveWorkerTags_0 = runtime.ForwardResponseMessage + + forward_WorkerService_ReadCertificateAuthority_0 = runtime.ForwardResponseMessage + + forward_WorkerService_ReinitializeCertificateAuthority_0 = runtime.ForwardResponseMessage ) diff --git a/internal/gen/controller/api/services/worker_service_grpc.pb.go b/internal/gen/controller/api/services/worker_service_grpc.pb.go index 99d383a9d..7acb07250 100644 --- a/internal/gen/controller/api/services/worker_service_grpc.pb.go +++ b/internal/gen/controller/api/services/worker_service_grpc.pb.go @@ -64,6 +64,10 @@ type WorkerServiceClient interface { // RemoveWorkerTags removes api tags from an existing Worker. If missing, malformed, // or referencing a non-existing resource, an error is returned. RemoveWorkerTags(ctx context.Context, in *RemoveWorkerTagsRequest, opts ...grpc.CallOption) (*RemoveWorkerTagsResponse, error) + // ReadCertificateAuthority returns the current and next set of root certificates + ReadCertificateAuthority(ctx context.Context, in *ReadCertificateAuthorityRequest, opts ...grpc.CallOption) (*ReadCertificateAuthorityResponse, error) + // ReinitializeCas removes both current and next root certs and replaces them with a new set + ReinitializeCertificateAuthority(ctx context.Context, in *ReinitializeCertificateAuthorityRequest, opts ...grpc.CallOption) (*ReinitializeCertificateAuthorityResponse, error) } type workerServiceClient struct { @@ -155,6 +159,24 @@ func (c *workerServiceClient) RemoveWorkerTags(ctx context.Context, in *RemoveWo return out, nil } +func (c *workerServiceClient) ReadCertificateAuthority(ctx context.Context, in *ReadCertificateAuthorityRequest, opts ...grpc.CallOption) (*ReadCertificateAuthorityResponse, error) { + out := new(ReadCertificateAuthorityResponse) + err := c.cc.Invoke(ctx, "/controller.api.services.v1.WorkerService/ReadCertificateAuthority", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *workerServiceClient) ReinitializeCertificateAuthority(ctx context.Context, in *ReinitializeCertificateAuthorityRequest, opts ...grpc.CallOption) (*ReinitializeCertificateAuthorityResponse, error) { + out := new(ReinitializeCertificateAuthorityResponse) + err := c.cc.Invoke(ctx, "/controller.api.services.v1.WorkerService/ReinitializeCertificateAuthority", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // WorkerServiceServer is the server API for WorkerService service. // All implementations must embed UnimplementedWorkerServiceServer // for forward compatibility @@ -205,6 +227,10 @@ type WorkerServiceServer interface { // RemoveWorkerTags removes api tags from an existing Worker. If missing, malformed, // or referencing a non-existing resource, an error is returned. RemoveWorkerTags(context.Context, *RemoveWorkerTagsRequest) (*RemoveWorkerTagsResponse, error) + // ReadCertificateAuthority returns the current and next set of root certificates + ReadCertificateAuthority(context.Context, *ReadCertificateAuthorityRequest) (*ReadCertificateAuthorityResponse, error) + // ReinitializeCas removes both current and next root certs and replaces them with a new set + ReinitializeCertificateAuthority(context.Context, *ReinitializeCertificateAuthorityRequest) (*ReinitializeCertificateAuthorityResponse, error) mustEmbedUnimplementedWorkerServiceServer() } @@ -239,6 +265,12 @@ func (UnimplementedWorkerServiceServer) SetWorkerTags(context.Context, *SetWorke func (UnimplementedWorkerServiceServer) RemoveWorkerTags(context.Context, *RemoveWorkerTagsRequest) (*RemoveWorkerTagsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method RemoveWorkerTags not implemented") } +func (UnimplementedWorkerServiceServer) ReadCertificateAuthority(context.Context, *ReadCertificateAuthorityRequest) (*ReadCertificateAuthorityResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ReadCertificateAuthority not implemented") +} +func (UnimplementedWorkerServiceServer) ReinitializeCertificateAuthority(context.Context, *ReinitializeCertificateAuthorityRequest) (*ReinitializeCertificateAuthorityResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ReinitializeCertificateAuthority not implemented") +} func (UnimplementedWorkerServiceServer) mustEmbedUnimplementedWorkerServiceServer() {} // UnsafeWorkerServiceServer may be embedded to opt out of forward compatibility for this service. @@ -414,6 +446,42 @@ func _WorkerService_RemoveWorkerTags_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } +func _WorkerService_ReadCertificateAuthority_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReadCertificateAuthorityRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).ReadCertificateAuthority(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.api.services.v1.WorkerService/ReadCertificateAuthority", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).ReadCertificateAuthority(ctx, req.(*ReadCertificateAuthorityRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _WorkerService_ReinitializeCertificateAuthority_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ReinitializeCertificateAuthorityRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(WorkerServiceServer).ReinitializeCertificateAuthority(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/controller.api.services.v1.WorkerService/ReinitializeCertificateAuthority", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(WorkerServiceServer).ReinitializeCertificateAuthority(ctx, req.(*ReinitializeCertificateAuthorityRequest)) + } + return interceptor(ctx, in, info, handler) +} + // WorkerService_ServiceDesc is the grpc.ServiceDesc for WorkerService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -457,6 +525,14 @@ var WorkerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "RemoveWorkerTags", Handler: _WorkerService_RemoveWorkerTags_Handler, }, + { + MethodName: "ReadCertificateAuthority", + Handler: _WorkerService_ReadCertificateAuthority_Handler, + }, + { + MethodName: "ReinitializeCertificateAuthority", + Handler: _WorkerService_ReinitializeCertificateAuthority_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "controller/api/services/v1/worker_service.proto", diff --git a/internal/gen/controller/servers/servers.pb.go b/internal/gen/controller/servers/servers.pb.go index 5e440bb74..1e0c13261 100644 --- a/internal/gen/controller/servers/servers.pb.go +++ b/internal/gen/controller/servers/servers.pb.go @@ -94,6 +94,8 @@ type ServerWorkerStatus struct { Tags []*TagPair `protobuf:"bytes,40,rep,name=tags,proto3" json:"tags,omitempty"` // The key id for this worker, if applicable (optional) KeyId string `protobuf:"bytes,50,opt,name=key_id,json=keyId,proto3" json:"key_id,omitempty" class:"public"` // @gotags: `class:"public"` + // The version of Boundary the worker binary is running + ReleaseVersion string `protobuf:"bytes,60,opt,name=release_version,proto3" json:"release_version,omitempty" class:"public"` // @gotags: `class:"public"` } func (x *ServerWorkerStatus) Reset() { @@ -170,6 +172,13 @@ func (x *ServerWorkerStatus) GetKeyId() string { return "" } +func (x *ServerWorkerStatus) GetReleaseVersion() string { + if x != nil { + return x.ReleaseVersion + } + return "" +} + var File_controller_servers_v1_servers_proto protoreflect.FileDescriptor var file_controller_servers_v1_servers_proto_rawDesc = []byte{ @@ -180,7 +189,7 @@ 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, - 0xcc, 0x01, 0x0a, 0x12, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, + 0xf6, 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, @@ -192,12 +201,15 @@ var file_controller_servers_v1_servers_proto_rawDesc = []byte{ 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, 0x47, - 0x5a, 0x45, 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, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x3b, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x28, + 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x47, 0x5a, 0x45, 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, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, + 0x72, 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/perms/acl_test.go b/internal/perms/acl_test.go index b4b86e6d5..441930610 100644 --- a/internal/perms/acl_test.go +++ b/internal/perms/acl_test.go @@ -791,11 +791,11 @@ func Test_AnonRestrictions(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { require, assert := require.New(t), assert.New(t) - for i := resource.Type(1); i <= resource.CredentialLibrary; i++ { + for i := resource.Type(1); i <= resource.Credential; i++ { if i == resource.Controller || i == resource.Worker { continue } - for j := action.Type(1); j <= action.CreateControllerLed; j++ { + for j := action.Type(1); j <= action.ReadCertificateAuthority; j++ { res := Resource{ ScopeId: scope.Global.String(), Id: "foobar", diff --git a/internal/proto/controller/api/resources/workers/v1/worker.proto b/internal/proto/controller/api/resources/workers/v1/worker.proto index 9e169fff8..5b02357f4 100644 --- a/internal/proto/controller/api/resources/workers/v1/worker.proto +++ b/internal/proto/controller/api/resources/workers/v1/worker.proto @@ -86,6 +86,27 @@ message Worker { // Output only. The api tags set for the worker. map api_tags = 180 [json_name = "api_tags"]; // @gotags: `class:"public"` + // 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 available actions on this resource for the requester. repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: `class:"public"` } + +message Certificate { + // Output only. The ID of the certificate + string id = 10; // @gotags: `class:"public"` + + // Output only. The public key of the cert authority + string public_key_sha256 = 20; // @gotags: `class:"public"` + + // Output only. The time before which this CA is invalid + google.protobuf.Timestamp not_before_time = 30; // @gotags: `class:"public"` + + // Output only. The time after which this CA is invalid + google.protobuf.Timestamp not_after_time = 40; // @gotags: `class:"public"` +} + +message CertificateAuthority { + repeated Certificate certs = 10; // @gotags: `class:"public"` +} diff --git a/internal/proto/controller/api/services/v1/worker_service.proto b/internal/proto/controller/api/services/v1/worker_service.proto index 421b53c8e..7c553c7d5 100644 --- a/internal/proto/controller/api/services/v1/worker_service.proto +++ b/internal/proto/controller/api/services/v1/worker_service.proto @@ -141,6 +141,28 @@ service WorkerService { summary: "Removes api tags from an existing Worker." }; } + + // ReadCertificateAuthority returns the current and next set of root certificates + rpc ReadCertificateAuthority(ReadCertificateAuthorityRequest) returns (ReadCertificateAuthorityResponse) { + option (google.api.http) = { + get: "/v1/workers:read-certificate-authority" + response_body: "item" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Retrieves root certificates used for worker authentication." + }; + } + + // ReinitializeCas removes both current and next root certs and replaces them with a new set + rpc ReinitializeCertificateAuthority(ReinitializeCertificateAuthorityRequest) returns (ReinitializeCertificateAuthorityResponse) { + option (google.api.http) = { + post: "/v1/workers:reinitialize-certificate-authority" + response_body: "item" + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Reinitializes root certificates used for worker authentication." + }; + } } message GetWorkerRequest { @@ -230,3 +252,19 @@ message RemoveWorkerTagsRequest { message RemoveWorkerTagsResponse { resources.workers.v1.Worker item = 1; } + +message ReadCertificateAuthorityRequest { + string scope_id = 1; // @gotags: `class:"public"` +} + +message ReadCertificateAuthorityResponse { + resources.workers.v1.CertificateAuthority item = 1; +} + +message ReinitializeCertificateAuthorityRequest { + string scope_id = 1; // @gotags: `class:"public"` +} + +message ReinitializeCertificateAuthorityResponse { + resources.workers.v1.CertificateAuthority item = 1; +} diff --git a/internal/proto/controller/servers/v1/servers.proto b/internal/proto/controller/servers/v1/servers.proto index a22763f03..eb1afd312 100644 --- a/internal/proto/controller/servers/v1/servers.proto +++ b/internal/proto/controller/servers/v1/servers.proto @@ -29,4 +29,7 @@ message ServerWorkerStatus { // The key id for this worker, if applicable (optional) string key_id = 50; // @gotags: `class:"public"` + + // The version of Boundary the worker binary is running + string release_version = 60 [json_name = "release_version"]; // @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 9bb432f2d..bc582c5f1 100644 --- a/internal/proto/controller/storage/servers/store/v1/worker.proto +++ b/internal/proto/controller/storage/servers/store/v1/worker.proto @@ -54,6 +54,10 @@ message Worker { // The type of the worker, denoted by how it authenticates: pki or kms. // @inject_tag: `gorm:"not_null"` string type = 130; + + // The version of Boundary the worker binary is running + // @inject_tag: `gorm:"default:null"` + string release_version = 140; } // WorkerTag is a tag for a worker. The primary key is comprised of the diff --git a/internal/server/job/rotate_roots_job.go b/internal/server/job/rotate_roots_job.go index 5122b7a21..cb623d8a8 100644 --- a/internal/server/job/rotate_roots_job.go +++ b/internal/server/job/rotate_roots_job.go @@ -71,7 +71,7 @@ func (r *rotateRootsJob) Status() scheduler.JobStatus { func (r *rotateRootsJob) Run(ctx context.Context) error { const op = "server.(rotateRootsJob).Run" - err := server.RotateRoots(ctx, r.workerAuthRepo) + _, err := server.RotateRoots(ctx, r.workerAuthRepo) if err != nil { return errors.Wrap(ctx, err, op) } diff --git a/internal/server/options.go b/internal/server/options.go index 7c869f66c..18ca8127b 100644 --- a/internal/server/options.go +++ b/internal/server/options.go @@ -42,6 +42,7 @@ type options struct { withRoot string withStopAfter uint WithCreateControllerLedActivationToken bool + withReleaseVersion string } func getDefaultOptions() options { @@ -196,3 +197,10 @@ func WithCreateControllerLedActivationToken(with bool) Option { o.WithCreateControllerLedActivationToken = with } } + +// WithRelease version provides an optional release version +func WithReleaseVersion(version string) Option { + return func(o *options) { + o.withReleaseVersion = version + } +} diff --git a/internal/server/options_test.go b/internal/server/options_test.go index 8b566c813..131daa1c4 100644 --- a/internal/server/options_test.go +++ b/internal/server/options_test.go @@ -182,4 +182,10 @@ func Test_GetOpts(t *testing.T) { opts = GetOpts(WithCreateControllerLedActivationToken(true)) assert.True(t, opts.WithCreateControllerLedActivationToken) }) + t.Run("WithReleaseVersion", func(t *testing.T) { + opts := getDefaultOptions() + assert.Empty(t, opts.withReleaseVersion) + opts = GetOpts(WithReleaseVersion("version")) + assert.Equal(t, "version", opts.withReleaseVersion) + }) } diff --git a/internal/server/repository_worker.go b/internal/server/repository_worker.go index daffcd8f6..e5dbce65a 100644 --- a/internal/server/repository_worker.go +++ b/internal/server/repository_worker.go @@ -294,7 +294,7 @@ func (r *Repository) UpsertWorkerStatus(ctx context.Context, worker *Worker, opt // "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, workerClone, []string{"address"}, nil) + n, err := w.Update(ctx, workerClone, []string{"address", "ReleaseVersion"}, nil) if err != nil { return errors.Wrap(ctx, err, op, errors.WithMsg("unable to update status of pki worker")) } @@ -311,7 +311,7 @@ func (r *Repository) UpsertWorkerStatus(ctx context.Context, worker *Worker, opt workerClone.Type = KmsWorkerType.String() workerCreateConflict := &db.OnConflict{ Target: db.Columns{"public_id"}, - Action: append(db.SetColumns([]string{"address"}), + Action: append(db.SetColumns([]string{"address", "release_version"}), db.SetColumnValues(map[string]interface{}{"last_status_time": "now()"})...), } var withRowsAffected int64 diff --git a/internal/server/repository_worker_test.go b/internal/server/repository_worker_test.go index f4e8100c3..b88727144 100644 --- a/internal/server/repository_worker_test.go +++ b/internal/server/repository_worker_test.go @@ -263,7 +263,8 @@ func TestUpsertWorkerStatus(t *testing.T) { t.Run("create an initial kms worker and update status", func(t *testing.T) { wStatus1 := server.NewWorker(scope.Global.String(), server.WithAddress("address"), server.WithName("config_name1"), - server.WithDescription("kms_description1")) + server.WithDescription("kms_description1"), + ) worker, err := repo.UpsertWorkerStatus(ctx, wStatus1) require.NoError(t, err) @@ -274,16 +275,18 @@ func TestUpsertWorkerStatus(t *testing.T) { assert.Equal(t, worker.GetLastStatusTime().AsTime(), worker.GetUpdateTime().AsTime()) assert.Equal(t, uint32(1), worker.Version) assert.Equal(t, "address", worker.GetAddress()) + assert.NotNil(t, worker.ReleaseVersion) // update again and see updated last status time wStatus2 := server.NewWorker(scope.Global.String(), - server.WithAddress("new_address"), server.WithName("config_name1")) + server.WithAddress("new_address"), server.WithName("config_name1"), server.WithReleaseVersion("test-version")) 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) // Version does not change for status updates assert.Equal(t, uint32(1), worker.Version) + assert.Equal(t, "test-version", wStatus2.ReleaseVersion) assert.Equal(t, "new_address", worker.GetAddress()) }) @@ -293,8 +296,9 @@ func TestUpsertWorkerStatus(t *testing.T) { t.Run("update status for pki worker", func(t *testing.T) { wStatus1 := server.NewWorker(scope.Global.String(), - server.WithAddress("pki_address"), server.WithDescription("pki_description2")) - worker, err := repo.UpsertWorkerStatus(ctx, wStatus1, server.WithKeyId(pkiWorkerKeyId)) + server.WithAddress("pki_address"), server.WithDescription("pki_description2"), + server.WithReleaseVersion("test-version")) + worker, err := repo.UpsertWorkerStatus(ctx, wStatus1, server.WithKeyId(pkiWorkerKeyId), server.WithReleaseVersion("test-version")) require.NoError(t, err) assert.True(t, strings.HasPrefix(worker.GetPublicId(), "w_")) @@ -305,6 +309,7 @@ func TestUpsertWorkerStatus(t *testing.T) { assert.Equal(t, worker.GetLastStatusTime().AsTime(), worker.GetUpdateTime().AsTime()) assert.Equal(t, uint32(1), worker.Version) assert.Equal(t, "pki_address", worker.GetAddress()) + assert.Equal(t, "test-version", worker.ReleaseVersion) }) failureCases := []struct { diff --git a/internal/server/repository_workerauth.go b/internal/server/repository_workerauth.go index 35117a870..f2d218193 100644 --- a/internal/server/repository_workerauth.go +++ b/internal/server/repository_workerauth.go @@ -229,7 +229,7 @@ func (r *WorkerAuthRepositoryStorage) convertRootCertificate(ctx context.Context rootCert.NotValidBefore = timestamp.New(cert.NotBefore.AsTime()) rootCert.PublicKey = cert.PublicKeyPkix rootCert.State = cert.Id - rootCert.IssuingCa = ca_id + rootCert.IssuingCa = CaId // Encrypt the private key databaseWrapper, err := r.kms.GetWrapper(ctx, scope.Global.String(), kms.KeyPurposeDatabase) @@ -280,7 +280,7 @@ func (r *WorkerAuthRepositoryStorage) storeRootCertificates(ctx context.Context, } certAuthority := &CertificateAuthority{ CertificateAuthority: &store.CertificateAuthority{ - PrivateId: ca_id, + PrivateId: CaId, Version: version + 1, }, } @@ -698,7 +698,7 @@ func (r *WorkerAuthRepositoryStorage) removeCertificateAuthority(ctx context.Con } certAuthority := &CertificateAuthority{ CertificateAuthority: &store.CertificateAuthority{ - PrivateId: ca_id, + PrivateId: CaId, Version: version + 1, }, } @@ -730,6 +730,7 @@ func (r *WorkerAuthRepositoryStorage) removeCertificateAuthority(ctx context.Con if err != nil { return errors.Wrap(ctx, err, op) } + cert.State.Fields["version"] = structpb.NewNumberValue(float64(version + 1)) return nil } diff --git a/internal/server/repository_workerauth_test.go b/internal/server/repository_workerauth_test.go index 8df8c3c81..2fb82513b 100644 --- a/internal/server/repository_workerauth_test.go +++ b/internal/server/repository_workerauth_test.go @@ -49,7 +49,7 @@ func TestStoreRootCertificates(t *testing.T) { require.NoError(err) // Fail to find root certificates prior to rotation/ creation - noCertAuth := &types.RootCertificates{Id: ca_id} + noCertAuth := &types.RootCertificates{Id: CaId} err = workerAuthRepo.Load(ctx, noCertAuth) require.Error(err) rootIds, err := workerAuthRepo.List(ctx, (*types.RootCertificate)(nil)) @@ -64,7 +64,7 @@ func TestStoreRootCertificates(t *testing.T) { assert.Len(rootIds, 2) // Load stored roots - certAuthority := &types.RootCertificates{Id: ca_id} + certAuthority := &types.RootCertificates{Id: CaId} err = workerAuthRepo.Load(ctx, certAuthority) require.NoError(err) require.NotNil(certAuthority.GetNext()) @@ -103,7 +103,7 @@ func TestStoreCertAuthorityVersioning(t *testing.T) { roots, err := rotation.RotateRootCertificates(ctx, workerAuthRepo) require.NoError(err) - cAuth2 := &types.RootCertificates{Id: ca_id} + cAuth2 := &types.RootCertificates{Id: CaId} err = workerAuthRepo.Load(ctx, cAuth2) require.NoError(err) var result2 rootCertificatesVersion @@ -118,7 +118,7 @@ func TestStoreCertAuthorityVersioning(t *testing.T) { badState, err := structpb.NewStruct(s.Map()) require.NoError(err) newRoots2 := &types.RootCertificates{ - Id: ca_id, + Id: CaId, Next: roots.Next, Current: roots.Current, } @@ -127,7 +127,7 @@ func TestStoreCertAuthorityVersioning(t *testing.T) { require.Error(err) // Remove CA, expect updated version - cAuthRemove := &types.RootCertificates{Id: ca_id} + cAuthRemove := &types.RootCertificates{Id: CaId} removeVersion := &rootCertificatesVersion{Version: uint32(2)} s = structs.New(removeVersion) s.TagName = "mapstructure" diff --git a/internal/server/root_certificate.go b/internal/server/root_certificate.go index d700872b5..20511b754 100644 --- a/internal/server/root_certificate.go +++ b/internal/server/root_certificate.go @@ -12,8 +12,8 @@ import ( ) // The CertificateAuthority id will always be set to "roots". -// The const ca_id contains this value -const ca_id = "roots" +// The const CaId contains this value +const CaId = "roots" // CertificateAuthority is a versioned entity used to lock the database when rotation RootCertificates type CertificateAuthority struct { @@ -24,7 +24,7 @@ type CertificateAuthority struct { func newCertificateAuthority() *CertificateAuthority { ca := &CertificateAuthority{ CertificateAuthority: &store.CertificateAuthority{ - PrivateId: ca_id, + PrivateId: CaId, }, } return ca @@ -96,7 +96,7 @@ func newRootCertificate(ctx context.Context, serialNumber uint64, certificate [] PrivateKey: rootCertificateKeys.privateKey, KeyId: keyId, State: string(state), - IssuingCa: ca_id, + IssuingCa: CaId, }, } return l, nil diff --git a/internal/server/service_reinitialize_roots.go b/internal/server/service_reinitialize_roots.go new file mode 100644 index 000000000..e65b5e5cc --- /dev/null +++ b/internal/server/service_reinitialize_roots.go @@ -0,0 +1,29 @@ +package server + +import ( + "context" + + "github.com/hashicorp/boundary/internal/errors" + "github.com/hashicorp/nodeenrollment" + "github.com/hashicorp/nodeenrollment/types" +) + +// ReinitializeRoots is a domain service function that removes both root certificates and then +// calls RotateRoots to generate new root certificates. +// Accepts the nodeenrollment option, WithCertificateLifetime(time.Duration) to specify the lifetime +// of the generated cert(s) +func ReinitializeRoots(ctx context.Context, workerAuthRepo *WorkerAuthRepositoryStorage, opt ...nodeenrollment.Option) (*types.RootCertificates, error) { + const op = "server.ReinitializeRoots" + if workerAuthRepo == nil { + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing workerAuthRepo") + } + + // Use WithReinitializeRoots to ensure existing roots are removed before rotation + opt = append(opt, nodeenrollment.WithReinitializeRoots(true)) + roots, err := RotateRoots(ctx, workerAuthRepo, opt...) + if err != nil { + return nil, errors.Wrap(ctx, err, op) + } + + return roots, nil +} diff --git a/internal/server/service_reinitialize_roots_test.go b/internal/server/service_reinitialize_roots_test.go new file mode 100644 index 000000000..1f892ba11 --- /dev/null +++ b/internal/server/service_reinitialize_roots_test.go @@ -0,0 +1,84 @@ +package server + +import ( + "context" + "crypto/rand" + "testing" + "time" + + "github.com/hashicorp/boundary/internal/db" + "github.com/hashicorp/boundary/internal/kms" + "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/nodeenrollment" + "github.com/hashicorp/nodeenrollment/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestReinitializeRoots(t *testing.T) { + require, assert := require.New(t), assert.New(t) + ctx := context.Background() + wrapper := db.TestWrapper(t) + conn, _ := db.TestSetup(t, "postgres") + kmsCache := kms.TestKms(t, conn, wrapper) + err := kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)) + require.NoError(err) + + rw := db.New(conn) + workerAuthRepo, err := NewRepositoryStorage(ctx, rw, rw, kmsCache) + require.NoError(err) + + // Check that we have no roots first + rootIds, err := workerAuthRepo.List(ctx, (*types.RootCertificate)(nil)) + require.NoError(err) + assert.Len(rootIds, 0) + + // Generate roots + _, err = RotateRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) + require.NoError(err) + + // Check that we have roots now + rootIds, err = workerAuthRepo.List(ctx, (*types.RootCertificate)(nil)) + require.NoError(err) + assert.Len(rootIds, 2) + certAuthority := &types.RootCertificates{Id: CaId} + err = workerAuthRepo.Load(ctx, certAuthority) + require.NoError(err) + require.NotNil(certAuthority.GetNext()) + require.NotNil(certAuthority.GetCurrent()) + + initialNext := certAuthority.GetNext() + initialCurrent := certAuthority.GetCurrent() + + // Reinitialize roots and assert that they're entirely new + newCerts, err := ReinitializeRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) + require.NoError(err) + + require.NotNil(newCerts.GetNext()) + require.NotNil(newCerts.GetCurrent()) + reinitNext := newCerts.GetNext() + reinitCurrent := newCerts.GetCurrent() + + // Next and current should have changed + assert.NotEqual(initialNext.PublicKeyPkix, reinitNext.PublicKeyPkix) + assert.NotEqual(initialCurrent.PublicKeyPkix, reinitCurrent.PublicKeyPkix) + assert.NotEqual(initialNext.PublicKeyPkix, reinitCurrent.PublicKeyPkix) + assert.NotEqual(initialCurrent.PublicKeyPkix, reinitNext.PublicKeyPkix) +} + +func TestReinitializeFailure(t *testing.T) { + require := require.New(t) + ctx := context.Background() + wrapper := db.TestWrapper(t) + conn, _ := db.TestSetup(t, "postgres") + + kmsCache := kms.TestKms(t, conn, wrapper) + err := kmsCache.CreateKeys(context.Background(), scope.Global.String(), kms.WithRandomReader(rand.Reader)) + require.NoError(err) + + workerAuthRepo, err := NewRepositoryStorage(ctx, &db.Db{}, &db.Db{}, kmsCache) + require.NoError(err) + + _, err = ReinitializeRoots(ctx, workerAuthRepo) + require.Error(err) +} diff --git a/internal/server/service_rotate_roots.go b/internal/server/service_rotate_roots.go index 57a2806c4..383b8852a 100644 --- a/internal/server/service_rotate_roots.go +++ b/internal/server/service_rotate_roots.go @@ -6,22 +6,31 @@ import ( "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/nodeenrollment" "github.com/hashicorp/nodeenrollment/rotation" + "github.com/hashicorp/nodeenrollment/types" ) // RotateRoots is a domain service function that initiates a rotation of root certificates // via a call to the nodenenrollment RotateRootCertificates function // Accepts the nodeenrollment option, WithCertificateLifetime(time.Duration) to specify the lifetime // of the generated cert(s) -func RotateRoots(ctx context.Context, workerAuthRepo *WorkerAuthRepositoryStorage, opt ...nodeenrollment.Option) error { +func RotateRoots(ctx context.Context, workerAuthRepo *WorkerAuthRepositoryStorage, opt ...nodeenrollment.Option) (*types.RootCertificates, error) { const op = "server.RotateRoots" if workerAuthRepo == nil { - return errors.New(ctx, errors.InvalidParameter, op, "missing workerAuthRepo") + return nil, errors.New(ctx, errors.InvalidParameter, op, "missing workerAuthRepo") } - _, err := rotation.RotateRootCertificates(ctx, workerAuthRepo, opt...) + // Get current root certs so we can pass along the version + rootCerts := &types.RootCertificates{Id: CaId} + err := workerAuthRepo.Load(ctx, rootCerts) + if err != nil && err != nodeenrollment.ErrNotFound { + return nil, errors.Wrap(ctx, err, op) + } + opt = append(opt, nodeenrollment.WithState(rootCerts.GetState())) + + roots, err := rotation.RotateRootCertificates(ctx, workerAuthRepo, opt...) if err != nil { - return errors.Wrap(ctx, err, op) + return nil, errors.Wrap(ctx, err, op) } - return nil + return roots, nil } diff --git a/internal/server/service_rotate_roots_test.go b/internal/server/service_rotate_roots_test.go index 2a4687ce7..d42267de7 100644 --- a/internal/server/service_rotate_roots_test.go +++ b/internal/server/service_rotate_roots_test.go @@ -34,40 +34,37 @@ func TestRotateRoots(t *testing.T) { assert.Len(rootIds, 0) // Generate roots - err = RotateRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) + roots, err := RotateRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) require.NoError(err) // Check that we have roots now rootIds, err = workerAuthRepo.List(ctx, (*types.RootCertificate)(nil)) require.NoError(err) assert.Len(rootIds, 2) - certAuthority := &types.RootCertificates{Id: ca_id} + certAuthority := &types.RootCertificates{Id: CaId} err = workerAuthRepo.Load(ctx, certAuthority) require.NoError(err) require.NotNil(certAuthority.GetNext()) require.NotNil(certAuthority.GetCurrent()) - initialNext := certAuthority.GetNext() - initialCurrent := certAuthority.GetCurrent() + initialNext := roots.GetNext() + initialCurrent := roots.GetCurrent() // Rotate roots and assert that they've rotated - err = RotateRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) + newRoots, err := RotateRoots(ctx, workerAuthRepo, nodeenrollment.WithCertificateLifetime(time.Second*5)) require.NoError(err) - certAuthority2 := &types.RootCertificates{Id: ca_id} - err = workerAuthRepo.Load(ctx, certAuthority2) - require.NoError(err) - require.NotNil(certAuthority2.GetNext()) - require.NotNil(certAuthority2.GetCurrent()) - rotatedNext := certAuthority2.GetNext() - rotatedCurrent := certAuthority2.GetCurrent() + require.NotNil(newRoots.GetNext()) + require.NotNil(newRoots.GetCurrent()) + rotatedNext := newRoots.GetNext() + rotatedCurrent := newRoots.GetCurrent() // Next and current should have changed - assert.NotEqual(initialNext, rotatedNext) - assert.NotEqual(initialCurrent, rotatedCurrent) + assert.NotEqual(initialNext.PublicKeyPkix, rotatedNext.PublicKeyPkix) + assert.NotEqual(initialCurrent.PublicKeyPkix, rotatedCurrent.PublicKeyPkix) // And the old next root should now be current - assert.Equal(initialNext, rotatedCurrent) + assert.Equal(initialNext.PublicKeyPkix, rotatedCurrent.PublicKeyPkix) } func TestRotateRootsFailure(t *testing.T) { @@ -83,6 +80,6 @@ func TestRotateRootsFailure(t *testing.T) { workerAuthRepo, err := NewRepositoryStorage(ctx, &db.Db{}, &db.Db{}, kmsCache) require.NoError(err) - err = RotateRoots(ctx, workerAuthRepo) + _, err = RotateRoots(ctx, workerAuthRepo) require.Error(err) } diff --git a/internal/server/store/worker.pb.go b/internal/server/store/worker.pb.go index 6a95ab424..b86edcc8e 100644 --- a/internal/server/store/worker.pb.go +++ b/internal/server/store/worker.pb.go @@ -58,6 +58,9 @@ type Worker struct { // 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"` + // The version of Boundary the worker binary is running + // @inject_tag: `gorm:"default:null"` + ReleaseVersion string `protobuf:"bytes,140,opt,name=release_version,json=releaseVersion,proto3" json:"release_version,omitempty" gorm:"default:null"` } func (x *Worker) Reset() { @@ -162,6 +165,13 @@ func (x *Worker) GetType() string { return "" } +func (x *Worker) GetReleaseVersion() string { + if x != nil { + return x.ReleaseVersion + } + return "" +} + // WorkerTag is a tag for a worker. The primary key is comprised of the // worker_id, key, value, and source. type WorkerTag struct { @@ -257,7 +267,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, 0xe1, 0x03, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8b, 0x04, 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,18 +297,21 @@ var file_controller_storage_servers_store_v1_worker_proto_rawDesc = []byte{ 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, 0x3b, 0x5a, 0x39, 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, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x28, 0x0a, 0x0f, 0x72, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x8c, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 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, 0x3b, 0x5a, 0x39, + 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, 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/server/testing.go b/internal/server/testing.go index 685e09625..a3c347661 100644 --- a/internal/server/testing.go +++ b/internal/server/testing.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/boundary/internal/kms" "github.com/hashicorp/boundary/internal/server/store" "github.com/hashicorp/boundary/internal/types/scope" + "github.com/hashicorp/boundary/version" wrapping "github.com/hashicorp/go-kms-wrapping/v2" "github.com/hashicorp/nodeenrollment" "github.com/hashicorp/nodeenrollment/registration" @@ -111,10 +112,13 @@ func TestKmsWorker(t *testing.T, conn *db.DB, wrapper wrapping.Wrapper, opt ...O if opts.withAddress != "" { address = opts.withAddress } + versionInfo := version.Get() + relVer := versionInfo.FullVersionNumber(false) wrk := NewWorker(scope.Global.String(), WithName(name), WithAddress(address), - WithDescription(opts.withDescription)) + WithDescription(opts.withDescription), + WithReleaseVersion(relVer)) wrk, err = serversRepo.UpsertWorkerStatus(ctx, wrk) require.NoError(t, err) require.NotNil(t, wrk) diff --git a/internal/server/worker.go b/internal/server/worker.go index 99b1d6590..5c30fe5e4 100644 --- a/internal/server/worker.go +++ b/internal/server/worker.go @@ -79,10 +79,11 @@ func NewWorker(scopeId string, opt ...Option) *Worker { opts := GetOpts(opt...) return &Worker{ Worker: &store.Worker{ - ScopeId: scopeId, - Name: opts.withName, - Description: opts.withDescription, - Address: opts.withAddress, + ScopeId: scopeId, + Name: opts.withName, + Description: opts.withDescription, + Address: opts.withAddress, + ReleaseVersion: opts.withReleaseVersion, }, inputTags: opts.withWorkerTags, } @@ -192,6 +193,7 @@ type workerAggregate struct { Address string Version uint32 Type string + ReleaseVersion string ApiTags string ActiveConnectionCount uint32 // Config Fields @@ -213,6 +215,7 @@ func (a *workerAggregate) toWorker(ctx context.Context) (*Worker, error) { Version: a.Version, LastStatusTime: a.LastStatusTime, Type: a.Type, + ReleaseVersion: a.ReleaseVersion, }, activeConnectionCount: a.ActiveConnectionCount, } diff --git a/internal/server/worker_test.go b/internal/server/worker_test.go index a70b9b382..daf5a9979 100644 --- a/internal/server/worker_test.go +++ b/internal/server/worker_test.go @@ -72,6 +72,7 @@ func TestWorkerAggregate(t *testing.T) { assert.Equal(t, "address", got.GetAddress()) assert.Equal(t, uint32(1), got.GetVersion()) assert.NotNil(t, got.GetLastStatusTime()) + assert.NotNil(t, got.GetReleaseVersion()) assert.Empty(t, got.CanonicalTags()) }) @@ -90,6 +91,7 @@ func TestWorkerAggregate(t *testing.T) { assert.Equal(t, id, got.GetPublicId()) assert.Equal(t, uint32(1), got.GetVersion()) assert.NotNil(t, got.GetLastStatusTime()) + assert.NotNil(t, got.GetReleaseVersion()) assert.Equal(t, strings.ToLower(id), got.GetName()) assert.Equal(t, "address", got.GetAddress()) }) @@ -115,6 +117,7 @@ func TestWorkerAggregate(t *testing.T) { assert.Equal(t, id, got.GetPublicId()) assert.Equal(t, uint32(1), got.GetVersion()) assert.NotNil(t, got.GetLastStatusTime()) + assert.NotNil(t, got.GetReleaseVersion()) assert.Empty(t, got.apiTags) assert.Equal(t, got.configTags, []*Tag{{Key: "key", Value: "val"}}) }) diff --git a/internal/server/workerauth_store_test.go b/internal/server/workerauth_store_test.go index 058efb523..4ea706ea2 100644 --- a/internal/server/workerauth_store_test.go +++ b/internal/server/workerauth_store_test.go @@ -75,7 +75,7 @@ func TestRootCertStore(t *testing.T) { NotValidAfter: afterTimestamp, KeyId: testKey, State: "next", - IssuingCa: ca_id, + IssuingCa: CaId, }, wantErr: false, }, @@ -99,7 +99,7 @@ func TestRootCertStore(t *testing.T) { NotValidAfter: afterTimestamp, KeyId: testKey, State: "current", - IssuingCa: ca_id, + IssuingCa: CaId, }, wantErr: false, }, diff --git a/internal/types/action/action.go b/internal/types/action/action.go index b9632d972..551d5bd29 100644 --- a/internal/types/action/action.go +++ b/internal/types/action/action.go @@ -8,112 +8,117 @@ import ( type Type uint const ( - Unknown Type = 0 - List Type = 1 - Create Type = 2 - Update Type = 3 - Read Type = 4 - Delete Type = 5 - Authenticate Type = 6 - All Type = 7 - AuthorizeSession Type = 8 - AddGrants Type = 9 - RemoveGrants Type = 10 - SetGrants Type = 11 - AddPrincipals Type = 12 - SetPrincipals Type = 13 - RemovePrincipals Type = 14 - Deauthenticate Type = 15 - AddMembers Type = 16 - SetMembers Type = 17 - RemoveMembers Type = 18 - SetPassword Type = 19 - ChangePassword Type = 20 - AddHosts Type = 21 - SetHosts Type = 22 - RemoveHosts Type = 23 - AddHostSets Type = 24 // DEPRECATED - SetHostSets Type = 25 // DEPRECATED - RemoveHostSets Type = 26 // DEPRECATED - Cancel Type = 27 - AddAccounts Type = 28 - SetAccounts Type = 29 - RemoveAccounts Type = 30 - ReadSelf Type = 31 - CancelSelf Type = 32 - ChangeState Type = 33 - DeleteSelf Type = 34 - NoOp Type = 35 - AddCredentialLibraries Type = 36 // DEPRECATED - SetCredentialLibraries Type = 37 // DEPRECATED - RemoveCredentialLibraries Type = 38 // DEPRECATED - AddCredentialSources Type = 39 - SetCredentialSources Type = 40 - RemoveCredentialSources Type = 41 - AddHostSources Type = 42 - SetHostSources Type = 43 - RemoveHostSources Type = 44 - CreateWorkerLed Type = 45 - AddWorkerTags Type = 46 - SetWorkerTags Type = 47 - RemoveWorkerTags Type = 48 - CreateControllerLed Type = 49 + Unknown Type = 0 + List Type = 1 + Create Type = 2 + Update Type = 3 + Read Type = 4 + Delete Type = 5 + Authenticate Type = 6 + All Type = 7 + AuthorizeSession Type = 8 + AddGrants Type = 9 + RemoveGrants Type = 10 + SetGrants Type = 11 + AddPrincipals Type = 12 + SetPrincipals Type = 13 + RemovePrincipals Type = 14 + Deauthenticate Type = 15 + AddMembers Type = 16 + SetMembers Type = 17 + RemoveMembers Type = 18 + SetPassword Type = 19 + ChangePassword Type = 20 + AddHosts Type = 21 + SetHosts Type = 22 + RemoveHosts Type = 23 + AddHostSets Type = 24 // DEPRECATED + SetHostSets Type = 25 // DEPRECATED + RemoveHostSets Type = 26 // DEPRECATED + Cancel Type = 27 + AddAccounts Type = 28 + SetAccounts Type = 29 + RemoveAccounts Type = 30 + ReadSelf Type = 31 + CancelSelf Type = 32 + ChangeState Type = 33 + DeleteSelf Type = 34 + NoOp Type = 35 + AddCredentialLibraries Type = 36 // DEPRECATED + SetCredentialLibraries Type = 37 // DEPRECATED + RemoveCredentialLibraries Type = 38 // DEPRECATED + AddCredentialSources Type = 39 + SetCredentialSources Type = 40 + RemoveCredentialSources Type = 41 + AddHostSources Type = 42 + SetHostSources Type = 43 + RemoveHostSources Type = 44 + CreateWorkerLed Type = 45 + AddWorkerTags Type = 46 + SetWorkerTags Type = 47 + RemoveWorkerTags Type = 48 + CreateControllerLed Type = 49 + ReinitializeCertificateAuthority Type = 50 + ReadCertificateAuthority Type = 51 // When adding new actions, be sure to update: // - // * The Test_AnonRestrictions test + // * The Test_AnonRestrictions test: update the following line to include the last action: + // for j := action.Type(1); j <= action.; j++ { ) var Map = map[string]Type{ - Create.String(): Create, - List.String(): List, - Update.String(): Update, - Read.String(): Read, - Delete.String(): Delete, - Authenticate.String(): Authenticate, - All.String(): All, - AuthorizeSession.String(): AuthorizeSession, - AddGrants.String(): AddGrants, - RemoveGrants.String(): RemoveGrants, - SetGrants.String(): SetGrants, - AddPrincipals.String(): AddPrincipals, - SetPrincipals.String(): SetPrincipals, - RemovePrincipals.String(): RemovePrincipals, - Deauthenticate.String(): Deauthenticate, - AddMembers.String(): AddMembers, - SetMembers.String(): SetMembers, - RemoveMembers.String(): RemoveMembers, - SetPassword.String(): SetPassword, - ChangePassword.String(): ChangePassword, - AddHosts.String(): AddHosts, - SetHosts.String(): SetHosts, - RemoveHosts.String(): RemoveHosts, - AddHostSets.String(): AddHostSets, - SetHostSets.String(): SetHostSets, - RemoveHostSets.String(): RemoveHostSets, - Cancel.String(): Cancel, - AddAccounts.String(): AddAccounts, - SetAccounts.String(): SetAccounts, - RemoveAccounts.String(): RemoveAccounts, - ReadSelf.String(): ReadSelf, - CancelSelf.String(): CancelSelf, - ChangeState.String(): ChangeState, - DeleteSelf.String(): DeleteSelf, - NoOp.String(): NoOp, - AddCredentialLibraries.String(): AddCredentialLibraries, - SetCredentialLibraries.String(): SetCredentialLibraries, - RemoveCredentialLibraries.String(): RemoveCredentialLibraries, - AddCredentialSources.String(): AddCredentialSources, - SetCredentialSources.String(): SetCredentialSources, - RemoveCredentialSources.String(): RemoveCredentialSources, - AddHostSources.String(): AddHostSources, - SetHostSources.String(): SetHostSources, - RemoveHostSources.String(): RemoveHostSources, - CreateWorkerLed.String(): CreateWorkerLed, - AddWorkerTags.String(): AddWorkerTags, - SetWorkerTags.String(): SetWorkerTags, - RemoveWorkerTags.String(): RemoveWorkerTags, - CreateControllerLed.String(): CreateControllerLed, + Create.String(): Create, + List.String(): List, + Update.String(): Update, + Read.String(): Read, + Delete.String(): Delete, + Authenticate.String(): Authenticate, + All.String(): All, + AuthorizeSession.String(): AuthorizeSession, + AddGrants.String(): AddGrants, + RemoveGrants.String(): RemoveGrants, + SetGrants.String(): SetGrants, + AddPrincipals.String(): AddPrincipals, + SetPrincipals.String(): SetPrincipals, + RemovePrincipals.String(): RemovePrincipals, + Deauthenticate.String(): Deauthenticate, + AddMembers.String(): AddMembers, + SetMembers.String(): SetMembers, + RemoveMembers.String(): RemoveMembers, + SetPassword.String(): SetPassword, + ChangePassword.String(): ChangePassword, + AddHosts.String(): AddHosts, + SetHosts.String(): SetHosts, + RemoveHosts.String(): RemoveHosts, + AddHostSets.String(): AddHostSets, + SetHostSets.String(): SetHostSets, + RemoveHostSets.String(): RemoveHostSets, + Cancel.String(): Cancel, + AddAccounts.String(): AddAccounts, + SetAccounts.String(): SetAccounts, + RemoveAccounts.String(): RemoveAccounts, + ReadSelf.String(): ReadSelf, + CancelSelf.String(): CancelSelf, + ChangeState.String(): ChangeState, + DeleteSelf.String(): DeleteSelf, + NoOp.String(): NoOp, + AddCredentialLibraries.String(): AddCredentialLibraries, + SetCredentialLibraries.String(): SetCredentialLibraries, + RemoveCredentialLibraries.String(): RemoveCredentialLibraries, + AddCredentialSources.String(): AddCredentialSources, + SetCredentialSources.String(): SetCredentialSources, + RemoveCredentialSources.String(): RemoveCredentialSources, + AddHostSources.String(): AddHostSources, + SetHostSources.String(): SetHostSources, + RemoveHostSources.String(): RemoveHostSources, + CreateWorkerLed.String(): CreateWorkerLed, + AddWorkerTags.String(): AddWorkerTags, + SetWorkerTags.String(): SetWorkerTags, + RemoveWorkerTags.String(): RemoveWorkerTags, + CreateControllerLed.String(): CreateControllerLed, + ReinitializeCertificateAuthority.String(): ReinitializeCertificateAuthority, + ReadCertificateAuthority.String(): ReadCertificateAuthority, } func (a Type) String() string { @@ -168,6 +173,8 @@ func (a Type) String() string { "set-worker-tags", "remove-worker-tags", "create:controller-led", + "reinitialize-certificate-authority", + "read-certificate-authority", }[a] } diff --git a/internal/types/resource/resource.go b/internal/types/resource/resource.go index 84fca300e..2fb5147b6 100644 --- a/internal/types/resource/resource.go +++ b/internal/types/resource/resource.go @@ -31,7 +31,8 @@ const ( // * The Grant.validateType function and test // * The perms.topLevelType function // * The scopes service collection actions for appropriate scopes - // * The Test_AnonRestrictions test + // * The Test_AnonRestrictions test: update the following line to include the last resource: + // for i := resource.Type(1); i <= resource.; i++ { ) func (r Type) MarshalJSON() ([]byte, error) { diff --git a/sdk/pbs/controller/api/resources/workers/worker.pb.go b/sdk/pbs/controller/api/resources/workers/worker.pb.go index 0fca6402a..5b79b50a2 100644 --- a/sdk/pbs/controller/api/resources/workers/worker.pb.go +++ b/sdk/pbs/controller/api/resources/workers/worker.pb.go @@ -76,6 +76,8 @@ type Worker struct { Type string `protobuf:"bytes,170,opt,name=type,proto3" json:"type,omitempty"` // Output only. The api tags set for the worker. 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 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"` } @@ -231,6 +233,13 @@ func (x *Worker) GetApiTags() map[string]*structpb.ListValue { return nil } +func (x *Worker) GetReleaseVersion() string { + if x != nil { + return x.ReleaseVersion + } + return "" +} + func (x *Worker) GetAuthorizedActions() []string { if x != nil { return x.AuthorizedActions @@ -238,6 +247,128 @@ func (x *Worker) GetAuthorizedActions() []string { return nil } +type Certificate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Output only. The ID of the certificate + Id string `protobuf:"bytes,10,opt,name=id,proto3" json:"id,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The public key of the cert authority + PublicKeySha256 string `protobuf:"bytes,20,opt,name=public_key_sha256,json=publicKeySha256,proto3" json:"public_key_sha256,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The time before which this CA is invalid + NotBeforeTime *timestamppb.Timestamp `protobuf:"bytes,30,opt,name=not_before_time,json=notBeforeTime,proto3" json:"not_before_time,omitempty" class:"public"` // @gotags: `class:"public"` + // Output only. The time after which this CA is invalid + NotAfterTime *timestamppb.Timestamp `protobuf:"bytes,40,opt,name=not_after_time,json=notAfterTime,proto3" json:"not_after_time,omitempty" class:"public"` // @gotags: `class:"public"` +} + +func (x *Certificate) Reset() { + *x = Certificate{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Certificate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Certificate) ProtoMessage() {} + +func (x *Certificate) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[1] + 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 Certificate.ProtoReflect.Descriptor instead. +func (*Certificate) Descriptor() ([]byte, []int) { + return file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP(), []int{1} +} + +func (x *Certificate) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Certificate) GetPublicKeySha256() string { + if x != nil { + return x.PublicKeySha256 + } + return "" +} + +func (x *Certificate) GetNotBeforeTime() *timestamppb.Timestamp { + if x != nil { + return x.NotBeforeTime + } + return nil +} + +func (x *Certificate) GetNotAfterTime() *timestamppb.Timestamp { + if x != nil { + return x.NotAfterTime + } + return nil +} + +type CertificateAuthority struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Certs []*Certificate `protobuf:"bytes,10,rep,name=certs,proto3" json:"certs,omitempty" class:"public"` // @gotags: `class:"public"` +} + +func (x *CertificateAuthority) Reset() { + *x = CertificateAuthority{} + if protoimpl.UnsafeEnabled { + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CertificateAuthority) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertificateAuthority) ProtoMessage() {} + +func (x *CertificateAuthority) ProtoReflect() protoreflect.Message { + mi := &file_controller_api_resources_workers_v1_worker_proto_msgTypes[2] + 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 CertificateAuthority.ProtoReflect.Descriptor instead. +func (*CertificateAuthority) Descriptor() ([]byte, []int) { + return file_controller_api_resources_workers_v1_worker_proto_rawDescGZIP(), []int{2} +} + +func (x *CertificateAuthority) GetCerts() []*Certificate { + if x != nil { + return x.Certs + } + return nil +} + var File_controller_api_resources_workers_v1_worker_proto protoreflect.FileDescriptor var file_controller_api_resources_workers_v1_worker_proto_rawDesc = []byte{ @@ -258,7 +389,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, 0xc7, 0x0b, 0x0a, 0x06, 0x57, 0x6f, 0x72, 0x6b, 0x65, 0x72, 0x12, 0x0e, 0x0a, + 0x74, 0x6f, 0x22, 0xf2, 0x0b, 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, @@ -330,33 +461,55 @@ var file_controller_api_resources_workers_v1_worker_proto_rawDesc = []byte{ 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, 0x41, 0x70, 0x69, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x08, 0x61, 0x70, 0x69, 0x5f, 0x74, 0x61, 0x67, 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, + 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, 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, 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, + 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, + 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 ( @@ -371,39 +524,44 @@ 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, 4) +var file_controller_api_resources_workers_v1_worker_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_controller_api_resources_workers_v1_worker_proto_goTypes = []interface{}{ (*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 - nil, // 3: controller.api.resources.workers.v1.Worker.ApiTagsEntry - (*scopes.ScopeInfo)(nil), // 4: controller.api.resources.scopes.v1.ScopeInfo - (*wrapperspb.StringValue)(nil), // 5: google.protobuf.StringValue - (*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp - (*wrapperspb.UInt32Value)(nil), // 7: google.protobuf.UInt32Value - (*structpb.ListValue)(nil), // 8: google.protobuf.ListValue + (*Certificate)(nil), // 1: controller.api.resources.workers.v1.Certificate + (*CertificateAuthority)(nil), // 2: controller.api.resources.workers.v1.CertificateAuthority + nil, // 3: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry + nil, // 4: controller.api.resources.workers.v1.Worker.ConfigTagsEntry + nil, // 5: controller.api.resources.workers.v1.Worker.ApiTagsEntry + (*scopes.ScopeInfo)(nil), // 6: controller.api.resources.scopes.v1.ScopeInfo + (*wrapperspb.StringValue)(nil), // 7: google.protobuf.StringValue + (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*wrapperspb.UInt32Value)(nil), // 9: google.protobuf.UInt32Value + (*structpb.ListValue)(nil), // 10: google.protobuf.ListValue } var file_controller_api_resources_workers_v1_worker_proto_depIdxs = []int32{ - 4, // 0: controller.api.resources.workers.v1.Worker.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo - 5, // 1: controller.api.resources.workers.v1.Worker.name:type_name -> google.protobuf.StringValue - 5, // 2: controller.api.resources.workers.v1.Worker.description:type_name -> google.protobuf.StringValue - 6, // 3: controller.api.resources.workers.v1.Worker.created_time:type_name -> google.protobuf.Timestamp - 6, // 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 - 6, // 7: controller.api.resources.workers.v1.Worker.last_status_time:type_name -> google.protobuf.Timestamp - 5, // 8: controller.api.resources.workers.v1.Worker.worker_generated_auth_token:type_name -> google.protobuf.StringValue - 5, // 9: controller.api.resources.workers.v1.Worker.controller_generated_activation_token:type_name -> google.protobuf.StringValue - 7, // 10: controller.api.resources.workers.v1.Worker.active_connection_count:type_name -> google.protobuf.UInt32Value - 3, // 11: controller.api.resources.workers.v1.Worker.api_tags:type_name -> controller.api.resources.workers.v1.Worker.ApiTagsEntry - 8, // 12: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry.value:type_name -> google.protobuf.ListValue - 8, // 13: controller.api.resources.workers.v1.Worker.ConfigTagsEntry.value:type_name -> google.protobuf.ListValue - 8, // 14: controller.api.resources.workers.v1.Worker.ApiTagsEntry.value:type_name -> google.protobuf.ListValue - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name + 6, // 0: controller.api.resources.workers.v1.Worker.scope:type_name -> controller.api.resources.scopes.v1.ScopeInfo + 7, // 1: controller.api.resources.workers.v1.Worker.name:type_name -> google.protobuf.StringValue + 7, // 2: controller.api.resources.workers.v1.Worker.description:type_name -> google.protobuf.StringValue + 8, // 3: controller.api.resources.workers.v1.Worker.created_time:type_name -> google.protobuf.Timestamp + 8, // 4: controller.api.resources.workers.v1.Worker.updated_time:type_name -> google.protobuf.Timestamp + 3, // 5: controller.api.resources.workers.v1.Worker.canonical_tags:type_name -> controller.api.resources.workers.v1.Worker.CanonicalTagsEntry + 4, // 6: controller.api.resources.workers.v1.Worker.config_tags:type_name -> controller.api.resources.workers.v1.Worker.ConfigTagsEntry + 8, // 7: controller.api.resources.workers.v1.Worker.last_status_time:type_name -> google.protobuf.Timestamp + 7, // 8: controller.api.resources.workers.v1.Worker.worker_generated_auth_token:type_name -> google.protobuf.StringValue + 7, // 9: controller.api.resources.workers.v1.Worker.controller_generated_activation_token:type_name -> google.protobuf.StringValue + 9, // 10: controller.api.resources.workers.v1.Worker.active_connection_count:type_name -> google.protobuf.UInt32Value + 5, // 11: controller.api.resources.workers.v1.Worker.api_tags:type_name -> controller.api.resources.workers.v1.Worker.ApiTagsEntry + 8, // 12: controller.api.resources.workers.v1.Certificate.not_before_time:type_name -> google.protobuf.Timestamp + 8, // 13: controller.api.resources.workers.v1.Certificate.not_after_time:type_name -> google.protobuf.Timestamp + 1, // 14: controller.api.resources.workers.v1.CertificateAuthority.certs:type_name -> controller.api.resources.workers.v1.Certificate + 10, // 15: controller.api.resources.workers.v1.Worker.CanonicalTagsEntry.value:type_name -> google.protobuf.ListValue + 10, // 16: controller.api.resources.workers.v1.Worker.ConfigTagsEntry.value:type_name -> google.protobuf.ListValue + 10, // 17: controller.api.resources.workers.v1.Worker.ApiTagsEntry.value:type_name -> google.protobuf.ListValue + 18, // [18:18] is the sub-list for method output_type + 18, // [18:18] is the sub-list for method input_type + 18, // [18:18] is the sub-list for extension type_name + 18, // [18:18] is the sub-list for extension extendee + 0, // [0:18] is the sub-list for field type_name } func init() { file_controller_api_resources_workers_v1_worker_proto_init() } @@ -424,6 +582,30 @@ func file_controller_api_resources_workers_v1_worker_proto_init() { return nil } } + file_controller_api_resources_workers_v1_worker_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Certificate); 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[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CertificateAuthority); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -431,7 +613,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: 4, + NumMessages: 6, NumExtensions: 0, NumServices: 0, },