diff --git a/CHANGELOG.md b/CHANGELOG.md index 40710c93c1..bedc9dab7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,14 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ### Changes/Deprecations +Note: in addition to changes marked below in this section, be aware that +currently names of resources are case-sensitive, but in a future update they +will become case-preserving but case-insensitive for comparisons (e.g. if using +them to access targets). + * cli: There are two changes to token storage handling: - * Specifying `none` for the `token-name` parameter has been deprecated in - favor of specifying `none` for the new `keyring-type` parameter. + * Specifying `none` for the `-token-name` parameter has been deprecated in + favor of specifying `none` for the new `-keyring-type` parameter. * [`pass`](https://www.passwordstore.org/) is now the default keyring type on non-Windows/non-macOS platforms. See the [CLI docs page](https://www.boundaryproject.io/docs/api-clients/cli) for more @@ -16,9 +21,12 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. ### New and Improved -* cli: New `keyring-type` option and `pass` keyring type for token storage +* cli: New `-keyring-type` option and `pass` keyring type for token storage ([Issue](https://github.com/hashicorp/boundary/issues/697)) ([PR](https://github.com/hashicorp/boundary/issues/731)) +* connect: Allow using `-target-name` in conjunction with either + `-target-scope-id` or `-target-scope-name` to connect to targets, rather than + the target's ID. ([PR](https://github.com/hashicorp/boundary/pull/737)) * controller: Allow API/Cluster listeners to be Unix domain sockets ([Issue](https://github.com/hashicorp/boundary/pull/699)) ([PR](https://github.com/hashicorp/boundary/pull/705)) diff --git a/api/targets/custom.go b/api/targets/custom.go index bc084e1b73..89a9bb7198 100644 --- a/api/targets/custom.go +++ b/api/targets/custom.go @@ -26,12 +26,25 @@ func (n SessionAuthorizationResult) GetResponseMap() map[string]interface{} { } func (c *Client) AuthorizeSession(ctx context.Context, targetId string, opt ...Option) (*SessionAuthorizationResult, error) { + opts, apiOpts := getOpts(opt...) + if targetId == "" { - return nil, fmt.Errorf("empty targetId value passed into AuthorizeSession request") + if opts.postMap["name"] == nil { + return nil, fmt.Errorf("empty target name provided to AuthorizeSession request") + } + scopeIdEmpty := opts.postMap["scope_id"] == nil + scopeNameEmpty := opts.postMap["scope_name"] == nil + switch { + case scopeIdEmpty && scopeNameEmpty: + return nil, fmt.Errorf("empty targetId value and no combination of target name and scope ID/name passed into AuthorizeSession request") + case !scopeIdEmpty && !scopeNameEmpty: + return nil, fmt.Errorf("both scope ID and scope name cannot be provided in AuthorizeSession request") + default: + // Name is not empty and only one of scope ID or name set + targetId = opts.postMap["name"].(string) + } } - opts, apiOpts := getOpts(opt...) - if c.client == nil { return nil, fmt.Errorf("nil client") } diff --git a/api/targets/option.gen.go b/api/targets/option.gen.go index d53dce5e9e..305b3d1829 100644 --- a/api/targets/option.gen.go +++ b/api/targets/option.gen.go @@ -111,6 +111,18 @@ func DefaultName() Option { } } +func WithScopeId(inScopeId string) Option { + return func(o *options) { + o.postMap["scope_id"] = inScopeId + } +} + +func WithScopeName(inScopeName string) Option { + return func(o *options) { + o.postMap["scope_name"] = inScopeName + } +} + func WithSessionConnectionLimit(inSessionConnectionLimit int32) Option { return func(o *options) { o.postMap["session_connection_limit"] = inSessionConnectionLimit diff --git a/internal/api/genapi/input.go b/internal/api/genapi/input.go index 86bc08d8e6..e8545c4f58 100644 --- a/internal/api/genapi/input.go +++ b/internal/api/genapi/input.go @@ -365,6 +365,18 @@ var inputStructs = []*structInfo{ FieldType: "string", SkipDefault: true, }, + { + Name: "ScopeId", + ProtoName: "scope_id", + FieldType: "string", + SkipDefault: true, + }, + { + Name: "ScopeName", + ProtoName: "scope_name", + FieldType: "string", + SkipDefault: true, + }, }, versionEnabled: true, typeOnCreate: true, diff --git a/internal/auth/auth.go b/internal/auth/auth.go index c7788a60d2..95175be097 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -68,6 +68,11 @@ type VerifyResults struct { Error error Scope *scopes.ScopeInfo + // RoundTripValue can be set to allow the function performing authentication + // (often accompanied by lookup(s)) to return a result of that lookup to the + // calling function. It is opaque to this package. + RoundTripValue interface{} + // Used for additional verification v *verifier } diff --git a/internal/cmd/base/base.go b/internal/cmd/base/base.go index fa89fa56e2..6f9ba1c283 100644 --- a/internal/cmd/base/base.go +++ b/internal/cmd/base/base.go @@ -69,6 +69,7 @@ type Command struct { flagOutputCurlString bool FlagScopeId string + FlagScopeName string FlagId string FlagName string FlagDescription string diff --git a/internal/cmd/commands/connect/connect.go b/internal/cmd/commands/connect/connect.go index bfb01d0467..e4471e400f 100644 --- a/internal/cmd/commands/connect/connect.go +++ b/internal/cmd/commands/connect/connect.go @@ -64,6 +64,7 @@ type Command struct { flagListenAddr string flagListenPort int flagTargetId string + flagTargetName string flagHostId string flagExec string flagUsername string @@ -175,6 +176,28 @@ func (c *Command) Flags() *base.FlagSets { Usage: `If set, after connecting to the worker, the given binary will be executed. This should be a binary on your path, or an absolute path. If all command flags are followed by " -- " (space, two hyphens, space), then any arguments after that will be sent directly to the binary.`, }) + f.StringVar(&base.StringVar{ + Name: "target-name", + Target: &c.flagTargetName, + Usage: "Target name, if authorizing the session via scope parameters and target name.", + }) + + f.StringVar(&base.StringVar{ + Name: "target-scope-id", + Target: &c.FlagScopeId, + EnvVar: "BOUNDARY_CONNECT_TARGET_SCOPE_ID", + Completion: complete.PredictAnything, + Usage: "Target scope ID, if authorizing the session via scope parameters and target name. Mutually exclusive with -scope-name.", + }) + + f.StringVar(&base.StringVar{ + Name: "target-scope-name", + Target: &c.FlagScopeName, + EnvVar: "BOUNDARY_CONNECT_TARGET_SCOPE_NAME", + Completion: complete.PredictAnything, + Usage: "Target scope name, if authorizing the session via scope parameters and target name. Mutually exclusive with -scope-id.", + }) + switch c.Func { case "connect": f.StringVar(&base.StringVar{ @@ -237,9 +260,21 @@ func (c *Command) Run(args []string) (retCode int) { case c.flagAuthzToken != "" && c.flagTargetId != "": c.UI.Error(`-target-id and -authz-token cannot both be specified`) return 1 - case c.flagAuthzToken == "" && c.flagTargetId == "": - c.UI.Error(`One of -target-id and -authz-token must be set`) + case c.flagAuthzToken != "" && c.flagTargetName != "": + c.UI.Error(`-target-name and -authz-token cannot both be specified`) return 1 + default: + if c.flagTargetId == "" && + (c.flagTargetName == "" || + (c.FlagScopeId == "" && c.FlagScopeName == "")) { + c.UI.Error("Target ID was not passed in, but no combination of target name and scope ID/name was passed in either") + return 1 + } + if c.flagTargetId != "" && + (c.flagTargetName != "" || c.FlagScopeId != "" || c.FlagScopeName != "") { + c.UI.Error("Cannot specify a target ID and also other lookup parameters") + return 1 + } } if c.flagExec == "" { @@ -314,6 +349,15 @@ func (c *Command) Run(args []string) (retCode int) { if len(c.flagHostId) != 0 { opts = append(opts, targets.WithHostId(c.flagHostId)) } + if len(c.flagTargetName) > 0 { + opts = append(opts, targets.WithName(c.flagTargetName)) + } + if len(c.FlagScopeId) > 0 { + opts = append(opts, targets.WithScopeId(c.FlagScopeId)) + } + if len(c.FlagScopeName) > 0 { + opts = append(opts, targets.WithScopeName(c.FlagScopeName)) + } sar, err := targetClient.AuthorizeSession(c.Context, c.flagTargetId, opts...) if err != nil { diff --git a/internal/cmd/commands/targets/target.go b/internal/cmd/commands/targets/target.go index 2252567987..96727160db 100644 --- a/internal/cmd/commands/targets/target.go +++ b/internal/cmd/commands/targets/target.go @@ -130,10 +130,14 @@ func (c *Command) Help() string { "", " This command allows fetching session authorization credentials against a target. Example:", "", - " Set host-set resources on a tcp-type target:", + " Request an authorized session using the target ID:", "", ` $ boundary targets authorize-session -id ttcp_1234567890`, "", + " Request an authorized session using the scope ID and target name:", + "", + ` $ boundary targets authorize-session -scope-id o_1234567890 -name prod-ssh`, + "", "", }) default: @@ -168,6 +172,34 @@ func (c *Command) Flags() *base.FlagSets { } } + if c.Func == "authorize-session" { + flagsMap[c.Func] = append(flagsMap[c.Func], "name", "scope-id", "scope-name") + + // We put these here to change usage and change defaults (don't want + // them populated by default) + f.StringVar(&base.StringVar{ + Name: "name", + Target: &c.FlagName, + Usage: "Target name, if authorizing the session via scope parameters and target name.", + }) + + f.StringVar(&base.StringVar{ + Name: "scope-id", + Target: &c.FlagScopeId, + EnvVar: "BOUNDARY_SCOPE_ID", + Completion: complete.PredictAnything, + Usage: "Target scope ID, if authorizing the session via scope parameters and target name. Mutually exclusive with -scope-name.", + }) + + f.StringVar(&base.StringVar{ + Name: "scope-name", + Target: &c.FlagScopeName, + EnvVar: "BOUNDARY_SCOPE_NAME", + Completion: complete.PredictAnything, + Usage: "Target scope name, if authorizing the session via scope parameters and target name. Mutually exclusive with -scope-id.", + }) + } + return set } @@ -197,13 +229,41 @@ func (c *Command) Run(args []string) int { return 1 } - if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" { - c.UI.Error("ID is required but not passed in via -id") - return 1 + var opts []targets.Option + + if strutil.StrListContains(flagsMap[c.Func], "id") { + switch c.Func { + case "authorize-session": + if c.FlagId == "" && + (c.FlagName == "" || + (c.FlagScopeId == "" && c.FlagScopeName == "")) { + c.UI.Error("ID was not passed in, but no combination of name and scope ID/name was passed in either") + return 1 + } + if c.FlagId != "" && + (c.FlagName != "" || c.FlagScopeId != "" || c.FlagScopeName != "") { + c.UI.Error("Cannot specify a target ID and also other lookup parameters") + return 1 + } + default: + if c.FlagId == "" { + c.UI.Error("ID is required but not passed in via -id") + return 1 + } + } } - if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" { - c.UI.Error("Scope ID must be passed in via -scope-id") - return 1 + if strutil.StrListContains(flagsMap[c.Func], "scope-id") { + switch c.Func { + case "list": + if c.FlagScopeId == "" { + c.UI.Error("Scope ID must be passed in via -scope-id") + return 1 + } + default: + if c.FlagScopeId != "" { + opts = append(opts, targets.WithScopeId(c.FlagScopeId)) + } + } } client, err := c.Client() @@ -212,8 +272,6 @@ func (c *Command) Run(args []string) int { return 2 } - var opts []targets.Option - switch c.FlagName { case "": case "null": @@ -222,6 +280,12 @@ func (c *Command) Run(args []string) int { opts = append(opts, targets.WithName(c.FlagName)) } + switch c.FlagScopeName { + case "": + default: + opts = append(opts, targets.WithScopeName(c.FlagScopeName)) + } + switch c.FlagDescription { case "": case "null": diff --git a/internal/cmd/common/flags.go b/internal/cmd/common/flags.go index b5113cfd5c..ea52ea3fe0 100644 --- a/internal/cmd/common/flags.go +++ b/internal/cmd/common/flags.go @@ -17,25 +17,33 @@ func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType string, EnvVar: "BOUNDARY_SCOPE_ID", Default: "global", Completion: complete.PredictAnything, - Usage: `Scope in which to make the request`, + Usage: `Scope in which to make the request.`, + }) + case "scope-name": + f.StringVar(&base.StringVar{ + Name: "scope-name", + Target: &c.FlagScopeName, + EnvVar: "BOUNDARY_SCOPE_NAME", + Completion: complete.PredictAnything, + Usage: `Scope in which to make the request, identified by name.`, }) case "id": f.StringVar(&base.StringVar{ Name: "id", Target: &c.FlagId, - Usage: fmt.Sprintf("ID of the %s on which to operate", resourceType), + Usage: fmt.Sprintf("ID of the %s on which to operate.", resourceType), }) case "name": f.StringVar(&base.StringVar{ Name: "name", Target: &c.FlagName, - Usage: fmt.Sprintf("Name to set on the %s", resourceType), + Usage: fmt.Sprintf("Name to set on the %s.", resourceType), }) case "description": f.StringVar(&base.StringVar{ Name: "description", Target: &c.FlagDescription, - Usage: fmt.Sprintf("Description to set on the %s", resourceType), + Usage: fmt.Sprintf("Description to set on the %s.", resourceType), }) case "version": f.IntVar(&base.IntVar{ @@ -48,14 +56,14 @@ func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType string, Name: "auth-method-id", EnvVar: "BOUNDARY_AUTH_METHOD_ID", Target: &c.FlagAuthMethodId, - Usage: "The auth-method resource to use for the operation", + Usage: "The auth-method resource to use for the operation.", }) case "host-catalog-id": f.StringVar(&base.StringVar{ Name: "host-catalog-id", EnvVar: "BOUNDARY_HOST_CATALOG_ID", Target: &c.FlagHostCatalogId, - Usage: "The host-catalog resource to use for the operation", + Usage: "The host-catalog resource to use for the operation.", }) } } diff --git a/internal/db/testing.go b/internal/db/testing.go index 9b5729c2f6..eb1958daa7 100644 --- a/internal/db/testing.go +++ b/internal/db/testing.go @@ -19,14 +19,26 @@ import ( ) // setup the tests (initialize the database one-time and intialized testDatabaseURL). Do not close the returned db. -func TestSetup(t *testing.T, dialect string) (*gorm.DB, string) { - cleanup, url, _, err := StartDbInDocker(dialect) - if err != nil { - t.Fatal(err) +func TestSetup(t *testing.T, dialect string, opt ...TestOption) (*gorm.DB, string) { + var cleanup func() error + var url string + var err error + + opts := getTestOpts(opt...) + + switch opts.withTestDatabaseUrl { + case "": + cleanup, url, _, err = StartDbInDocker(dialect) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + assert.NoError(t, cleanup(), "Got error cleaning up db in docker.") + }) + default: + cleanup = func() error { return nil } + url = opts.withTestDatabaseUrl } - t.Cleanup(func() { - assert.NoError(t, cleanup(), "Got error cleaning up db in docker.") - }) _, err = InitStore(dialect, cleanup, url) if err != nil { t.Fatal(err) @@ -144,6 +156,7 @@ type TestOption func(*testOptions) type testOptions struct { withCreateNotBefore *int withOperation oplog.OpType + withTestDatabaseUrl string } func getDefaultTestOptions() testOptions { @@ -168,3 +181,10 @@ func WithOperation(op oplog.OpType) TestOption { o.withOperation = op } } + +// WithTestDatabaseUrl provides a way to specify an existing database for tests +func WithTestDatabaseUrl(url string) TestOption { + return func(o *testOptions) { + o.withTestDatabaseUrl = url + } +} diff --git a/internal/gen/controller.swagger.json b/internal/gen/controller.swagger.json index dd0aaac42a..349ed54be6 100644 --- a/internal/gen/controller.swagger.json +++ b/internal/gen/controller.swagger.json @@ -1978,6 +1978,7 @@ "parameters": [ { "name": "id", + "description": "The ID of the target. Required unless some combination of scope_id/scope_name and name are set.", "in": "path", "required": true, "type": "string" @@ -3503,7 +3504,20 @@ "type": "object", "properties": { "id": { - "type": "string" + "type": "string", + "description": "The ID of the target. Required unless some combination of scope_id/scope_name and name are set." + }, + "name": { + "type": "string", + "description": "The name of the target. When using this, scope_id or scope_name must be set." + }, + "scope_id": { + "type": "string", + "description": "The scope ID containing the target, if specifying the target by name." + }, + "scope_name": { + "type": "string", + "description": "The scope name containing the target, if specifying the target by name." }, "host_id": { "type": "string", diff --git a/internal/gen/controller/api/services/target_service.pb.go b/internal/gen/controller/api/services/target_service.pb.go index 6bd0e23149..cab98bf3df 100644 --- a/internal/gen/controller/api/services/target_service.pb.go +++ b/internal/gen/controller/api/services/target_service.pb.go @@ -855,7 +855,14 @@ type AuthorizeSessionRequest struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + // The ID of the target. Required unless some combination of scope_id/scope_name and name are set. Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + // The name of the target. When using this, scope_id or scope_name must be set. + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + // The scope ID containing the target, if specifying the target by name. + ScopeId string `protobuf:"bytes,4,opt,name=scope_id,json=scopeId,proto3" json:"scope_id,omitempty"` + // The scope name containing the target, if specifying the target by name. + ScopeName string `protobuf:"bytes,5,opt,name=scope_name,json=scopeName,proto3" json:"scope_name,omitempty"` // An optional parameter allowing specification of the particular Host within the Target's configured Host Sets to connect to during this Session. HostId string `protobuf:"bytes,2,opt,name=host_id,proto3" json:"host_id,omitempty"` } @@ -899,6 +906,27 @@ func (x *AuthorizeSessionRequest) GetId() string { return "" } +func (x *AuthorizeSessionRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *AuthorizeSessionRequest) GetScopeId() string { + if x != nil { + return x.ScopeId + } + return "" +} + +func (x *AuthorizeSessionRequest) GetScopeName() string { + if x != nil { + return x.ScopeName + } + return "" +} + func (x *AuthorizeSessionRequest) GetHostId() string { if x != nil { return x.HostId @@ -1057,132 +1085,137 @@ var file_controller_api_services_v1_target_service_proto_rawDesc = []byte{ 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, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x22, 0x43, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, - 0x18, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 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, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x32, 0xc4, 0x0d, 0x0a, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, - 0x67, 0x6c, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x9a, 0x01, 0x0a, 0x0b, - 0x4c, 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x92, 0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x12, 0xaf, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, + 0x69, 0x74, 0x65, 0x6d, 0x22, 0x91, 0x01, 0x0a, 0x17, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x49, 0x64, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x22, 0x69, 0x0a, 0x18, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 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, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x32, 0xc4, 0x0d, 0x0a, 0x0d, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xa2, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x54, 0x61, 0x72, + 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x38, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x92, 0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x4c, + 0x69, 0x73, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2a, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x92, 0x41, 0x14, 0x12, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x54, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, 0x2e, 0x12, 0xaf, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 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, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, + 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x19, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x73, + 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1a, 0x12, + 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, + 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3c, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x19, 0x22, 0x0b, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x1a, - 0x12, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, - 0x6c, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, + 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 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, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 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, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x2f, 0x2e, 0x63, 0x6f, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3a, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x32, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, + 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xa1, 0x01, 0x0a, 0x0c, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 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, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 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, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 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, - 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xcc, - 0x01, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 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, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, + 0x61, 0x72, 0x67, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x2a, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x13, 0x12, 0x11, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xcc, 0x01, + 0x0a, 0x10, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 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, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 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, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, + 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, + 0x65, 0x2d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, + 0x73, 0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x12, 0xda, 0x01, 0x0a, + 0x11, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, + 0x74, 0x73, 0x12, 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, + 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 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, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, - 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x7a, 0x65, 0x2d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, - 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x73, 0x20, 0x61, 0x20, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x12, 0xda, 0x01, - 0x0a, 0x11, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, - 0x65, 0x74, 0x73, 0x12, 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, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x58, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x68, - 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x92, 0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, - 0x69, 0x6e, 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x6f, - 0x20, 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xd7, 0x01, 0x0a, 0x11, 0x53, - 0x65, 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, - 0x12, 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, 0x53, 0x65, - 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, - 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, 0x74, - 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, - 0x23, 0x12, 0x21, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, - 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, - 0x67, 0x65, 0x74, 0x2e, 0x12, 0xe4, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, - 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 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, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, - 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x59, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, - 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 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, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x58, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x64, 0x64, 0x2d, 0x68, 0x6f, + 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x92, 0x41, 0x26, 0x12, 0x24, 0x41, 0x64, 0x64, 0x73, 0x20, 0x65, 0x78, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, + 0x61, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 0x12, 0xd7, 0x01, 0x0a, 0x11, 0x53, 0x65, + 0x74, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, + 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, 0x53, 0x65, 0x74, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, + 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x29, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, + 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x23, + 0x12, 0x21, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x48, 0x6f, 0x73, 0x74, 0x20, + 0x53, 0x65, 0x74, 0x73, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x2e, 0x12, 0xe4, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x54, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x12, 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, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 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, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x48, + 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x59, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x74, 0x61, 0x72, + 0x67, 0x65, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x2d, 0x68, 0x6f, 0x73, 0x74, 0x2d, 0x73, 0x65, 0x74, 0x73, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x92, 0x41, 0x24, 0x12, 0x22, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x73, 0x20, + 0x48, 0x6f, 0x73, 0x74, 0x20, 0x53, 0x65, 0x74, 0x73, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x2e, 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 ( diff --git a/internal/proto/local/controller/api/services/v1/target_service.proto b/internal/proto/local/controller/api/services/v1/target_service.proto index 25fc37011e..bb04615a04 100644 --- a/internal/proto/local/controller/api/services/v1/target_service.proto +++ b/internal/proto/local/controller/api/services/v1/target_service.proto @@ -229,8 +229,18 @@ message RemoveTargetHostSetsResponse { } message AuthorizeSessionRequest { + // The ID of the target. Required unless some combination of scope_id/scope_name and name are set. string id = 1; + // The name of the target. When using this, scope_id or scope_name must be set. + string name = 3; + + // The scope ID containing the target, if specifying the target by name. + string scope_id = 4; + + // The scope name containing the target, if specifying the target by name. + string scope_name = 5; + // An optional parameter allowing specification of the particular Host within the Target's configured Host Sets to connect to during this Session. string host_id = 2 [json_name="host_id"]; } diff --git a/internal/servers/controller/handlers/targets/target_service.go b/internal/servers/controller/handlers/targets/target_service.go index b2d95af44a..9fc5a0354f 100644 --- a/internal/servers/controller/handlers/targets/target_service.go +++ b/internal/servers/controller/handlers/targets/target_service.go @@ -6,6 +6,7 @@ import ( "fmt" "math/rand" "net/url" + "strings" "github.com/golang/protobuf/ptypes/wrappers" "github.com/hashicorp/boundary/internal/auth" @@ -230,10 +231,26 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession if err := validateAuthorizeSessionRequest(req); err != nil { return nil, err } - authResults := s.authResult(ctx, req.GetId(), action.AuthorizeSession) + authResults := s.authResult(ctx, req.GetId(), action.AuthorizeSession, + target.WithName(req.GetName()), + target.WithScopeId(req.GetScopeId()), + target.WithScopeName(req.GetScopeName()), + ) if authResults.Error != nil { return nil, authResults.Error } + + if authResults.RoundTripValue == nil { + return nil, errors.New("authorize session: expected to get a target back from auth results") + } + t, ok := authResults.RoundTripValue.(target.Target) + if !ok { + return nil, errors.New("authorize session: round tripped auth results value is not a target") + } + if t == nil { + return nil, errors.New("authorize session: round tripped target is nil") + } + // This could happen if, say, u_recovery was used or u_anon was granted. But // don't allow it. It's one thing if grants give access to resources within // Boundary, even if those could eventually be used to provide an unintended @@ -257,15 +274,15 @@ func (s Service) AuthorizeSession(ctx context.Context, req *pbs.AuthorizeSession if err != nil { return nil, err } - t, hostSets, err := repo.LookupTarget(ctx, req.GetId()) + t, hostSets, err := repo.LookupTarget(ctx, t.GetPublicId()) if err != nil { if errors.Is(err, db.ErrRecordNotFound) { - return nil, handlers.NotFoundErrorf("Target %q not found.", req.GetId()) + return nil, handlers.NotFoundErrorf("Target %q not found.", t.GetPublicId()) } return nil, err } if t == nil { - return nil, handlers.NotFoundErrorf("Target %q not found.", req.GetId()) + return nil, handlers.NotFoundErrorf("Target %q not found.", t.GetPublicId()) } // Instantiate some repos @@ -611,10 +628,11 @@ func (s Service) removeInRepo(ctx context.Context, targetId string, hostSetIds [ return toProto(out, m) } -func (s Service) authResult(ctx context.Context, id string, a action.Type) auth.VerifyResults { +func (s Service) authResult(ctx context.Context, id string, a action.Type, lookupOpt ...target.Option) auth.VerifyResults { res := auth.VerifyResults{} var parentId string + var t target.Target opts := []auth.Option{auth.WithType(resource.Target), auth.WithAction(a)} switch a { case action.List, action.Create: @@ -639,20 +657,28 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) auth. res.Error = err return res } - t, _, err := repo.LookupTarget(ctx, id) + t, _, err = repo.LookupTarget(ctx, id, lookupOpt...) if err != nil { - res.Error = err + // TODO: Fix this with new/better error handling + if strings.Contains(err.Error(), "more than one row returned by a subquery") { + res.Error = handlers.ApiErrorWithCodeAndMessage(codes.FailedPrecondition, "Scope name is ambiguous (matches more than one scope), use scope ID with target name instead, or use target ID.") + } else { + res.Error = err + } return res } if t == nil { res.Error = handlers.NotFoundError() return res } + id = t.GetPublicId() parentId = t.GetScopeId() opts = append(opts, auth.WithId(id)) } opts = append(opts, auth.WithScopeId(parentId)) - return auth.Verify(ctx, opts...) + ret := auth.Verify(ctx, opts...) + ret.RoundTripValue = t + return ret } func toProto(in target.Target, m []*target.TargetSet) (*pb.Target, error) { @@ -860,8 +886,31 @@ func validateRemoveRequest(req *pbs.RemoveTargetHostSetsRequest) error { func validateAuthorizeSessionRequest(req *pbs.AuthorizeSessionRequest) error { badFields := map[string]string{} - if !handlers.ValidId(target.TcpTargetPrefix, req.GetId()) { - badFields["id"] = "Incorrectly formatted identifier." + nameEmpty := req.GetName() == "" + scopeIdEmpty := req.GetScopeId() == "" + scopeNameEmpty := req.GetScopeName() == "" + if nameEmpty { + if !handlers.ValidId(target.TcpTargetPrefix, req.GetId()) { + badFields["id"] = "Incorrectly formatted identifier." + } + if !scopeIdEmpty { + badFields["scope_id"] = "Scope ID provided when target name was empty." + } + if !scopeNameEmpty { + badFields["scope_id"] = "Scope name provided when target name was empty." + } + } else { + if req.GetName() != req.GetId() { + badFields["name"] = "Target name provided but does not match the given ID value from the URL." + } + switch { + case scopeIdEmpty && scopeNameEmpty: + badFields["scope_id"] = "Scope ID or scope name must be provided when target name is used." + badFields["scope_name"] = "Scope ID or scope name must be provided when target name is used." + case !scopeIdEmpty && !scopeNameEmpty: + badFields["scope_id"] = "Scope ID and scope name cannot both be provided when target name is used." + badFields["scope_name"] = "Scope ID and scope name cannot both be provided when target name is used." + } } if req.GetHostId() != "" { switch host.SubtypeFromId(req.GetHostId()) { diff --git a/internal/target/options.go b/internal/target/options.go index 12884fc80a..f2c3088418 100644 --- a/internal/target/options.go +++ b/internal/target/options.go @@ -21,6 +21,7 @@ type options struct { withDefaultPort uint32 withLimit int withScopeId string + withScopeName string withUserId string withTargetType *TargetType withHostSets []string @@ -36,6 +37,7 @@ func getDefaultOptions() options { withLimit: 0, withDefaultPort: 0, withScopeId: "", + withScopeName: "", withUserId: "", withTargetType: nil, withHostSets: nil, @@ -82,6 +84,13 @@ func WithScopeId(scopeId string) Option { } } +// WithScopeId provides an option to search by a scope name +func WithScopeName(scopeName string) Option { + return func(o *options) { + o.withScopeName = scopeName + } +} + // WithUserId provides an option to search by a user public id func WithUserId(userId string) Option { return func(o *options) { diff --git a/internal/target/options_test.go b/internal/target/options_test.go index 78e5bf9563..dd81b677af 100644 --- a/internal/target/options_test.go +++ b/internal/target/options_test.go @@ -68,6 +68,13 @@ func Test_GetOpts(t *testing.T) { testOpts.withScopeId = "testId" assert.Equal(opts, testOpts) }) + t.Run("WithScopeName", func(t *testing.T) { + assert := assert.New(t) + opts := getOpts(WithScopeName("testName")) + testOpts := getDefaultOptions() + testOpts.withScopeName = "testName" + assert.Equal(opts, testOpts) + }) t.Run("WithPublicId", func(t *testing.T) { assert := assert.New(t) opts := getOpts(WithPublicId("testId")) diff --git a/internal/target/repository.go b/internal/target/repository.go index 805d620fdb..b21c58548d 100644 --- a/internal/target/repository.go +++ b/internal/target/repository.go @@ -58,20 +58,62 @@ func NewRepository(r db.Reader, w db.Writer, kms *kms.Kms, opt ...Option) (*Repo // LookupTarget will look up a target in the repository and return the target // with its host set ids. If the target is not found, it will return nil, nil, nil. // No options are currently supported. -func (r *Repository) LookupTarget(ctx context.Context, publicId string, opt ...Option) (Target, []*TargetSet, error) { - if publicId == "" { +func (r *Repository) LookupTarget(ctx context.Context, publicIdOrName string, opt ...Option) (Target, []*TargetSet, error) { + opts := getOpts(opt...) + + if publicIdOrName == "" { return nil, nil, fmt.Errorf("lookup target: missing private id: %w", db.ErrInvalidParameter) } + + var where []string + var whereArgs []interface{} + nameEmpty := opts.withName == "" + scopeIdEmpty := opts.withScopeId == "" + scopeNameEmpty := opts.withScopeName == "" + if !nameEmpty { + if opts.withName != publicIdOrName { + return nil, nil, fmt.Errorf("lookup target: name passed in but does not match publicId: %w", db.ErrInvalidParameter) + } + where, whereArgs = append(where, "lower(name) = lower(?)"), append(whereArgs, opts.withName) + switch { + case scopeIdEmpty && scopeNameEmpty: + return nil, nil, fmt.Errorf("lookup target: using name but both scope ID and scope name are empty: %w", db.ErrInvalidParameter) + case !scopeIdEmpty && !scopeNameEmpty: + return nil, nil, fmt.Errorf("lookup target: using name but both scope ID and scope name are set: %w", db.ErrInvalidParameter) + case !scopeIdEmpty: + where, whereArgs = append(where, "scope_id = ?"), append(whereArgs, opts.withScopeId) + case !scopeNameEmpty: + where, whereArgs = append(where, "scope_id = (select public_id from iam_scope where lower(name) = lower(?))"), append(whereArgs, opts.withScopeName) + default: + return nil, nil, fmt.Errorf("lookup target: unknown combination of parameters: %w", db.ErrInvalidParameter) + } + } else { + switch { + case !scopeIdEmpty: + return nil, nil, fmt.Errorf("lookup target: passed in scope ID when using target ID for lookup: %w", db.ErrInvalidParameter) + case !scopeNameEmpty: + return nil, nil, fmt.Errorf("lookup target: passed in scope name when using target ID for lookup: %w", db.ErrInvalidParameter) + } + } + target := allocTargetView() - target.PublicId = publicId + target.PublicId = publicIdOrName var hostSets []*TargetSet _, err := r.writer.DoTx( ctx, db.StdRetryCnt, db.ExpBackoff{}, func(read db.Reader, w db.Writer) error { - if err := read.LookupById(ctx, &target); err != nil { - return fmt.Errorf("lookup target: failed %w for %s", err, publicId) + var lookupErr error + switch where { + case nil: + lookupErr = read.LookupById(ctx, &target) + default: + target.PublicId = "" + lookupErr = read.LookupWhere(ctx, &target, strings.Join(where, " and "), whereArgs...) + } + if lookupErr != nil { + return fmt.Errorf("failed %w for %s", lookupErr, publicIdOrName) } var err error if hostSets, err = fetchSets(ctx, read, target.PublicId); err != nil { diff --git a/internal/target/repository_test.go b/internal/target/repository_test.go index 248a7de724..44176c37a7 100644 --- a/internal/target/repository_test.go +++ b/internal/target/repository_test.go @@ -100,6 +100,122 @@ func TestNewRepository(t *testing.T) { } } +func TestRepository_LookupTarget(t *testing.T) { + t.Parallel() + conn, _ := db.TestSetup(t, "postgres") + wrapper := db.TestWrapper(t) + testKms := kms.TestKms(t, conn, wrapper) + iamRepo := iam.TestRepo(t, conn, wrapper) + _, proj := iam.TestScopes(t, iamRepo) + proj.Name = "project-name" + _, _, err := iamRepo.UpdateScope(context.Background(), proj, 1, []string{"name"}) + require.NoError(t, err) + rw := db.New(conn) + repo, err := NewRepository(rw, rw, testKms) + require.NoError(t, err) + tgt := TestTcpTarget(t, conn, proj.PublicId, "target-name") + + tests := []struct { + testName string + id string + name string + scopeId string + scopeName string + wantErr bool + }{ + { + testName: "id", + id: tgt.PublicId, + wantErr: false, + }, + { + testName: "name only", + name: tgt.Name, + wantErr: true, + }, + { + testName: "scope id only", + scopeId: proj.PublicId, + wantErr: true, + }, + { + testName: "scope name only", + scopeName: proj.Name, + wantErr: true, + }, + { + testName: "scope name and id", + scopeId: proj.PublicId, + scopeName: proj.Name, + wantErr: true, + }, + { + testName: "everything", + name: tgt.Name, + scopeId: proj.PublicId, + scopeName: proj.Name, + wantErr: true, + }, + { + testName: "name and scope name", + name: tgt.Name, + scopeName: proj.Name, + wantErr: false, + }, + { + testName: "name and scope id", + name: tgt.Name, + scopeId: proj.PublicId, + wantErr: false, + }, + { + testName: "id and name", + id: tgt.PublicId, + name: tgt.Name, + scopeId: proj.PublicId, + wantErr: true, + }, + { + testName: "id and scope name", + id: tgt.PublicId, + scopeName: proj.Name, + wantErr: true, + }, + { + testName: "id and scope id", + id: tgt.PublicId, + scopeId: proj.PublicId, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.testName, func(t *testing.T) { + assert, require := assert.New(t), require.New(t) + id := tt.id + if tt.name != "" && tt.id == "" { + id = tt.name + } + var opts []Option + if tt.name != "" { + opts = append(opts, WithName(tt.name)) + } + if tt.scopeId != "" { + opts = append(opts, WithScopeId(tt.scopeId)) + } + if tt.scopeName != "" { + opts = append(opts, WithScopeName(tt.scopeName)) + } + got, _, err := repo.LookupTarget(context.Background(), id, opts...) + if tt.wantErr { + require.Error(err) + return + } + require.NoError(err) + assert.Equal(tgt.PublicId, got.GetPublicId()) + }) + } +} + func TestRepository_ListTargets(t *testing.T) { t.Parallel() conn, _ := db.TestSetup(t, "postgres")