From 53481146fd56ba1524cb0a5a805f39e5acb49ef0 Mon Sep 17 00:00:00 2001 From: Johan Brandhorst-Satzkorn Date: Fri, 8 Apr 2022 11:40:59 -0400 Subject: [PATCH] feat(authmethods): add well typed attribute options (#1972) Add well typed attribute options to the authmethods proto definitions, while hiding them from being rendered in the openapiv2 spec. --- internal/auth/oidc/ids.go | 3 +- internal/auth/password/public_ids.go | 3 +- internal/auth/subtype.go | 3 + .../api/services/auth_method_service.pb.go | 536 ++++++++------- .../services/auth_method_service_taggable.go | 130 ---- .../authmethods/v1/auth_method.proto | 23 +- .../api/services/v1/auth_method_service.proto | 11 +- .../authmethods/authmethod_service.go | 286 ++++---- .../authmethods/authmethod_service_test.go | 457 ++++++------ .../controller/handlers/authmethods/oidc.go | 6 +- .../handlers/authmethods/oidc_test.go | 650 +++++++++--------- .../handlers/authmethods/password.go | 6 +- .../handlers/authmethods/password_test.go | 97 +-- .../api/authmethods/authenticate_test.go | 8 +- .../tests/api/authmethods/authmethod_test.go | 152 +++- .../api/authmethods/classification_test.go | 97 +-- .../service_classification_test.go} | 42 +- internal/types/subtypes/interceptor.go | 5 +- .../resources/authmethods/auth_method.pb.go | 496 +++++++------ .../authmethods/auth_method_taggable.go | 82 --- 20 files changed, 1544 insertions(+), 1549 deletions(-) delete mode 100644 internal/gen/controller/api/services/auth_method_service_taggable.go rename sdk/pbs/controller/api/resources/authmethods/auth_method_taggable_test.go => internal/tests/api/authmethods/classification_test.go (50%) rename internal/{gen/controller/api/services/auth_method_service_taggable_test.go => tests/api/authmethods/service_classification_test.go} (73%) diff --git a/internal/auth/oidc/ids.go b/internal/auth/oidc/ids.go index 2e0cf18e1..0aeee3e8a 100644 --- a/internal/auth/oidc/ids.go +++ b/internal/auth/oidc/ids.go @@ -3,6 +3,7 @@ package oidc import ( "context" + "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/intglobals" @@ -10,7 +11,7 @@ import ( ) func init() { - if err := subtypes.Register("auth", Subtype, AuthMethodPrefix, AccountPrefix, intglobals.OidcManagedGroupPrefix); err != nil { + if err := subtypes.Register(auth.Domain, Subtype, AuthMethodPrefix, AccountPrefix, intglobals.OidcManagedGroupPrefix); err != nil { panic(err) } } diff --git a/internal/auth/password/public_ids.go b/internal/auth/password/public_ids.go index 70e176df0..24f8f9e41 100644 --- a/internal/auth/password/public_ids.go +++ b/internal/auth/password/public_ids.go @@ -1,6 +1,7 @@ package password import ( + "github.com/hashicorp/boundary/internal/auth" "github.com/hashicorp/boundary/internal/db" "github.com/hashicorp/boundary/internal/errors" "github.com/hashicorp/boundary/internal/intglobals" @@ -8,7 +9,7 @@ import ( ) func init() { - if err := subtypes.Register("auth", Subtype, AuthMethodPrefix, intglobals.OldPasswordAccountPrefix, intglobals.NewPasswordAccountPrefix); err != nil { + if err := subtypes.Register(auth.Domain, Subtype, AuthMethodPrefix, intglobals.OldPasswordAccountPrefix, intglobals.NewPasswordAccountPrefix); err != nil { panic(err) } } diff --git a/internal/auth/subtype.go b/internal/auth/subtype.go index 4ecd1e246..10fcd1c44 100644 --- a/internal/auth/subtype.go +++ b/internal/auth/subtype.go @@ -4,6 +4,9 @@ import ( "github.com/hashicorp/boundary/internal/boundary" ) +// Domain defines the domain for the auth package. +const Domain = "auth" + // AuthMethod contains the common methods across all the different types of auth methods. type AuthMethod interface { boundary.Resource diff --git a/internal/gen/controller/api/services/auth_method_service.pb.go b/internal/gen/controller/api/services/auth_method_service.pb.go index e2053593f..06d1dc86b 100644 --- a/internal/gen/controller/api/services/auth_method_service.pb.go +++ b/internal/gen/controller/api/services/auth_method_service.pb.go @@ -9,7 +9,9 @@ package services import ( _ "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options" authmethods "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authmethods" + _ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" _ "google.golang.org/genproto/googleapis/api/annotations" + _ "google.golang.org/genproto/googleapis/api/visibility" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" fieldmaskpb "google.golang.org/protobuf/types/known/fieldmaskpb" @@ -595,8 +597,10 @@ type ChangeStateRequest struct { // Version is used to ensure this resource has not changed. // The mutation will fail if the version does not match the latest known good version. Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - // The attributes specific to this auth method's state. - Attributes *structpb.Struct `protobuf:"bytes,4,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Types that are assignable to Attrs: + // *ChangeStateRequest_Attributes + // *ChangeStateRequest_OidcChangeStateAttributes + Attrs isChangeStateRequest_Attrs `protobuf_oneof:"attrs"` } func (x *ChangeStateRequest) Reset() { @@ -645,13 +649,44 @@ func (x *ChangeStateRequest) GetVersion() uint32 { return 0 } +func (m *ChangeStateRequest) GetAttrs() isChangeStateRequest_Attrs { + if m != nil { + return m.Attrs + } + return nil +} + func (x *ChangeStateRequest) GetAttributes() *structpb.Struct { - if x != nil { + if x, ok := x.GetAttrs().(*ChangeStateRequest_Attributes); ok { return x.Attributes } return nil } +func (x *ChangeStateRequest) GetOidcChangeStateAttributes() *OidcChangeStateAttributes { + if x, ok := x.GetAttrs().(*ChangeStateRequest_OidcChangeStateAttributes); ok { + return x.OidcChangeStateAttributes + } + return nil +} + +type isChangeStateRequest_Attrs interface { + isChangeStateRequest_Attrs() +} + +type ChangeStateRequest_Attributes struct { + // The attributes specific to this auth method's state. + Attributes *structpb.Struct `protobuf:"bytes,4,opt,name=attributes,proto3,oneof"` +} + +type ChangeStateRequest_OidcChangeStateAttributes struct { + OidcChangeStateAttributes *OidcChangeStateAttributes `protobuf:"bytes,5,opt,name=oidc_change_state_attributes,json=oidcChangeStateAttributes,proto3,oneof"` +} + +func (*ChangeStateRequest_Attributes) isChangeStateRequest_Attrs() {} + +func (*ChangeStateRequest_OidcChangeStateAttributes) isChangeStateRequest_Attrs() {} + type ChangeStateResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1035,230 +1070,246 @@ var file_controller_api_services_v1_auth_method_service_proto_rawDesc = []byte{ 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2f, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x1a, 0x39, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x14, 0x47, - 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x02, 0x69, 0x64, 0x22, 0x60, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, - 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x6a, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x72, - 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, - 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, - 0x74, 0x65, 0x72, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x22, 0x64, 0x0a, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x05, - 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, - 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x62, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x76, 0x69, 0x73, + 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x66, + 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x39, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x26, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x60, 0x0a, 0x15, + 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, + 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, + 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x6a, + 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, + 0x65, 0x5f, 0x69, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, 0x76, + 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x72, 0x65, 0x63, 0x75, 0x72, 0x73, 0x69, + 0x76, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x1e, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x22, 0x64, 0x0a, 0x17, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 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, + 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, + 0x22, 0x62, 0x0a, 0x17, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x47, 0x0a, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x22, 0x75, 0x0a, 0x18, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, + 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x69, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x75, 0x0a, 0x18, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x22, 0xb0, 0x01, 0x0a, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0xb0, 0x01, 0x0a, 0x17, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, + 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, + 0x12, 0x3c, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, + 0x6b, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x63, + 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, + 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x22, 0x29, 0x0a, 0x17, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x47, - 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x3c, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, - 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x63, 0x0a, 0x18, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x29, 0x0a, 0x17, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1a, 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x85, 0x01, 0x0a, 0x19, 0x4f, 0x69, 0x64, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, - 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x52, 0x0a, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, - 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x77, 0x0a, 0x12, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, - 0x65, 0x73, 0x22, 0x5e, 0x0a, 0x13, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, - 0x65, 0x6d, 0x22, 0x55, 0x0a, 0x17, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, - 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x96, 0x01, 0x0a, 0x13, 0x4f, 0x69, - 0x64, 0x63, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x12, 0x45, 0x0a, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x74, 0x72, 0x69, 0x70, 0x5f, 0x70, - 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x74, 0x72, 0x69, 0x70, - 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x38, 0x0a, 0x18, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x74, 0x72, 0x69, 0x70, 0x5f, 0x70, 0x61, 0x79, - 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x63, 0x61, 0x63, 0x68, - 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x74, 0x72, 0x69, 0x70, 0x50, 0x61, 0x79, 0x6c, 0x6f, - 0x61, 0x64, 0x22, 0x30, 0x0a, 0x13, 0x4f, 0x69, 0x64, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x41, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x49, 0x64, 0x22, 0xdb, 0x01, 0x0a, 0x13, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, - 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x5f, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0a, 0x74, 0x6f, - 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0a, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, - 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4a, - 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, - 0x6c, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, - 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, - 0x61, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, - 0x6e, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x04, - 0x69, 0x74, 0x65, 0x6d, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, - 0x32, 0x95, 0x0b, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb8, 0x01, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 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, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x92, - 0x41, 0x1c, 0x12, 0x1a, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, - 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, - 0x6d, 0x12, 0xb0, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x73, 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, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x73, 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, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, - 0x92, 0x41, 0x19, 0x12, 0x17, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x41, - 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x12, 0xc5, 0x01, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, - 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x1a, + 0x0a, 0x18, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x85, 0x01, 0x0a, 0x19, 0x4f, + 0x69, 0x64, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x52, + 0x0a, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x24, 0x64, 0x69, + 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, + 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0xa4, 0x02, 0x0a, 0x12, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x65, 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, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x46, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x42, 0x0b, 0x9a, 0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, + 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x92, 0x01, 0x0a, 0x1c, + 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x5f, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 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, + 0x4f, 0x69, 0x64, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, 0x18, 0x9a, 0xe3, 0x29, 0x04, 0x6f, + 0x69, 0x64, 0x63, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x49, 0x4e, 0x54, 0x45, 0x52, + 0x4e, 0x41, 0x4c, 0x48, 0x00, 0x52, 0x19, 0x6f, 0x69, 0x64, 0x63, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x42, 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x5e, 0x0a, 0x13, 0x43, 0x68, 0x61, + 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x47, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x92, 0x41, 0x1f, 0x12, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, - 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x10, - 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, - 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xc4, 0x01, 0x0a, - 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 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, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x45, 0x92, 0x41, - 0x19, 0x12, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x75, - 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, - 0x32, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, - 0x74, 0x65, 0x6d, 0x12, 0xb6, 0x01, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x22, 0x55, 0x0a, 0x17, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x22, 0x96, 0x01, 0x0a, 0x13, 0x4f, 0x69, 0x64, 0x63, 0x53, 0x74, 0x61, 0x72, 0x74, 0x41, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x11, 0x72, 0x6f, 0x75, 0x6e, + 0x64, 0x74, 0x72, 0x69, 0x70, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x11, 0x72, 0x6f, + 0x75, 0x6e, 0x64, 0x74, 0x72, 0x69, 0x70, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, + 0x38, 0x0a, 0x18, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x74, + 0x72, 0x69, 0x70, 0x5f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x16, 0x63, 0x61, 0x63, 0x68, 0x65, 0x64, 0x52, 0x6f, 0x75, 0x6e, 0x64, 0x74, 0x72, + 0x69, 0x70, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x30, 0x0a, 0x13, 0x4f, 0x69, 0x64, + 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, + 0x12, 0x19, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x49, 0x64, 0x22, 0xdb, 0x01, 0x0a, 0x13, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, + 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x12, 0x22, 0x0a, 0x0a, 0x74, + 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, + 0x02, 0x18, 0x01, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, + 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x0b, 0x63, 0x72, + 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x9b, 0x01, 0x0a, 0x14, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x37, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x4a, + 0x04, 0x08, 0x02, 0x10, 0x03, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x52, 0x0a, 0x74, 0x6f, 0x6b, + 0x65, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x32, 0x95, 0x0b, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xb8, 0x01, + 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x47, 0x65, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x47, + 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x42, 0x92, 0x41, 0x1c, 0x12, 0x1a, 0x47, 0x65, 0x74, 0x73, 0x20, + 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, + 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x15, 0x2f, 0x76, 0x31, + 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xb0, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 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, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x75, + 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 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, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x34, 0x92, 0x41, 0x19, 0x12, 0x17, 0x4c, 0x69, 0x73, 0x74, + 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x41, 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x61, + 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x12, 0xc5, 0x01, 0x0a, 0x10, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 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, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x92, 0x41, 0x1f, + 0x12, 0x1d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, + 0x6c, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, + 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, + 0x74, 0x65, 0x6d, 0x12, 0xc4, 0x01, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, + 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x37, 0x92, 0x41, 0x17, 0x12, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x73, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x2a, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xcf, 0x01, 0x0a, - 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x92, - 0x41, 0x29, 0x12, 0x27, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x4f, 0x49, 0x44, 0x43, - 0x20, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, - 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xf7, - 0x01, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 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, 0x41, 0x75, 0x74, - 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 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, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x83, 0x01, 0x92, 0x41, 0x47, 0x12, 0x45, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, - 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, - 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, - 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, - 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 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, + 0x6e, 0x73, 0x65, 0x22, 0x45, 0x92, 0x41, 0x19, 0x12, 0x17, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x73, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x32, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, 0x74, + 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, + 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xb6, 0x01, 0x0a, 0x10, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 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, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x37, 0x92, 0x41, 0x17, 0x12, + 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x41, 0x75, 0x74, 0x68, + 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x2a, 0x15, 0x2f, 0x76, + 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, + 0x69, 0x64, 0x7d, 0x12, 0xcf, 0x01, 0x0a, 0x0b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, + 0x61, 0x74, 0x65, 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, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 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, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5f, 0x92, 0x41, 0x29, 0x12, 0x27, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x65, 0x20, 0x6f, 0x66, 0x20, + 0x61, 0x6e, 0x20, 0x4f, 0x49, 0x44, 0x43, 0x20, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x22, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x75, + 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x73, 0x74, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, + 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0xf7, 0x01, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 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, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, + 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, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x83, 0x01, 0x92, 0x41, 0x47, 0x12, + 0x45, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, + 0x75, 0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e, + 0x20, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x33, 0x22, 0x2e, 0x2f, 0x76, + 0x31, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, + 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, + 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x42, + 0x55, 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, 0xa2, 0xe3, + 0x29, 0x04, 0x61, 0x75, 0x74, 0x68, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1306,29 +1357,30 @@ var file_controller_api_services_v1_auth_method_service_proto_depIdxs = []int32{ 19, // 5: controller.api.services.v1.UpdateAuthMethodRequest.update_mask:type_name -> google.protobuf.FieldMask 18, // 6: controller.api.services.v1.UpdateAuthMethodResponse.item:type_name -> controller.api.resources.authmethods.v1.AuthMethod 20, // 7: controller.api.services.v1.ChangeStateRequest.attributes:type_name -> google.protobuf.Struct - 18, // 8: controller.api.services.v1.ChangeStateResponse.item:type_name -> controller.api.resources.authmethods.v1.AuthMethod - 20, // 9: controller.api.services.v1.OidcStartAttributes.roundtrip_payload:type_name -> google.protobuf.Struct - 20, // 10: controller.api.services.v1.AuthenticateRequest.attributes:type_name -> google.protobuf.Struct - 20, // 11: controller.api.services.v1.AuthenticateResponse.attributes:type_name -> google.protobuf.Struct - 0, // 12: controller.api.services.v1.AuthMethodService.GetAuthMethod:input_type -> controller.api.services.v1.GetAuthMethodRequest - 2, // 13: controller.api.services.v1.AuthMethodService.ListAuthMethods:input_type -> controller.api.services.v1.ListAuthMethodsRequest - 4, // 14: controller.api.services.v1.AuthMethodService.CreateAuthMethod:input_type -> controller.api.services.v1.CreateAuthMethodRequest - 6, // 15: controller.api.services.v1.AuthMethodService.UpdateAuthMethod:input_type -> controller.api.services.v1.UpdateAuthMethodRequest - 8, // 16: controller.api.services.v1.AuthMethodService.DeleteAuthMethod:input_type -> controller.api.services.v1.DeleteAuthMethodRequest - 11, // 17: controller.api.services.v1.AuthMethodService.ChangeState:input_type -> controller.api.services.v1.ChangeStateRequest - 16, // 18: controller.api.services.v1.AuthMethodService.Authenticate:input_type -> controller.api.services.v1.AuthenticateRequest - 1, // 19: controller.api.services.v1.AuthMethodService.GetAuthMethod:output_type -> controller.api.services.v1.GetAuthMethodResponse - 3, // 20: controller.api.services.v1.AuthMethodService.ListAuthMethods:output_type -> controller.api.services.v1.ListAuthMethodsResponse - 5, // 21: controller.api.services.v1.AuthMethodService.CreateAuthMethod:output_type -> controller.api.services.v1.CreateAuthMethodResponse - 7, // 22: controller.api.services.v1.AuthMethodService.UpdateAuthMethod:output_type -> controller.api.services.v1.UpdateAuthMethodResponse - 9, // 23: controller.api.services.v1.AuthMethodService.DeleteAuthMethod:output_type -> controller.api.services.v1.DeleteAuthMethodResponse - 12, // 24: controller.api.services.v1.AuthMethodService.ChangeState:output_type -> controller.api.services.v1.ChangeStateResponse - 17, // 25: controller.api.services.v1.AuthMethodService.Authenticate:output_type -> controller.api.services.v1.AuthenticateResponse - 19, // [19:26] is the sub-list for method output_type - 12, // [12:19] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 10, // 8: controller.api.services.v1.ChangeStateRequest.oidc_change_state_attributes:type_name -> controller.api.services.v1.OidcChangeStateAttributes + 18, // 9: controller.api.services.v1.ChangeStateResponse.item:type_name -> controller.api.resources.authmethods.v1.AuthMethod + 20, // 10: controller.api.services.v1.OidcStartAttributes.roundtrip_payload:type_name -> google.protobuf.Struct + 20, // 11: controller.api.services.v1.AuthenticateRequest.attributes:type_name -> google.protobuf.Struct + 20, // 12: controller.api.services.v1.AuthenticateResponse.attributes:type_name -> google.protobuf.Struct + 0, // 13: controller.api.services.v1.AuthMethodService.GetAuthMethod:input_type -> controller.api.services.v1.GetAuthMethodRequest + 2, // 14: controller.api.services.v1.AuthMethodService.ListAuthMethods:input_type -> controller.api.services.v1.ListAuthMethodsRequest + 4, // 15: controller.api.services.v1.AuthMethodService.CreateAuthMethod:input_type -> controller.api.services.v1.CreateAuthMethodRequest + 6, // 16: controller.api.services.v1.AuthMethodService.UpdateAuthMethod:input_type -> controller.api.services.v1.UpdateAuthMethodRequest + 8, // 17: controller.api.services.v1.AuthMethodService.DeleteAuthMethod:input_type -> controller.api.services.v1.DeleteAuthMethodRequest + 11, // 18: controller.api.services.v1.AuthMethodService.ChangeState:input_type -> controller.api.services.v1.ChangeStateRequest + 16, // 19: controller.api.services.v1.AuthMethodService.Authenticate:input_type -> controller.api.services.v1.AuthenticateRequest + 1, // 20: controller.api.services.v1.AuthMethodService.GetAuthMethod:output_type -> controller.api.services.v1.GetAuthMethodResponse + 3, // 21: controller.api.services.v1.AuthMethodService.ListAuthMethods:output_type -> controller.api.services.v1.ListAuthMethodsResponse + 5, // 22: controller.api.services.v1.AuthMethodService.CreateAuthMethod:output_type -> controller.api.services.v1.CreateAuthMethodResponse + 7, // 23: controller.api.services.v1.AuthMethodService.UpdateAuthMethod:output_type -> controller.api.services.v1.UpdateAuthMethodResponse + 9, // 24: controller.api.services.v1.AuthMethodService.DeleteAuthMethod:output_type -> controller.api.services.v1.DeleteAuthMethodResponse + 12, // 25: controller.api.services.v1.AuthMethodService.ChangeState:output_type -> controller.api.services.v1.ChangeStateResponse + 17, // 26: controller.api.services.v1.AuthMethodService.Authenticate:output_type -> controller.api.services.v1.AuthenticateResponse + 20, // [20:27] is the sub-list for method output_type + 13, // [13:20] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_controller_api_services_v1_auth_method_service_proto_init() } @@ -1554,6 +1606,10 @@ func file_controller_api_services_v1_auth_method_service_proto_init() { } } } + file_controller_api_services_v1_auth_method_service_proto_msgTypes[11].OneofWrappers = []interface{}{ + (*ChangeStateRequest_Attributes)(nil), + (*ChangeStateRequest_OidcChangeStateAttributes)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/internal/gen/controller/api/services/auth_method_service_taggable.go b/internal/gen/controller/api/services/auth_method_service_taggable.go deleted file mode 100644 index 140f579cb..000000000 --- a/internal/gen/controller/api/services/auth_method_service_taggable.go +++ /dev/null @@ -1,130 +0,0 @@ -package services - -import "github.com/hashicorp/eventlogger/filters/encrypt" - -// Tags implements the encrypt.Taggable interface which allows -// AuthenticateResponse Attributes to be classified for the encrypt filter. -func (req *AuthenticateResponse) Tags() ([]encrypt.PointerTag, error) { - if req.Attributes == nil { - return nil, nil - } - return []encrypt.PointerTag{ - // public fields - { - Pointer: "/Attributes/Fields/account_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/approximate_last_used_time", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/auth_method_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/authorized_actions", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/created_time", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/expiration_time", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/scope", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/type", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/updated_time", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/user_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/status", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/auth_url", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/token_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/final_redirect_url", - Classification: encrypt.PublicClassification, - }, - // secret fields - { - Pointer: "/Attributes/Fields/token", - Classification: encrypt.SecretClassification, - }, - }, nil -} - -// Tags implements the encrypt.Taggable interface which allows -// AuthenticateRequest Attributes to be classified for the encrypt filter. -func (req *AuthenticateRequest) Tags() ([]encrypt.PointerTag, error) { - if req.Attributes == nil { - return nil, nil - } - return []encrypt.PointerTag{ - // public fields - { - Pointer: "/Attributes/Fields/login_name", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/auth_url", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/token_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/state", - Classification: encrypt.PublicClassification, - }, - // secret fields - { - Pointer: "/Attributes/Fields/password", - Classification: encrypt.SecretClassification, - }, - { - Pointer: "/Attributes/Fields/code", - Classification: encrypt.SecretClassification, - }, - }, nil -} - -// Tags implements the encrypt.Taggable interface which allows -// ChangeStateRequest Attributes to be classified for the encrypt filter. -func (req *ChangeStateRequest) Tags() ([]encrypt.PointerTag, error) { - if req.Attributes == nil { - return nil, nil - } - return []encrypt.PointerTag{ - // public fields - { - Pointer: "/Attributes/Fields/state", - Classification: encrypt.PublicClassification, - }, - }, nil -} diff --git a/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto b/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto index ba4a16bfc..34cab4d76 100644 --- a/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto +++ b/internal/proto/controller/api/resources/authmethods/v1/auth_method.proto @@ -7,9 +7,12 @@ option go_package = "github.com/hashicorp/boundary/sdk/pbs/controller/api/resour import "google/protobuf/timestamp.proto"; import "google/protobuf/wrappers.proto"; import "google/protobuf/struct.proto"; +import "google/api/visibility.proto"; import "controller/api/resources/scopes/v1/scope.proto"; import "controller/custom_options/v1/options.proto"; +option (custom_options.v1.domain) = "auth"; + // AuthMethod contains all fields related to an Auth Method resource message AuthMethod { // Output only. The ID of the Auth Method. @@ -41,8 +44,20 @@ message AuthMethod { // The Auth Method type. string type = 90; // @gotags: `class:"public"` - // The attributes that are applicable for the specific Auth Method type. - google.protobuf.Struct attributes = 100 [(custom_options.v1.generate_sdk_option) = true]; + oneof attrs { + // The attributes that are applicable for the specific Auth Method type. + google.protobuf.Struct attributes = 100 [(custom_options.v1.generate_sdk_option) = true, (custom_options.v1.subtype) = "default"]; + PasswordAuthMethodAttributes password_auth_method_attributes = 101 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.subtype) = "password", + (google.api.field_visibility).restriction = "INTERNAL" + ]; + OidcAuthMethodAttributes oidc_auth_methods_attributes = 102 [ + (custom_options.v1.generate_sdk_option) = true, + (custom_options.v1.subtype) = "oidc", + (google.api.field_visibility).restriction = "INTERNAL" + ]; + } // Output only. Whether this auth method is the primary auth method for it's scope. // To change this value update the primary_auth_method_id field on the scope. @@ -52,7 +67,7 @@ message AuthMethod { repeated string authorized_actions = 300 [json_name = "authorized_actions"]; // @gotags: `class:"public"` // Output only. The authorized actions for the scope's collections. - map authorized_collection_actions = 310 [json_name = "authorized_collection_actions"]; + map authorized_collection_actions = 310 [json_name = "authorized_collection_actions"]; // classified as public via taggable implementation } // The attributes of a password typed auth method. @@ -191,4 +206,4 @@ message OidcAuthMethodAuthenticateTokenResponse { // The status. This will always be "unknown". It will never be forwarded to // the consumer. string status = 10; // @gotags: `class:"public"` -} \ No newline at end of file +} diff --git a/internal/proto/controller/api/services/v1/auth_method_service.proto b/internal/proto/controller/api/services/v1/auth_method_service.proto index cc4a529a2..1e6be74fd 100644 --- a/internal/proto/controller/api/services/v1/auth_method_service.proto +++ b/internal/proto/controller/api/services/v1/auth_method_service.proto @@ -6,9 +6,13 @@ option go_package = "github.com/hashicorp/boundary/internal/gen/controller/api/s import "protoc-gen-openapiv2/options/annotations.proto"; import "google/api/annotations.proto"; +import "google/api/visibility.proto"; import "google/protobuf/field_mask.proto"; import "google/protobuf/struct.proto"; import "controller/api/resources/authmethods/v1/auth_method.proto"; +import "controller/custom_options/v1/options.proto"; + +option (custom_options.v1.domain) = "auth"; service AuthMethodService { // GetAuthMethod returns a stored Auth Method if present. The provided request @@ -165,8 +169,11 @@ message ChangeStateRequest { // The mutation will fail if the version does not match the latest known good version. uint32 version = 2; - // The attributes specific to this auth method's state. - google.protobuf.Struct attributes = 4; + oneof attrs { + // The attributes specific to this auth method's state. + google.protobuf.Struct attributes = 4 [(custom_options.v1.subtype) = "default"]; + OidcChangeStateAttributes oidc_change_state_attributes = 5 [(custom_options.v1.subtype) = "oidc", (google.api.field_visibility).restriction = "INTERNAL"]; + } } message ChangeStateResponse { diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service.go b/internal/servers/controller/handlers/authmethods/authmethod_service.go index d1173eb48..ec9cbca0a 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service.go @@ -32,7 +32,6 @@ import ( "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" "github.com/hashicorp/go-secure-stdlib/strutil" "google.golang.org/grpc/codes" - "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/wrapperspb" ) @@ -46,6 +45,8 @@ const ( authMethodIdField = "auth_method_id" tokenTypeField = "type" isPrimaryField = "is_primary" + + domain = "auth" ) var ( @@ -150,7 +151,7 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe for _, am := range ul { res.Id = am.GetPublicId() res.ScopeId = am.GetScopeId() - authorizedActions := authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId("auth", am.GetPublicId())], requestauth.WithResource(&res)).Strings() + authorizedActions := authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())], requestauth.WithResource(&res)).Strings() if len(authorizedActions) == 0 { continue } @@ -177,7 +178,13 @@ func (s Service) ListAuthMethods(ctx context.Context, req *pbs.ListAuthMethodsRe return nil, err } - if filter.Match(item) { + // This comes last so that we can use item fields in the filter after + // the allowed fields are populated above + filterable, err := subtypes.Filterable(item) + if err != nil { + return nil, err + } + if filter.Match(filterable) { finalItems = append(finalItems, item) } } @@ -211,7 +218,7 @@ func (s Service) GetAuthMethod(ctx context.Context, req *pbs.GetAuthMethodReques outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId("auth", am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -256,7 +263,7 @@ func (s Service) CreateAuthMethod(ctx context.Context, req *pbs.CreateAuthMethod outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId("auth", am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -306,7 +313,7 @@ func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethod outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId("auth", am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -321,8 +328,8 @@ func (s Service) UpdateAuthMethod(ctx context.Context, req *pbs.UpdateAuthMethod return nil, err } - if item.GetAttributes() != nil && dryRun { - item.GetAttributes().Fields["dry_run"] = structpb.NewBoolValue(true) + if item.GetOidcAuthMethodsAttributes() != nil && dryRun { + item.GetOidcAuthMethodsAttributes().DryRun = true } return &pbs.UpdateAuthMethodResponse{Item: item}, nil @@ -360,7 +367,7 @@ func (s Service) ChangeState(ctx context.Context, req *pbs.ChangeStateRequest) ( outputOpts = append(outputOpts, handlers.WithScope(authResults.Scope)) } if outputFields.Has(globals.AuthorizedActionsField) { - outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId("auth", am.GetPublicId())]).Strings())) + outputOpts = append(outputOpts, handlers.WithAuthorizedActions(authResults.FetchActionSetForId(ctx, am.GetPublicId(), IdActions[subtypes.SubtypeFromId(domain, am.GetPublicId())]).Strings())) } if outputFields.Has(globals.AuthorizedCollectionActionsField) { collectionActions, err := requestauth.CalculateAuthorizedCollectionActions(ctx, authResults, collectionTypeMap, authResults.Scope.Id, am.GetPublicId()) @@ -401,7 +408,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) return nil, err } - switch subtypes.SubtypeFromId("auth", req.GetAuthMethodId()) { + switch subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) { case password.Subtype: if err := validateAuthenticatePasswordRequest(req); err != nil { return nil, err @@ -417,7 +424,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) return nil, authResults.Error } - switch subtypes.SubtypeFromId("auth", req.GetAuthMethodId()) { + switch subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) { case password.Subtype: return s.authenticatePassword(ctx, req, &authResults) @@ -430,7 +437,7 @@ func (s Service) Authenticate(ctx context.Context, req *pbs.AuthenticateRequest) func (s Service) getFromRepo(ctx context.Context, id string) (auth.AuthMethod, error) { var lookupErr error var am auth.AuthMethod - switch subtypes.SubtypeFromId("auth", id) { + switch subtypes.SubtypeFromId(domain, id) { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -500,7 +507,7 @@ func (s Service) listFromRepo(ctx context.Context, scopeIds []string, authResult func (s Service) createInRepo(ctx context.Context, scopeId string, item *pb.AuthMethod) (auth.AuthMethod, error) { const op = "authmethods.(Service).createInRepo" var out auth.AuthMethod - switch subtypes.SubtypeFromType("auth", item.GetType()) { + switch subtypes.SubtypeFromType(domain, item.GetType()) { case password.Subtype: am, err := s.createPwInRepo(ctx, scopeId, item) if err != nil { @@ -529,7 +536,7 @@ func (s Service) updateInRepo(ctx context.Context, scopeId string, req *pbs.Upda var am auth.AuthMethod var dryRun bool - switch subtypes.SubtypeFromId("auth", req.GetId()) { + switch subtypes.SubtypeFromId(domain, req.GetId()) { case password.Subtype: pam, err := s.updatePwInRepo(ctx, scopeId, req.GetId(), req.GetUpdateMask().GetPaths(), req.GetItem()) if err != nil { @@ -559,7 +566,7 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, const op = "authmethods.(Service).deleteFromRepo" var rows int var dErr error - switch subtypes.SubtypeFromId("auth", id) { + switch subtypes.SubtypeFromId(domain, id) { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -588,18 +595,14 @@ func (s Service) deleteFromRepo(ctx context.Context, scopeId, id string) (bool, func (s Service) changeStateInRepo(ctx context.Context, req *pbs.ChangeStateRequest) (auth.AuthMethod, error) { const op = "authmethod_service.(Service).changeStateInRepo" - switch subtypes.SubtypeFromId("auth", req.GetId()) { + switch subtypes.SubtypeFromId(domain, req.GetId()) { case oidc.Subtype: repo, err := s.oidcRepoFn() if err != nil { return nil, err } - attrs := &pbs.OidcChangeStateAttributes{} - if err := handlers.StructToProto(req.GetAttributes(), attrs); err != nil { - return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to parse attributes")) - } - + attrs := req.GetOidcChangeStateAttributes() var opts []oidc.Option if attrs.GetDisableDiscoveredConfigValidation() { opts = append(opts, oidc.WithForce()) @@ -651,7 +654,7 @@ func (s Service) authResult(ctx context.Context, id string, a action.Type) reque } default: var authMeth auth.AuthMethod - switch subtypes.SubtypeFromId("auth", id) { + switch subtypes.SubtypeFromId(domain, id) { case password.Subtype: repo, err := s.pwRepoFn() if err != nil { @@ -744,14 +747,12 @@ func toAuthMethodProto(ctx context.Context, in auth.AuthMethod, opt ...handlers. if !outputFields.Has(globals.AttributesField) { break } - st, err := handlers.ProtoToStruct(&pb.PasswordAuthMethodAttributes{ - MinLoginNameLength: i.GetMinLoginNameLength(), - MinPasswordLength: i.GetMinPasswordLength(), - }) - if err != nil { - return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "failed building password attribute struct: %v", err) + out.Attrs = &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinLoginNameLength: i.GetMinLoginNameLength(), + MinPasswordLength: i.GetMinPasswordLength(), + }, } - out.Attributes = st case *oidc.AuthMethod: if outputFields.Has(globals.TypeField) { out.Type = oidc.Subtype.String() @@ -787,12 +788,11 @@ func toAuthMethodProto(ctx context.Context, in auth.AuthMethod, opt ...handlers. attrs.MaxAge = wrapperspb.UInt32(uint32(i.GetMaxAge())) } - st, err := handlers.ProtoToStruct(attrs) - if err != nil { - return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "failed building oidc attribute struct: %v", err) + out.Attrs = &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: attrs, } - out.Attributes = st } + fmt.Println("attrs", out.Attrs) return &out, nil } @@ -837,16 +837,14 @@ func validateCreateRequest(ctx context.Context, req *pbs.CreateAuthMethodRequest if req.GetItem().GetIsPrimary() { badFields[isPrimaryField] = "This field is read only." } - switch subtypes.SubtypeFromType("auth", req.GetItem().GetType()) { + switch subtypes.SubtypeFromType(domain, req.GetItem().GetType()) { case password.Subtype: - attrs := &pb.PasswordAuthMethodAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), attrs); err != nil { - badFields[attributesField] = "Attribute fields do not match the expected format." - } + // Password attributes are not required when creating a password auth method. case oidc.Subtype: - attrs := &pb.OidcAuthMethodAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), attrs); err != nil { - badFields[attributesField] = "Attribute fields do not match the expected format." + attrs := req.GetItem().GetOidcAuthMethodsAttributes() + if attrs == nil { + // OIDC attributes are required when creating an OIDC auth method. + badFields[attributesField] = "Attributes are required for creating an OIDC auth method." } else { if attrs.GetIssuer().GetValue() != "" { iss, err := url.Parse(attrs.GetIssuer().GetValue()) @@ -935,119 +933,114 @@ func validateUpdateRequest(ctx context.Context, req *pbs.UpdateAuthMethodRequest if handlers.MaskContains(req.GetUpdateMask().GetPaths(), isPrimaryField) { badFields[isPrimaryField] = "This field is read only." } - switch subtypes.SubtypeFromId("auth", req.GetId()) { + switch subtypes.SubtypeFromId(domain, req.GetId()) { case password.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType("auth", req.GetItem().GetType()) != password.Subtype { + if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != password.Subtype { badFields[typeField] = "Cannot modify the resource type." } - attrs := &pb.PasswordAuthMethodAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), attrs); err != nil { - badFields[attributesField] = "Attribute fields do not match the expected format." - } case oidc.Subtype: - if req.GetItem().GetType() != "" && subtypes.SubtypeFromType("auth", req.GetItem().GetType()) != oidc.Subtype { + if req.GetItem().GetType() != "" && subtypes.SubtypeFromType(domain, req.GetItem().GetType()) != oidc.Subtype { badFields[typeField] = "Cannot modify the resource type." } - attrs := &pb.OidcAuthMethodAttributes{} - if err := handlers.StructToProto(req.GetItem().GetAttributes(), attrs); err != nil { - badFields[attributesField] = "Attribute fields do not match the expected format." - } - if attrs.DryRun && attrs.DisableDiscoveredConfigValidation { - badFields[disableDiscoveredConfigValidationField] = "This field cannot be set to true with dry_run." - } + attrs := req.GetItem().GetOidcAuthMethodsAttributes() + if attrs != nil { + if attrs.DryRun && attrs.DisableDiscoveredConfigValidation { + badFields[disableDiscoveredConfigValidationField] = "This field cannot be set to true with dry_run." + } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), apiUrlPrefixField) { - // TODO: When we start accepting the address used in the request make this an optional field. - if strings.TrimSpace(attrs.GetApiUrlPrefix().GetValue()) == "" { - badFields[apiUrlPrefixField] = "This field should not be set to empty." - } - if cu, err := url.Parse(attrs.GetApiUrlPrefix().GetValue()); err != nil || (cu.Scheme != "http" && cu.Scheme != "https") || cu.Host == "" { - badFields[apiUrlPrefixField] = fmt.Sprintf("%q cannot be parsed as a url.", attrs.GetApiUrlPrefix().GetValue()) - } - } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), issuerField) { - if attrs.GetIssuer().GetValue() != "" { - iss, err := url.Parse(attrs.GetIssuer().GetValue()) - if err != nil { - badFields[issuerField] = fmt.Sprintf("Cannot be parsed as a url. %v", err) + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), apiUrlPrefixField) { + // TODO: When we start accepting the address used in the request make this an optional field. + if strings.TrimSpace(attrs.GetApiUrlPrefix().GetValue()) == "" { + badFields[apiUrlPrefixField] = "This field should not be set to empty." } - if iss != nil && !strutil.StrListContains([]string{"http", "https"}, iss.Scheme) { - badFields[issuerField] = fmt.Sprintf("Must have schema %q or %q specified", "http", "https") - } - } - } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), apiUrlPrefixField) { - if attrs.GetApiUrlPrefix().GetValue() != "" { - cu, err := url.Parse(attrs.GetApiUrlPrefix().GetValue()) - if err != nil || cu.Host == "" { + if cu, err := url.Parse(attrs.GetApiUrlPrefix().GetValue()); err != nil || (cu.Scheme != "http" && cu.Scheme != "https") || cu.Host == "" { badFields[apiUrlPrefixField] = fmt.Sprintf("%q cannot be parsed as a url.", attrs.GetApiUrlPrefix().GetValue()) } - if !strutil.StrListContains([]string{"http", "https"}, cu.Scheme) { - badFields[apiUrlPrefixField] = fmt.Sprintf("Must have schema %q or %q specified", "http", "https") - } } - } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), clientSecretField) && attrs.GetClientSecret().GetValue() == "" { - badFields[clientSecretField] = "Can change but cannot unset this field." - } - if handlers.MaskContains(req.GetUpdateMask().GetPaths(), clientIdField) && attrs.GetClientId().GetValue() == "" { - badFields[clientIdField] = "Can change but cannot unset this field." - } - - if attrs.GetClientSecretHmac() != "" { - badFields[clientSecretHmacField] = "Field is read only." - } - if attrs.GetState() != "" { - badFields[stateField] = "Field is read only." - } - if attrs.GetCallbackUrl() != "" { - badFields[callbackUrlField] = "Field is read only." - } - - if len(attrs.GetSigningAlgorithms()) > 0 { - for _, sa := range attrs.GetSigningAlgorithms() { - if !oidc.SupportedAlgorithm(oidc.Alg(sa)) { - badFields[signingAlgorithmField] = fmt.Sprintf("Contains unsupported algorithm %q", sa) - break - } - } - } - if len(attrs.GetIdpCaCerts()) > 0 { - if _, err := oidc.ParseCertificates(ctx, attrs.GetIdpCaCerts()...); err != nil { - badFields[idpCaCertsField] = fmt.Sprintf("Cannot parse CA certificates. %v", err.Error()) - } - } - if len(attrs.GetClaimsScopes()) > 0 { - for _, cs := range attrs.GetClaimsScopes() { - if cs == oidc.DefaultClaimsScope { - badFields[claimsScopesField] = fmt.Sprintf("%s is the default scope and cannot be added as optional %q", oidc.DefaultClaimsScope, cs) - break - } - } - } - if len(attrs.GetAccountClaimMaps()) > 0 { - acm, err := oidc.ParseAccountClaimMaps(ctx, attrs.GetAccountClaimMaps()...) - if err != nil { - badFields[accountClaimMapsField] = fmt.Sprintf("Contains invalid map %q", err.Error()) - } else { - foundTo := make(map[string]bool, len(attrs.GetAccountClaimMaps())) - for _, m := range acm { - if foundTo[m.To] { - badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map - multiple maps to the same Boundary to-claim %s", m.From, m.To, m.To) - } - foundTo[m.To] = true - - to, err := oidc.ConvertToAccountToClaim(ctx, m.To) + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), issuerField) { + if attrs.GetIssuer().GetValue() != "" { + iss, err := url.Parse(attrs.GetIssuer().GetValue()) if err != nil { - badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map %q", m.From, m.To, err.Error()) + badFields[issuerField] = fmt.Sprintf("Cannot be parsed as a url. %v", err) + } + if iss != nil && !strutil.StrListContains([]string{"http", "https"}, iss.Scheme) { + badFields[issuerField] = fmt.Sprintf("Must have schema %q or %q specified", "http", "https") + } + } + } + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), apiUrlPrefixField) { + if attrs.GetApiUrlPrefix().GetValue() != "" { + cu, err := url.Parse(attrs.GetApiUrlPrefix().GetValue()) + if err != nil || cu.Host == "" { + badFields[apiUrlPrefixField] = fmt.Sprintf("%q cannot be parsed as a url.", attrs.GetApiUrlPrefix().GetValue()) + } + if !strutil.StrListContains([]string{"http", "https"}, cu.Scheme) { + badFields[apiUrlPrefixField] = fmt.Sprintf("Must have schema %q or %q specified", "http", "https") + } + } + } + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), clientSecretField) && attrs.GetClientSecret().GetValue() == "" { + badFields[clientSecretField] = "Can change but cannot unset this field." + } + if handlers.MaskContains(req.GetUpdateMask().GetPaths(), clientIdField) && attrs.GetClientId().GetValue() == "" { + badFields[clientIdField] = "Can change but cannot unset this field." + } + + if attrs.GetClientSecretHmac() != "" { + badFields[clientSecretHmacField] = "Field is read only." + } + if attrs.GetState() != "" { + badFields[stateField] = "Field is read only." + } + if attrs.GetCallbackUrl() != "" { + badFields[callbackUrlField] = "Field is read only." + } + + if len(attrs.GetSigningAlgorithms()) > 0 { + for _, sa := range attrs.GetSigningAlgorithms() { + if !oidc.SupportedAlgorithm(oidc.Alg(sa)) { + badFields[signingAlgorithmField] = fmt.Sprintf("Contains unsupported algorithm %q", sa) break } - if to == oidc.ToSubClaim { - badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map: not allowed to update sub claim maps", m.From, m.To) + } + } + if len(attrs.GetIdpCaCerts()) > 0 { + if _, err := oidc.ParseCertificates(ctx, attrs.GetIdpCaCerts()...); err != nil { + badFields[idpCaCertsField] = fmt.Sprintf("Cannot parse CA certificates. %v", err.Error()) + } + } + if len(attrs.GetClaimsScopes()) > 0 { + for _, cs := range attrs.GetClaimsScopes() { + if cs == oidc.DefaultClaimsScope { + badFields[claimsScopesField] = fmt.Sprintf("%s is the default scope and cannot be added as optional %q", oidc.DefaultClaimsScope, cs) break } } } + if len(attrs.GetAccountClaimMaps()) > 0 { + acm, err := oidc.ParseAccountClaimMaps(ctx, attrs.GetAccountClaimMaps()...) + if err != nil { + badFields[accountClaimMapsField] = fmt.Sprintf("Contains invalid map %q", err.Error()) + } else { + foundTo := make(map[string]bool, len(attrs.GetAccountClaimMaps())) + for _, m := range acm { + if foundTo[m.To] { + badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map - multiple maps to the same Boundary to-claim %s", m.From, m.To, m.To) + } + foundTo[m.To] = true + + to, err := oidc.ConvertToAccountToClaim(ctx, m.To) + if err != nil { + badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map %q", m.From, m.To, err.Error()) + break + } + if to == oidc.ToSubClaim { + badFields[accountClaimMapsField] = fmt.Sprintf("%s=%s contains invalid map: not allowed to update sub claim maps", m.From, m.To) + break + } + } + } + } } default: badFields["id"] = "Incorrectly formatted identifier." @@ -1088,7 +1081,7 @@ func validateChangeStateRequest(req *pbs.ChangeStateRequest) error { if req == nil { return errors.NewDeprecated(errors.InvalidParameter, op, "Missing request") } - if st := subtypes.SubtypeFromId("auth", req.GetId()); st != oidc.Subtype { + if st := subtypes.SubtypeFromId(domain, req.GetId()); st != oidc.Subtype { return handlers.NotFoundErrorf("This endpoint is only available for the %q Auth Method type.", oidc.Subtype.String()) } badFields := make(map[string]string) @@ -1096,14 +1089,15 @@ func validateChangeStateRequest(req *pbs.ChangeStateRequest) error { badFields[versionField] = "Resource version is required." } - attrs := &pbs.OidcChangeStateAttributes{} - if err := handlers.StructToProto(req.GetAttributes(), attrs); err != nil { - badFields[attributesField] = "Attribute fields do not match the expected format." - } - switch oidcStateMap[attrs.GetState()] { - case inactiveState, privateState, publicState: - default: - badFields[stateField] = fmt.Sprintf("Only supported values are %q, %q, or %q.", inactiveState.String(), privateState.String(), publicState.String()) + attrs := req.GetOidcChangeStateAttributes() + if attrs == nil { + badFields[attributesField] = "Attributes are required when changing an auth method." + } else { + switch oidcStateMap[attrs.GetState()] { + case inactiveState, privateState, publicState: + default: + badFields[stateField] = fmt.Sprintf("Only supported values are %q, %q, or %q.", inactiveState.String(), privateState.String(), publicState.String()) + } } if len(badFields) > 0 { return handlers.InvalidArgumentErrorf("Invalid fields provided in request.", badFields) @@ -1122,7 +1116,7 @@ func validateAuthenticateRequest(req *pbs.AuthenticateRequest) error { if strings.TrimSpace(req.GetAuthMethodId()) == "" { badFields[authMethodIdField] = "This is a required field." } else { - st := subtypes.SubtypeFromId("auth", req.GetAuthMethodId()) + st := subtypes.SubtypeFromId(domain, req.GetAuthMethodId()) switch st { case password.Subtype, oidc.Subtype: default: diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go index 577ec6275..9653c8412 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "regexp" - "sort" "strings" "testing" @@ -102,10 +101,12 @@ func TestGet(t *testing.T) { CreatedTime: am.CreateTime.GetTimestamp(), UpdatedTime: am.UpdateTime.GetTimestamp(), Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Version: 1, Scope: &scopepb.ScopeInfo{ Id: o.GetPublicId(), @@ -128,14 +129,16 @@ func TestGet(t *testing.T) { CreatedTime: oidcam.CreateTime.GetTimestamp(), UpdatedTime: oidcam.UpdateTime.GetTimestamp(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://alice.com"), - "client_id": structpb.NewStringValue("alice_rp"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "callback_url": structpb.NewStringValue(fmt.Sprintf(oidc.CallbackEndpoint, "https://api.com")), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://alice.com"), + ClientId: wrapperspb.String("alice_rp"), + ClientSecretHmac: "", + State: string(oidc.InactiveState), + ApiUrlPrefix: wrapperspb.String("https://api.com"), + CallbackUrl: fmt.Sprintf(oidc.CallbackEndpoint, "https://api.com"), + }, + }, Version: 1, Scope: &scopepb.ScopeInfo{ Id: o.GetPublicId(), @@ -201,11 +204,10 @@ func TestGet(t *testing.T) { return } require.NoError(gErr) - if _, ok := got.Item.Attributes.Fields["client_secret_hmac"]; ok { - assert.NotEqual("secret", got.Item.Attributes.Fields["client_secret_hmac"]) - got.Item.Attributes.Fields["client_secret_hmac"] = structpb.NewStringValue("") + if oidcAttrs := got.Item.GetOidcAuthMethodsAttributes(); oidcAttrs != nil { + assert.NotEqual("secret", oidcAttrs.ClientSecretHmac) } - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "GetAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.IgnoreFields(&pb.OidcAuthMethodAttributes{}, "client_secret_hmac")), "GetAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) }) } } @@ -249,18 +251,19 @@ func TestList(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: oWithAuthMethods.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, Version: 2, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://alice.com"), - "client_id": structpb.NewStringValue("alice_rp"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.ActivePublicState)), - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "callback_url": structpb.NewStringValue(fmt.Sprintf(oidc.CallbackEndpoint, "https://api.com")), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.EdDSA)}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://alice.com"), + ClientId: wrapperspb.String("alice_rp"), + ClientSecretHmac: "", + State: string(oidc.ActivePublicState), + ApiUrlPrefix: wrapperspb.String("https://api.com"), + CallbackUrl: fmt.Sprintf(oidc.CallbackEndpoint, "https://api.com"), + SigningAlgorithms: []string{ + string(oidc.EdDSA), + }, + }, + }, IsPrimary: true, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -275,10 +278,12 @@ func TestList(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: oWithAuthMethods.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, Version: 1, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }) @@ -294,10 +299,12 @@ func TestList(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: oWithOtherAuthMethods.GetPublicId(), Type: scope.Org.String(), ParentScopeId: scope.Global.String()}, Version: 1, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }) @@ -369,21 +376,20 @@ func TestList(t *testing.T) { return } require.NoError(gErr) - for i, g := range got.Items { - if _, ok := g.Attributes.Fields["client_secret_hmac"]; ok { - assert.NotEqual("secret", g.Attributes.Fields["client_secret_hmac"]) - delete(g.Attributes.Fields, "client_secret_hmac") - delete(tc.res.Items[i].Attributes.Fields, "client_secret_hmac") + for _, g := range got.Items { + if oidcAttrs := g.GetOidcAuthMethodsAttributes(); oidcAttrs != nil { + assert.NotEqual("secret", oidcAttrs.ClientSecretHmac) } } - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ListAuthMethods() for scope %q got response %q, wanted %q", tc.req.GetScopeId(), got, tc.res) + assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.IgnoreFields(&pb.OidcAuthMethodAttributes{}, "client_secret_hmac")), + "ListAuthMethods() for scope %q got response %q, wanted %q", tc.req.GetScopeId(), got, tc.res) // Now check with anonymous user got, gErr = s.ListAuthMethods(requestauth.DisabledAuthTestContext(iamRepoFn, tc.req.GetScopeId(), requestauth.WithUserId(requestauth.AnonymousUserId)), tc.req) require.NoError(gErr) assert.Len(got.Items, len(tc.res.Items)) for _, g := range got.GetItems() { - assert.Nil(g.Attributes) + assert.Nil(g.Attrs) assert.Nil(g.CreatedTime) assert.Nil(g.UpdatedTime) assert.Empty(g.Version) @@ -560,10 +566,12 @@ func TestCreate(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: o.GetType(), ParentScopeId: scope.Global.String()}, Version: 1, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, @@ -574,24 +582,17 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "api_url_prefix": structpb.NewStringValue("https://callback.prefix:9281/path"), - "allowed_audiences": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"foo", "bar"}) - return structpb.NewListValue(lv) - }(), - "claims_scopes": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"email", "profile"}) - return structpb.NewListValue(lv) - }(), - "account_claim_maps": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"display_name=name", "oid=sub"}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + ApiUrlPrefix: wrapperspb.String("https://callback.prefix:9281/path"), + AllowedAudiences: []string{"foo", "bar"}, + ClaimsScopes: []string{"email", "profile"}, + AccountClaimMaps: []string{"display_name=name", "oid=sub"}, + }, + }, }}, idPrefix: oidc.AuthMethodPrefix + "_", res: &pbs.CreateAuthMethodResponse{ @@ -604,26 +605,19 @@ func TestCreate(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: o.GetType(), ParentScopeId: scope.Global.String()}, Version: 1, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - "api_url_prefix": structpb.NewStringValue("https://callback.prefix:9281/path"), - "callback_url": structpb.NewStringValue("https://callback.prefix:9281/path/v1/auth-methods/oidc:authenticate:callback"), - "allowed_audiences": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"foo", "bar"}) - return structpb.NewListValue(lv) - }(), - "claims_scopes": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"email", "profile"}) - return structpb.NewListValue(lv) - }(), - "account_claim_maps": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"display_name=name", "oid=sub"}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://example.discovery.url:4821/"), + ClientId: wrapperspb.String("someclientid"), + ClientSecretHmac: "", + State: string(oidc.InactiveState), + ApiUrlPrefix: wrapperspb.String("https://callback.prefix:9281/path"), + CallbackUrl: "https://callback.prefix:9281/path/v1/auth-methods/oidc:authenticate:callback", + AllowedAudiences: []string{"foo", "bar"}, + ClaimsScopes: []string{"email", "profile"}, + AccountClaimMaps: []string{"display_name=name", "oid=sub"}, + }, + }, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, @@ -650,10 +644,12 @@ func TestCreate(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, Version: 1, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, @@ -664,12 +660,14 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: scope.Global.String(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://example.discovery.url"), - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://example.discovery.url"), + ApiUrlPrefix: wrapperspb.String("https://api.com"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + }, + }, }}, idPrefix: oidc.AuthMethodPrefix + "_", res: &pbs.CreateAuthMethodResponse{ @@ -682,13 +680,15 @@ func TestCreate(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: scope.Global.String(), Type: scope.Global.String(), Name: scope.Global.String(), Description: "Global Scope"}, Version: 1, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url"), + ClientId: wrapperspb.String("someclientid"), + ClientSecretHmac: "", + State: string(oidc.InactiveState), + }, + }, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, @@ -754,46 +754,18 @@ func TestCreate(t *testing.T) { res: nil, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, - { - name: "Attributes must be valid for password type", - req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "Attributes must be valid for type"}, - Description: &wrapperspb.StringValue{Value: "Attributes must be valid for type"}, - Type: password.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "invalid_field": structpb.NewStringValue("invalid_value"), - "min_login_name_length": structpb.NewNumberValue(3), - }}, - }}, - res: nil, - err: handlers.ApiErrorWithCode(codes.InvalidArgument), - }, - { - name: "Attributes must be valid for oidc type", - req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "Attributes must be valid for type"}, - Description: &wrapperspb.StringValue{Value: "Attributes must be valid for type"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "login-name": structpb.NewStringValue("invalid_value"), - "password": structpb.NewNumberValue(3), - }}, - }}, - res: nil, - err: handlers.ApiErrorWithCode(codes.InvalidArgument), - }, { name: "OIDC AuthMethod Doesn't Require Issuer", req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + }, + }, }}, res: &pbs.CreateAuthMethodResponse{ Uri: fmt.Sprintf("auth-methods/%s_", oidc.AuthMethodPrefix), @@ -805,12 +777,14 @@ func TestCreate(t *testing.T) { Scope: &scopepb.ScopeInfo{Id: o.GetPublicId(), Type: o.GetType(), ParentScopeId: scope.Global.String()}, Version: 1, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + ClientId: wrapperspb.String("someclientid"), + ClientSecretHmac: "", + State: string(oidc.InactiveState), + }, + }, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, }, @@ -821,10 +795,12 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -833,11 +809,13 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_secret": structpb.NewStringValue("secret"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientSecret: wrapperspb.String("secret"), + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -846,11 +824,13 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_id": structpb.NewStringValue("someclientid"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientId: wrapperspb.String("someclientid"), + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -859,13 +839,15 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "client_secret_hmac": structpb.NewStringValue("hmac"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + ClientSecretHmac: "hmac", + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -874,13 +856,15 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + State: string(oidc.InactiveState), + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -889,16 +873,15 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example2.discovery.url:4821"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.ES256), strings.ToLower(string(oidc.EdDSA))}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example2.discovery.url:4821"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + SigningAlgorithms: []string{string(oidc.ES256), strings.ToLower(string(oidc.EdDSA))}, + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -907,12 +890,14 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://example2.discovery.url:4821"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "api_url_prefix": structpb.NewStringValue("invalid path"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://example2.discovery.url:4821"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + ApiUrlPrefix: wrapperspb.String("invalid path"), + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -921,12 +906,14 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue("https://example2.discovery.url:4821"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "callback_url": structpb.NewStringValue("http://another.url.com:82471"), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String("https://example2.discovery.url:4821"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + CallbackUrl: "http://another.url.com:82471", + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -935,16 +922,15 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example2.discovery.url:4821"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "idp_ca_certs": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"unparseable"}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example2.discovery.url:4821"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + IdpCaCerts: []string{"unparseable"}, + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -953,16 +939,15 @@ func TestCreate(t *testing.T) { req: &pbs.CreateAuthMethodRequest{Item: &pb.AuthMethod{ ScopeId: o.GetPublicId(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://api.com"), - "issuer": structpb.NewStringValue("https://example.discovery.url:4821/.well-known/openid-configuration/"), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "claims_scopes": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"openid"}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://api.com"), + Issuer: wrapperspb.String("https://example.discovery.url:4821/.well-known/openid-configuration/"), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + ClaimsScopes: []string{"openid"}, + }, + }, }}, err: handlers.ApiErrorWithCode(codes.InvalidArgument), }, @@ -984,6 +969,7 @@ func TestCreate(t *testing.T) { if tc.res == nil { require.Nil(got) } + cmpOptions := []cmp.Option{protocmp.Transform()} if got != nil { assert.Contains(got.GetUri(), tc.res.Uri) assert.True(strings.HasPrefix(got.GetItem().GetId(), tc.idPrefix)) @@ -994,38 +980,27 @@ func TestCreate(t *testing.T) { assert.True(gotCreateTime.AsTime().After(defaultCreated.AsTime()), "New auth_method should have been created after default auth_method. Was created %v, which is after %v", gotCreateTime, defaultCreated) assert.True(gotUpdateTime.AsTime().After(defaultCreated.AsTime()), "New auth_method should have been updated after default auth_method. Was updated %v, which is after %v", gotUpdateTime, defaultCreated) - // Clear all values which are hard to compare against. - got.Uri, tc.res.Uri = "", "" - got.Item.Id, tc.res.Item.Id = "", "" - got.Item.CreatedTime, got.Item.UpdatedTime, tc.res.Item.CreatedTime, tc.res.Item.UpdatedTime = nil, nil, nil, nil - if _, ok := got.Item.Attributes.Fields["client_secret_hmac"]; ok { - assert.NotEqual(tc.req.Item.Attributes.Fields["client_secret"], got.Item.Attributes.Fields["client_secret_hmac"]) - got.Item.Attributes.Fields["client_secret_hmac"] = structpb.NewStringValue("") - } - if _, ok := got.Item.Attributes.Fields["callback_url"]; ok { - exp := tc.res.Item.Attributes.Fields["callback_url"].GetStringValue() - gVal := got.Item.Attributes.Fields["callback_url"].GetStringValue() + // Ignore all values which are hard to compare against. + cmpOptions = append( + cmpOptions, + protocmp.IgnoreFields(&pbs.CreateAuthMethodResponse{}, "uri"), + protocmp.IgnoreFields(&pb.AuthMethod{}, "id", "created_time", "updated_time"), + ) + if oidcAttrs := got.Item.GetOidcAuthMethodsAttributes(); oidcAttrs != nil { + assert.NotEqual(oidcAttrs.ClientSecret, oidcAttrs.ClientSecretHmac) + exp := tc.res.Item.Attrs.(*pb.AuthMethod_OidcAuthMethodsAttributes).OidcAuthMethodsAttributes.CallbackUrl + gVal := oidcAttrs.CallbackUrl matches, err := regexp.MatchString(exp, gVal) require.NoError(err) assert.True(matches, "%q doesn't match %q", gVal, exp) - delete(got.Item.Attributes.Fields, "callback_url") - delete(tc.res.Item.Attributes.Fields, "callback_url") + cmpOptions = append( + cmpOptions, + protocmp.SortRepeatedFields(&pb.OidcAuthMethodAttributes{}, "account_claim_maps"), + protocmp.IgnoreFields(&pb.OidcAuthMethodAttributes{}, "client_secret_hmac", "callback_url"), + ) } - if v, ok := got.Item.Attributes.Fields["account_claim_maps"]; ok { - lv := v.GetListValue().GetValues() - sort.Slice(lv, func(i, j int) bool { - return lv[i].GetStringValue() < lv[j].GetStringValue() - }) - } - if v, ok := tc.res.Item.Attributes.Fields["account_claim_maps"]; ok { - lv := v.GetListValue().GetValues() - sort.Slice(lv, func(i, j int) bool { - return lv[i].GetStringValue() < lv[j].GetStringValue() - }) - } - } - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "CreateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) + assert.Empty(cmp.Diff(got, tc.res, cmpOptions...), "CreateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) }) } } diff --git a/internal/servers/controller/handlers/authmethods/oidc.go b/internal/servers/controller/handlers/authmethods/oidc.go index 6a5b4de92..4aeabbd17 100644 --- a/internal/servers/controller/handlers/authmethods/oidc.go +++ b/internal/servers/controller/handlers/authmethods/oidc.go @@ -414,11 +414,7 @@ func toStorageOidcAuthMethod(ctx context.Context, scopeId string, in *pb.AuthMet if in == nil { return nil, false, false, errors.NewDeprecated(errors.InvalidParameter, op, "nil auth method.") } - attrs := &pb.OidcAuthMethodAttributes{} - if err := handlers.StructToProto(in.GetAttributes(), attrs); err != nil { - return nil, false, false, handlers.InvalidArgumentErrorf("Error in provided request.", - map[string]string{attributesField: "Attribute fields do not match the expected format."}) - } + attrs := in.GetOidcAuthMethodsAttributes() clientId := attrs.GetClientId().GetValue() clientSecret := oidc.ClientSecret(attrs.GetClientSecret().GetValue()) diff --git a/internal/servers/controller/handlers/authmethods/oidc_test.go b/internal/servers/controller/handlers/authmethods/oidc_test.go index 6b656852e..c067a0fd7 100644 --- a/internal/servers/controller/handlers/authmethods/oidc_test.go +++ b/internal/servers/controller/handlers/authmethods/oidc_test.go @@ -267,39 +267,27 @@ func TestUpdate_OIDC(t *testing.T) { tp.SetClientCreds(tpClientId, tpClientSecret) _, _, tpAlg, _ := tp.SigningKeys() - defaultAttributeFields := func() map[string]*structpb.Value { - return map[string]*structpb.Value{ - "issuer": structpb.NewStringValue(tp.Addr()), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret": structpb.NewStringValue("secret"), - "api_url_prefix": structpb.NewStringValue("http://example.com"), - "idp_ca_certs": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{tp.CACert()}) - return structpb.NewListValue(lv) - }(), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(tpAlg)}) - return structpb.NewListValue(lv) - }(), - } + defaultAttributes := &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String(tp.Addr()), + ClientId: wrapperspb.String("someclientid"), + ClientSecret: wrapperspb.String("secret"), + ApiUrlPrefix: wrapperspb.String("https://example.com"), + IdpCaCerts: []string{tp.CACert()}, + SigningAlgorithms: []string{string(tpAlg)}, + }, } - defaultReadAttributeFields := func() map[string]*structpb.Value { - return map[string]*structpb.Value{ - "issuer": structpb.NewStringValue(tp.Addr()), - "client_id": structpb.NewStringValue("someclientid"), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.ActivePrivateState)), - "api_url_prefix": structpb.NewStringValue("http://example.com"), - "callback_url": structpb.NewStringValue("http://example.com/v1/auth-methods/oidc:authenticate:callback"), - "idp_ca_certs": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{tp.CACert()}) - return structpb.NewListValue(lv) - }(), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(tpAlg)}) - return structpb.NewListValue(lv) - }(), - } + defaultReadAttributes := &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String(tp.Addr()), + ClientId: wrapperspb.String("someclientid"), + ClientSecretHmac: "", + State: string(oidc.ActivePrivateState), + ApiUrlPrefix: wrapperspb.String("https://example.com"), + CallbackUrl: "https://example.com/v1/auth-methods/oidc:authenticate:callback", + IdpCaCerts: []string{tp.CACert()}, + SigningAlgorithms: []string{string(tpAlg)}, + }, } freshAuthMethod := func(t *testing.T) (*pb.AuthMethod, func()) { @@ -309,17 +297,17 @@ func TestUpdate_OIDC(t *testing.T) { Name: wrapperspb.String("default"), Description: wrapperspb.String("default"), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultAttributeFields(), - }, + Attrs: defaultAttributes, }}) require.NoError(t, err) csr, err := tested.ChangeState(ctx, &pbs.ChangeStateRequest{ Id: am.GetItem().GetId(), Version: am.GetItem().GetVersion(), - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{"state": structpb.NewStringValue("active-private")}, + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-private", + }, }, }) require.NoError(t, err) @@ -353,13 +341,11 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -380,13 +366,11 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "new"}, - Description: &wrapperspb.StringValue{Value: "desc"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "new"}, + Description: &wrapperspb.StringValue{Value: "desc"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -400,14 +384,12 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.issuer"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultAttributeFields() - f["issuer"] = structpb.NewStringValue("http://localhost:72759/somepath/.well-known/openid-configuration") - f["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.Issuer = wrapperspb.String("http://localhost:72759/somepath/.well-known/openid-configuration") + f.DisableDiscoveredConfigValidation = true + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), }, }, res: &pbs.UpdateAuthMethodResponse{ @@ -416,14 +398,13 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["issuer"] = structpb.NewStringValue("http://localhost:72759/somepath/") - f["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.Issuer = wrapperspb.String("http://localhost:72759/somepath/") + f.DisableDiscoveredConfigValidation = true + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), + Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -437,14 +418,12 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.issuer"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultAttributeFields() - f["issuer"] = structpb.NewStringValue("http://localhost:7dddd") - f["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.Issuer = wrapperspb.String("http://localhost:7dddd") + f.DisableDiscoveredConfigValidation = true + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), }, }, err: handlers.ApiErrorWithCode(codes.InvalidArgument), @@ -514,12 +493,10 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Description: &wrapperspb.StringValue{Value: "default"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Description: &wrapperspb.StringValue{Value: "default"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -538,12 +515,10 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "default"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "default"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -563,13 +538,11 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "updated"}, - Description: &wrapperspb.StringValue{Value: "default"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "updated"}, + Description: &wrapperspb.StringValue{Value: "default"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -589,13 +562,11 @@ func TestUpdate_OIDC(t *testing.T) { }, res: &pbs.UpdateAuthMethodResponse{ Item: &pb.AuthMethod{ - ScopeId: o.GetPublicId(), - Name: &wrapperspb.StringValue{Value: "default"}, - Description: &wrapperspb.StringValue{Value: "notignored"}, - Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: defaultReadAttributeFields(), - }, + ScopeId: o.GetPublicId(), + Name: &wrapperspb.StringValue{Value: "default"}, + Description: &wrapperspb.StringValue{Value: "notignored"}, + Type: oidc.Subtype.String(), + Attrs: defaultReadAttributes, Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -707,9 +678,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.max_age"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "max_age": structpb.NewNumberValue(0), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + MaxAge: wrapperspb.UInt32(0), }, }, }, @@ -720,13 +691,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["max_age"] = structpb.NewNumberValue(0) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.MaxAge = wrapperspb.UInt32(0) + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -740,9 +709,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.max_age"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "max_age": structpb.NewNumberValue(4), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + MaxAge: wrapperspb.UInt32(4), }, }, }, @@ -753,13 +722,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["max_age"] = structpb.NewNumberValue(4) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.MaxAge = wrapperspb.UInt32(4) + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -773,9 +740,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.client_id"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "client_id": structpb.NewStringValue("new id"), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ClientId: wrapperspb.String("new id"), }, }, }, @@ -786,13 +753,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["client_id"] = structpb.NewStringValue("new id") - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.ClientId = wrapperspb.String("new id") + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -806,7 +771,11 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.api_url_prefix"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: nil, // Not strictly necessary to populate this, since it is the zero value, but be explicit + }, + }, }, }, wantErr: true, @@ -818,13 +787,10 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.api_url_prefix"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue("https://callback.prefix:9281/path"), - } - return f - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String("https://callback.prefix:9281/path"), + }, }, }, }, @@ -834,14 +800,12 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["api_url_prefix"] = structpb.NewStringValue("https://callback.prefix:9281/path") - f["callback_url"] = structpb.NewStringValue("https://callback.prefix:9281/path/v1/auth-methods/oidc:authenticate:callback") - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.ApiUrlPrefix = wrapperspb.String("https://callback.prefix:9281/path") + f.CallbackUrl = "https://callback.prefix:9281/path/v1/auth-methods/oidc:authenticate:callback" + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -855,12 +819,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.allowed_audiences"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "allowed_audiences": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"bar", "foo"}) - return structpb.NewListValue(lv) - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + AllowedAudiences: []string{"bar", "foo"}, }, }, }, @@ -871,16 +832,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["allowed_audiences"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"bar", "foo"}) - return structpb.NewListValue(lv) - }() - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.AllowedAudiences = []string{"bar", "foo"} + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -894,12 +850,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.claims_scopes"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "claims_scopes": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"email", "profile"}) - return structpb.NewListValue(lv) - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ClaimsScopes: []string{"email", "profile"}, }, }, }, @@ -910,16 +863,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["claims_scopes"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"email", "profile"}) - return structpb.NewListValue(lv) - }() - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.ClaimsScopes = []string{"email", "profile"} + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -933,12 +881,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.account_claim_maps"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "account_claim_maps": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"display_name=name"}) - return structpb.NewListValue(lv) - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + AccountClaimMaps: []string{"display_name=name"}, }, }, }, @@ -949,16 +894,11 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["account_claim_maps"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"display_name=name"}) - return structpb.NewListValue(lv) - }() - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.AccountClaimMaps = []string{"display_name=name"} + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -972,12 +912,9 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.account_claim_maps"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "account_claim_maps": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{"oid=sub"}) - return structpb.NewListValue(lv) - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + AccountClaimMaps: []string{"oid=sub"}, }, }, }, @@ -1001,15 +938,10 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.signing_algorithms"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultAttributeFields() - f["signing_algorithms"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.EdDSA)}) - return structpb.NewListValue(lv) - }() - return f - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + SigningAlgorithms: []string{string(oidc.EdDSA)}, + }, }, }, }, @@ -1022,16 +954,11 @@ func TestUpdate_OIDC(t *testing.T) { Paths: []string{"attributes.signing_algorithms"}, }, Item: &pb.AuthMethod{ - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultAttributeFields() - f["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - f["signing_algorithms"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.EdDSA)}) - return structpb.NewListValue(lv) - }() - return f - }(), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + DisableDiscoveredConfigValidation: true, + SigningAlgorithms: []string{string(oidc.EdDSA)}, + }, }, }, }, @@ -1041,17 +968,12 @@ func TestUpdate_OIDC(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{ - Fields: func() map[string]*structpb.Value { - f := defaultReadAttributeFields() - f["signing_algorithms"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.EdDSA)}) - return structpb.NewListValue(lv) - }() - f["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - return f - }(), - }, + Attrs: func() *pb.AuthMethod_OidcAuthMethodsAttributes { + f := proto.Clone(defaultReadAttributes.OidcAuthMethodsAttributes).(*pb.OidcAuthMethodAttributes) + f.SigningAlgorithms = []string{string(oidc.EdDSA)} + f.DisableDiscoveredConfigValidation = true + return &pb.AuthMethod_OidcAuthMethodsAttributes{OidcAuthMethodsAttributes: f} + }(), Scope: defaultScopeInfo, AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -1088,7 +1010,7 @@ func TestUpdate_OIDC(t *testing.T) { if tc.res == nil { require.Nil(got) } - + cmpOptions := []cmp.Option{protocmp.Transform()} if got != nil { assert.NotNilf(tc.res, "Expected UpdateAuthMethod response to be nil, but was %v", got) gotUpdateTime := got.GetItem().GetUpdatedTime().AsTime() @@ -1097,27 +1019,26 @@ func TestUpdate_OIDC(t *testing.T) { // Verify it is a auth_method updated after it was created assert.True(gotUpdateTime.After(created), "Updated auth_method should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created) - // Clear all values which are hard to compare against. - if _, ok := got.Item.Attributes.Fields["client_secret_hmac"]; ok { - assert.NotEqual("secret", got.Item.Attributes.Fields["client_secret_hmac"]) - got.Item.Attributes.Fields["client_secret_hmac"] = structpb.NewStringValue("") - } - if _, ok := got.Item.Attributes.Fields["callback_url"]; ok { - exp := tc.res.Item.Attributes.Fields["callback_url"].GetStringValue() - gVal := got.Item.Attributes.Fields["callback_url"].GetStringValue() + // Ignore all values which are hard to compare against. + cmpOptions = append( + cmpOptions, + protocmp.IgnoreFields(&pb.AuthMethod{}, "updated_time"), + protocmp.IgnoreFields(&pb.OidcAuthMethodAttributes{}, "client_secret_hmac", "callback_url"), + ) + assert.NotEqual("secret", got.Item.GetOidcAuthMethodsAttributes().GetClientSecretHmac()) + if got.Item.GetOidcAuthMethodsAttributes().CallbackUrl != "" { + exp := tc.res.Item.GetOidcAuthMethodsAttributes().GetCallbackUrl() + gVal := got.Item.GetOidcAuthMethodsAttributes().GetCallbackUrl() matches, err := regexp.MatchString(exp, gVal) require.NoError(err) assert.True(matches, "%q doesn't match %q", gVal, exp) - delete(got.Item.Attributes.Fields, "callback_url") - delete(tc.res.Item.Attributes.Fields, "callback_url") } - got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil - assert.EqualValues(3, got.Item.Version) tc.res.Item.Version = 3 + } - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.SortRepeatedFields(got)), "UpdateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) + assert.Empty(cmp.Diff(got, tc.res, cmpOptions...), "UpdateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) }) } } @@ -1179,22 +1100,18 @@ func TestUpdate_OIDCDryRun(t *testing.T) { Type: oidc.Subtype.String(), AuthorizedActions: oidcAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "api_url_prefix": structpb.NewStringValue(am.GetApiUrl()), - "callback_url": structpb.NewStringValue(fmt.Sprintf("%s/v1/auth-methods/oidc:authenticate:callback", am.GetApiUrl())), - "client_id": structpb.NewStringValue(am.GetClientId()), - "client_secret_hmac": structpb.NewStringValue(am.GetClientSecretHmac()), - "issuer": structpb.NewStringValue(am.GetIssuer()), - "state": structpb.NewStringValue(am.GetOperationalState()), - "idp_ca_certs": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{tp.CACert()}) - return structpb.NewListValue(lv) - }(), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(tpAlg)}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + ApiUrlPrefix: wrapperspb.String(am.GetApiUrl()), + CallbackUrl: fmt.Sprintf("%s/v1/auth-methods/oidc:authenticate:callback", am.GetApiUrl()), + ClientId: wrapperspb.String(am.GetClientId()), + ClientSecretHmac: am.GetClientSecretHmac(), + Issuer: wrapperspb.String(am.GetIssuer()), + State: am.GetOperationalState(), + IdpCaCerts: []string{tp.CACert()}, + SigningAlgorithms: []string{string(tpAlg)}, + }, + }, } tested, err := authmethods.NewService(kmsCache, pwRepoFn, oidcRepoFn, iamRepoFn, atRepoFn) @@ -1216,15 +1133,17 @@ func TestUpdate_OIDCDryRun(t *testing.T) { Name: wrapperspb.String("updated"), Description: wrapperspb.String("updated"), Version: am.GetVersion(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "dry_run": structpb.NewBoolValue(true), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + DryRun: true, + }, + }, }, want: func() *pb.AuthMethod { c := proto.Clone(wireAuthMethod).(*pb.AuthMethod) c.Name = wrapperspb.String("updated") c.Description = wrapperspb.String("updated") - c.GetAttributes().GetFields()["dry_run"] = structpb.NewBoolValue(true) + c.GetOidcAuthMethodsAttributes().DryRun = true return c }(), }, @@ -1234,9 +1153,11 @@ func TestUpdate_OIDCDryRun(t *testing.T) { mask: []string{"attributes.issuer"}, item: &pb.AuthMethod{ Version: am.GetVersion(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "dry_run": structpb.NewBoolValue(true), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + DryRun: true, + }, + }, }, wantErr: true, }, @@ -1246,13 +1167,12 @@ func TestUpdate_OIDCDryRun(t *testing.T) { mask: []string{"attributes.signing_algorithms"}, item: &pb.AuthMethod{ Version: am.GetVersion(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "dry_run": structpb.NewBoolValue(true), - "signing_algorithms": func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.RS512)}) - return structpb.NewListValue(lv) - }(), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + DryRun: true, + SigningAlgorithms: []string{string(oidc.RS512)}, + }, + }, }, wantErr: true, }, @@ -1262,10 +1182,12 @@ func TestUpdate_OIDCDryRun(t *testing.T) { mask: []string{"name"}, item: &pb.AuthMethod{ Version: am.GetVersion(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "dry_run": structpb.NewBoolValue(true), - "disable_discovered_config_validation": structpb.NewBoolValue(true), - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + DryRun: true, + DisableDiscoveredConfigValidation: true, + }, + }, }, wantErr: true, }, @@ -1341,34 +1263,24 @@ func TestChangeState_OIDC(t *testing.T) { s, err := authmethods.NewService(kmsCache, pwRepoFn, oidcRepoFn, iamRepoFn, atRepoFn) require.NoError(t, err, "Error when getting new auth_method service.") - signingAlg := func() *structpb.Value { - lv, err := structpb.NewList([]interface{}{string(tpAlg)}) - require.NoError(t, err) - return structpb.NewListValue(lv) - }() - - certs := func() *structpb.Value { - lv, err := structpb.NewList([]interface{}{tp.CACert()}) - require.NoError(t, err) - return structpb.NewListValue(lv) - }() - wantTemplate := &pb.AuthMethod{ Id: oidcam.GetPublicId(), ScopeId: oidcam.GetScopeId(), CreatedTime: oidcam.CreateTime.GetTimestamp(), UpdatedTime: oidcam.UpdateTime.GetTimestamp(), Type: oidc.Subtype.String(), - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "issuer": structpb.NewStringValue(oidcam.GetIssuer()), - "client_id": structpb.NewStringValue(tpClientId), - "client_secret_hmac": structpb.NewStringValue(""), - "state": structpb.NewStringValue(string(oidc.InactiveState)), - "callback_url": structpb.NewStringValue("https://example.callback:58/v1/auth-methods/oidc:authenticate:callback"), - "api_url_prefix": structpb.NewStringValue("https://example.callback:58"), - "signing_algorithms": signingAlg, - "idp_ca_certs": certs, - }}, + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + Issuer: wrapperspb.String(oidcam.GetIssuer()), + ClientId: wrapperspb.String(tpClientId), + ClientSecretHmac: "", + State: string(oidc.InactiveState), + CallbackUrl: "https://example.callback:58/v1/auth-methods/oidc:authenticate:callback", + ApiUrlPrefix: wrapperspb.String("https://example.callback:58"), + SigningAlgorithms: []string{string(tpAlg)}, + IdpCaCerts: []string{tp.CACert()}, + }, + }, Version: 1, Scope: &scopepb.ScopeInfo{ Id: o.GetPublicId(), @@ -1379,10 +1291,6 @@ func TestChangeState_OIDC(t *testing.T) { AuthorizedCollectionActions: authorizedCollectionActions, } - toState := func(s string) *structpb.Struct { - return &structpb.Struct{Fields: map[string]*structpb.Value{"state": structpb.NewStringValue(s)}} - } - // These test cases must be run in this order since these tests rely on the correct versions being provided cases := []struct { name string @@ -1392,17 +1300,40 @@ func TestChangeState_OIDC(t *testing.T) { }{ { name: "Password Auth Method", - req: &pbs.ChangeStateRequest{Id: pwam.GetPublicId(), Version: pwam.GetVersion(), Attributes: toState("inactive")}, - err: true, + req: &pbs.ChangeStateRequest{ + Id: pwam.GetPublicId(), + Version: pwam.GetVersion(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "inactive", + }, + }, + }, + err: true, }, { name: "No Version Specified", - req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Attributes: toState("inactive")}, - err: true, + req: &pbs.ChangeStateRequest{ + Id: oidcam.GetPublicId(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "inactive", + }, + }, + }, + err: true, }, { name: "Keep Inactive", - req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: oidcam.GetVersion(), Attributes: toState("inactive")}, + req: &pbs.ChangeStateRequest{ + Id: oidcam.GetPublicId(), + Version: oidcam.GetVersion(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "inactive", + }, + }, + }, res: &pbs.ChangeStateResponse{Item: func() *pb.AuthMethod { am := proto.Clone(wantTemplate).(*pb.AuthMethod) return am @@ -1410,20 +1341,40 @@ func TestChangeState_OIDC(t *testing.T) { }, { name: "Make Incomplete Private", - req: &pbs.ChangeStateRequest{Id: incompleteAm.GetPublicId(), Version: oidcam.GetVersion(), Attributes: toState("active-private")}, - err: true, + req: &pbs.ChangeStateRequest{ + Id: incompleteAm.GetPublicId(), + Version: oidcam.GetVersion(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-private", + }, + }, + }, + err: true, }, { name: "Make Incomplete Public", - req: &pbs.ChangeStateRequest{Id: incompleteAm.GetPublicId(), Version: oidcam.GetVersion(), Attributes: toState("active-public")}, - err: true, + req: &pbs.ChangeStateRequest{ + Id: incompleteAm.GetPublicId(), + Version: oidcam.GetVersion(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-public", + }, + }, + }, + err: true, }, { name: "Mismatched To Public", req: &pbs.ChangeStateRequest{ - Id: mismatchedAM.GetPublicId(), - Version: mismatchedAM.GetVersion(), - Attributes: toState("active-public"), + Id: mismatchedAM.GetPublicId(), + Version: mismatchedAM.GetVersion(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-public", + }, + }, }, err: true, }, @@ -1432,22 +1383,20 @@ func TestChangeState_OIDC(t *testing.T) { req: &pbs.ChangeStateRequest{ Id: mismatchedAM.GetPublicId(), Version: mismatchedAM.GetVersion(), - Attributes: func() *structpb.Struct { - s := toState("active-public") - s.Fields["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - return s - }(), + Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-public", + DisableDiscoveredConfigValidation: true, + }, + }, }, res: &pbs.ChangeStateResponse{Item: func() *pb.AuthMethod { am := proto.Clone(wantTemplate).(*pb.AuthMethod) am.Id = mismatchedAM.PublicId - am.Attributes.Fields["disable_discovered_config_validation"] = structpb.NewBoolValue(true) - am.Attributes.Fields["state"] = structpb.NewStringValue("active-public") - am.Attributes.Fields["client_id"] = structpb.NewStringValue(mismatchedAM.ClientId) - am.Attributes.Fields["signing_algorithms"] = func() *structpb.Value { - lv, _ := structpb.NewList([]interface{}{string(oidc.EdDSA)}) - return structpb.NewListValue(lv) - }() + am.GetOidcAuthMethodsAttributes().DisableDiscoveredConfigValidation = true + am.GetOidcAuthMethodsAttributes().State = "active-public" + am.GetOidcAuthMethodsAttributes().ClientId = wrapperspb.String(mismatchedAM.ClientId) + am.GetOidcAuthMethodsAttributes().SigningAlgorithms = []string{string(oidc.EdDSA)} am.CreatedTime = mismatchedAM.CreateTime.GetTimestamp() am.Version = 2 return am @@ -1455,30 +1404,45 @@ func TestChangeState_OIDC(t *testing.T) { }, { name: "Make Complete Private", - req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: oidcam.GetVersion(), Attributes: toState("active-private")}, + req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: oidcam.GetVersion(), Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-private", + }, + }, + }, res: &pbs.ChangeStateResponse{Item: func() *pb.AuthMethod { am := proto.Clone(wantTemplate).(*pb.AuthMethod) - am.Attributes.Fields["state"] = structpb.NewStringValue("active-private") + am.GetOidcAuthMethodsAttributes().State = "active-private" am.Version = 2 return am }()}, }, { name: "Make Complete Public", - req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: 2, Attributes: toState("active-public")}, + req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: 2, Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "active-public", + }, + }, + }, res: &pbs.ChangeStateResponse{Item: func() *pb.AuthMethod { am := proto.Clone(wantTemplate).(*pb.AuthMethod) - am.Attributes.Fields["state"] = structpb.NewStringValue("active-public") + am.GetOidcAuthMethodsAttributes().State = "active-public" am.Version = 3 return am }()}, }, { name: "Make Complete Inactive", - req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: 3, Attributes: toState("inactive")}, + req: &pbs.ChangeStateRequest{Id: oidcam.GetPublicId(), Version: 3, Attrs: &pbs.ChangeStateRequest_OidcChangeStateAttributes{ + OidcChangeStateAttributes: &pbs.OidcChangeStateAttributes{ + State: "inactive", + }, + }, + }, res: &pbs.ChangeStateResponse{Item: func() *pb.AuthMethod { am := proto.Clone(wantTemplate).(*pb.AuthMethod) - am.Attributes.Fields["state"] = structpb.NewStringValue("inactive") + am.GetOidcAuthMethodsAttributes().State = "inactive" am.Version = 4 return am }()}, @@ -1494,21 +1458,19 @@ func TestChangeState_OIDC(t *testing.T) { return } require.NoError(gErr) - if _, ok := got.Item.Attributes.Fields["client_secret_hmac"]; ok { - got.Item.Attributes.Fields["client_secret_hmac"] = structpb.NewStringValue("") - } - if _, ok := got.Item.Attributes.Fields["callback_url"]; ok { - exp := tc.res.Item.Attributes.Fields["callback_url"].GetStringValue() - gVal := got.Item.Attributes.Fields["callback_url"].GetStringValue() + if got.Item.GetOidcAuthMethodsAttributes().CallbackUrl != "" { + exp := tc.res.Item.GetOidcAuthMethodsAttributes().CallbackUrl + gVal := got.Item.GetOidcAuthMethodsAttributes().CallbackUrl matches, err := regexp.MatchString(exp, gVal) require.NoError(err) assert.True(matches, "%q doesn't match %q", gVal, exp) - delete(got.Item.Attributes.Fields, "callback_url") - delete(tc.res.Item.Attributes.Fields, "callback_url") } got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "ChangeState() got response %q, wanted %q", got, tc.res) + assert.Empty( + cmp.Diff(got, tc.res, protocmp.Transform(), protocmp.IgnoreFields(&pb.OidcAuthMethodAttributes{}, "client_secret_hmac", "callback_url")), + "ChangeState() got response %q, wanted %q", got, tc.res, + ) }) } } diff --git a/internal/servers/controller/handlers/authmethods/password.go b/internal/servers/controller/handlers/authmethods/password.go index e8ba38e2d..fc6824113 100644 --- a/internal/servers/controller/handlers/authmethods/password.go +++ b/internal/servers/controller/handlers/authmethods/password.go @@ -189,11 +189,7 @@ func toStoragePwAuthMethod(scopeId string, item *pb.AuthMethod) (*password.AuthM return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "Unable to build auth method for creation: %v.", err) } - pwAttrs := &pb.PasswordAuthMethodAttributes{} - if err := handlers.StructToProto(item.GetAttributes(), pwAttrs); err != nil { - return nil, handlers.InvalidArgumentErrorf("Error in provided request.", - map[string]string{attributesField: "Attribute fields do not match the expected format."}) - } + pwAttrs := item.GetPasswordAuthMethodAttributes() if pwAttrs.GetMinLoginNameLength() != 0 { u.MinLoginNameLength = pwAttrs.GetMinLoginNameLength() } diff --git a/internal/servers/controller/handlers/authmethods/password_test.go b/internal/servers/controller/handlers/authmethods/password_test.go index b7ac3b6cd..4321ed225 100644 --- a/internal/servers/controller/handlers/authmethods/password_test.go +++ b/internal/servers/controller/handlers/authmethods/password_test.go @@ -100,10 +100,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "new"}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -128,10 +130,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "new"}, Description: &wrapperspb.StringValue{Value: "desc"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -206,10 +210,12 @@ func TestUpdate_Password(t *testing.T) { ScopeId: o.GetPublicId(), Description: &wrapperspb.StringValue{Value: "default"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -233,10 +239,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "updated"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -260,10 +268,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "notignored"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -347,10 +357,12 @@ func TestUpdate_Password(t *testing.T) { Item: &pb.AuthMethod{ Name: &wrapperspb.StringValue{Value: "ignored"}, Description: &wrapperspb.StringValue{Value: "ignored"}, - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_login_name_length": structpb.NewNumberValue(42), - "min_password_length": structpb.NewNumberValue(55555), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinLoginNameLength: 42, + MinPasswordLength: 55555, + }, + }, }, }, res: &pbs.UpdateAuthMethodResponse{ @@ -359,10 +371,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(8), - "min_login_name_length": structpb.NewNumberValue(42), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 8, + MinLoginNameLength: 42, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -378,10 +392,12 @@ func TestUpdate_Password(t *testing.T) { Item: &pb.AuthMethod{ Name: &wrapperspb.StringValue{Value: "ignored"}, Description: &wrapperspb.StringValue{Value: "ignored"}, - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_login_name_length": structpb.NewNumberValue(5555), - "min_password_length": structpb.NewNumberValue(42), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinLoginNameLength: 5555, + MinPasswordLength: 42, + }, + }, }, }, res: &pbs.UpdateAuthMethodResponse{ @@ -390,10 +406,12 @@ func TestUpdate_Password(t *testing.T) { Name: &wrapperspb.StringValue{Value: "default"}, Description: &wrapperspb.StringValue{Value: "default"}, Type: "password", - Attributes: &structpb.Struct{Fields: map[string]*structpb.Value{ - "min_password_length": structpb.NewNumberValue(42), - "min_login_name_length": structpb.NewNumberValue(3), - }}, + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinPasswordLength: 42, + MinLoginNameLength: 3, + }, + }, Scope: defaultScopeInfo, AuthorizedActions: pwAuthorizedActions, AuthorizedCollectionActions: authorizedCollectionActions, @@ -428,6 +446,7 @@ func TestUpdate_Password(t *testing.T) { require.Nil(got) } + cmpOptions := []cmp.Option{protocmp.Transform()} if got != nil { assert.NotNilf(tc.res, "Expected UpdateAuthMethod response to be nil, but was %v", got) @@ -436,13 +455,13 @@ func TestUpdate_Password(t *testing.T) { // Verify it is a auth_method updated after it was created assert.True(gotUpdateTime.After(created), "Updated auth_method should have been updated after it's creation. Was updated %v, which is after %v", gotUpdateTime, created) - // Clear all values which are hard to compare against. - got.Item.UpdatedTime, tc.res.Item.UpdatedTime = nil, nil + // Ignore all values which are hard to compare against. + cmpOptions = append(cmpOptions, protocmp.IgnoreFields(&pb.AuthMethod{}, "updated_time")) assert.EqualValues(2, got.Item.Version) tc.res.Item.Version = 2 } - assert.Empty(cmp.Diff(got, tc.res, protocmp.Transform()), "UpdateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) + assert.Empty(cmp.Diff(got, tc.res, cmpOptions...), "UpdateAuthMethod(%q) got response %q, wanted %q", tc.req, got, tc.res) }) } } diff --git a/internal/tests/api/authmethods/authenticate_test.go b/internal/tests/api/authmethods/authenticate_test.go index 0cc5a1eee..85323a1be 100644 --- a/internal/tests/api/authmethods/authenticate_test.go +++ b/internal/tests/api/authmethods/authenticate_test.go @@ -80,13 +80,15 @@ func TestAuthenticate(t *testing.T) { assert.NotNil(tok) got := tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) + // All attribute fields are classified for now. + // TODO(johanbrandhorst): revert this when classification is done for auth methods reqDetails := tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) - tests_api.AssertRedactedValues(t, reqDetails["attributes"], "password") + tests_api.AssertRedactedValues(t, reqDetails["attributes"], "password", "login_name") respDetails := tests_api.GetEventDetails(t, got, "response") tests_api.AssertRedactedValues(t, respDetails) - tests_api.AssertRedactedValues(t, respDetails["attributes"], "token") + tests_api.AssertRedactedValues(t, respDetails["attributes"], "token", "approximate_last_used_time", "expiration_time", "token_type", "updated_time", "user_id", "account_id", "auth_method_id", "authorized_actions", "created_time", "id") _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls tok, err = methods.Authenticate(tc.Context(), tc.Server().DevPasswordAuthMethodId, "login", map[string]interface{}{"login_name": "user", "password": "bad-pass"}) @@ -96,5 +98,5 @@ func TestAuthenticate(t *testing.T) { reqDetails = tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) - tests_api.AssertRedactedValues(t, reqDetails["attributes"], "password") + tests_api.AssertRedactedValues(t, reqDetails["attributes"], "password", "login_name") } diff --git a/internal/tests/api/authmethods/authmethod_test.go b/internal/tests/api/authmethods/authmethod_test.go index 4936e49c8..1c409141a 100644 --- a/internal/tests/api/authmethods/authmethod_test.go +++ b/internal/tests/api/authmethods/authmethod_test.go @@ -6,6 +6,8 @@ import ( "sync" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/boundary/api" "github.com/hashicorp/boundary/api/authmethods" "github.com/hashicorp/boundary/internal/auth/password" @@ -39,7 +41,7 @@ func TestCrud(t *testing.T) { tcConfig.Eventing = &eventConfig.EventerConfig tc := controller.NewTestController(t, &controller.TestControllerOpts{Config: tcConfig}) - defer tc.Shutdown() + t.Cleanup(tc.Shutdown) client := tc.Client() token := tc.Token() @@ -58,84 +60,175 @@ func TestCrud(t *testing.T) { require.NotNil(eventConfig.AuditEvents) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls - u, err := amClient.Create(tc.Context(), "password", global, + pw, err := amClient.Create(tc.Context(), "password", global, authmethods.WithName("bar")) require.NoError(err) - checkAuthMethod("create", u.Item, "bar", 1) + t.Cleanup(func() { + _, err = amClient.Delete(tc.Context(), pw.Item.Id) + require.NoError(err) + }) + checkAuthMethod("create", pw.Item, "bar", 1) got := tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) reqItem := tests_api.GetEventDetails(t, got, "request")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, reqItem) + tests_api.AssertRedactedValues(t, reqItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, reqItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) respItem := tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - tests_api.AssertRedactedValues(t, respItem["attributes"]) + tests_api.AssertRedactedValues(t, respItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls - u, err = amClient.Read(tc.Context(), u.Item.Id) + pw, err = amClient.Read(tc.Context(), pw.Item.Id) require.NoError(err) - checkAuthMethod("read", u.Item, "bar", 1) + checkAuthMethod("read", pw.Item, "bar", 1) got = tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) tests_api.AssertRedactedValues(t, tests_api.GetEventDetails(t, got, "request")) respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - tests_api.AssertRedactedValues(t, respItem["attributes"]) + tests_api.AssertRedactedValues(t, respItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls - u, err = amClient.Update(tc.Context(), u.Item.Id, u.Item.Version, authmethods.WithName("buz")) + pw, err = amClient.Update(tc.Context(), pw.Item.Id, pw.Item.Version, authmethods.WithName("buz")) require.NoError(err) - checkAuthMethod("update", u.Item, "buz", 2) + checkAuthMethod("update", pw.Item, "buz", 2) got = tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) tests_api.AssertRedactedValues(t, tests_api.GetEventDetails(t, got, "request")["item"].(map[string]interface{})) respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - tests_api.AssertRedactedValues(t, respItem["attributes"]) + tests_api.AssertRedactedValues(t, respItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["PasswordAuthMethodAttributes"]) - u, err = amClient.Update(tc.Context(), u.Item.Id, u.Item.Version, authmethods.DefaultName()) - require.NoError(err) - checkAuthMethod("update", u.Item, "", 3) - - _, err = amClient.Delete(tc.Context(), u.Item.Id) + pw, err = amClient.Update(tc.Context(), pw.Item.Id, pw.Item.Version, authmethods.DefaultName()) require.NoError(err) + checkAuthMethod("update", pw.Item, "", 3) _ = os.WriteFile(eventConfig.AuditEvents.Name(), nil, 0o666) // clean out audit events from previous calls // OIDC auth methods - u, err = amClient.Create(tc.Context(), "oidc", global, + oidc, err := amClient.Create(tc.Context(), "oidc", global, authmethods.WithName("foo"), authmethods.WithOidcAuthMethodApiUrlPrefix("https://api.com"), authmethods.WithOidcAuthMethodIssuer("https://example.com"), authmethods.WithOidcAuthMethodClientSecret("secret"), authmethods.WithOidcAuthMethodClientId("client-id")) require.NoError(err) - checkAuthMethod("create", u.Item, "foo", 1) + t.Cleanup(func() { + _, err = amClient.Delete(tc.Context(), oidc.Item.Id) + require.NoError(err) + }) + checkAuthMethod("create", oidc.Item, "foo", 1) got = tests_api.CloudEventFromFile(t, eventConfig.AuditEvents.Name()) reqItem = tests_api.GetEventDetails(t, got, "request")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, reqItem) - tests_api.AssertRedactedValues(t, reqItem["attributes"], "client_secret") + tests_api.AssertRedactedValues(t, reqItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, reqItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "callback_url", "state", "client_secret_hmac") respItem = tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - tests_api.AssertRedactedValues(t, respItem["attributes"]) + tests_api.AssertRedactedValues(t, respItem["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "state", "client_secret_hmac", "callback_url") - u, err = amClient.Read(tc.Context(), u.Item.Id) + oidc, err = amClient.Read(tc.Context(), oidc.Item.Id) require.NoError(err) - checkAuthMethod("read", u.Item, "foo", 1) + checkAuthMethod("read", oidc.Item, "foo", 1) - u, err = amClient.Update(tc.Context(), u.Item.Id, u.Item.Version, authmethods.WithName("bar")) + oidc, err = amClient.Update(tc.Context(), oidc.Item.Id, oidc.Item.Version, authmethods.WithName("bar")) require.NoError(err) - checkAuthMethod("update", u.Item, "bar", 2) + checkAuthMethod("update", oidc.Item, "bar", 2) - u, err = amClient.Update(tc.Context(), u.Item.Id, u.Item.Version, authmethods.DefaultName()) + oidc, err = amClient.Update(tc.Context(), oidc.Item.Id, oidc.Item.Version, authmethods.DefaultName()) require.NoError(err) - checkAuthMethod("update", u.Item, "", 3) + checkAuthMethod("update", oidc.Item, "", 3) +} - _, err = amClient.Delete(tc.Context(), u.Item.Id) +func TestList(t *testing.T) { + assert, require := assert.New(t), require.New(t) + tcConfig, err := config.DevController() require.NoError(err) + + tc := controller.NewTestController(t, &controller.TestControllerOpts{Config: tcConfig}) + t.Cleanup(tc.Shutdown) + + client := tc.Client() + token := tc.Token() + client.SetToken(token.Token) + amClient := authmethods.NewClient(client) + + result, err := amClient.List(tc.Context(), global) + require.NoError(err) + require.Len(result.Items, 2) + genOIDCAM := result.Items[0] + genPWAM := result.Items[1] + + pwAM, err := amClient.Create(tc.Context(), "password", global, + authmethods.WithName("bar"), + authmethods.WithPasswordAuthMethodMinPasswordLength(10), + ) + require.NoError(err) + t.Cleanup(func() { + _, err = amClient.Delete(tc.Context(), pwAM.Item.Id) + require.NoError(err) + }) + + result, err = amClient.List(tc.Context(), global) + require.NoError(err) + require.Len(result.Items, 3) + assert.Empty(cmp.Diff(genOIDCAM, result.Items[0], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(genPWAM, result.Items[1], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(pwAM.Item, result.Items[2], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + + oidcAM, err := amClient.Create(tc.Context(), "oidc", global, + authmethods.WithName("foo"), + authmethods.WithOidcAuthMethodApiUrlPrefix("https://api.com"), + authmethods.WithOidcAuthMethodIssuer("https://example.com"), + authmethods.WithOidcAuthMethodClientSecret("secret"), + authmethods.WithOidcAuthMethodClientId("client-id")) + require.NoError(err) + t.Cleanup(func() { + _, err = amClient.Delete(tc.Context(), oidcAM.Item.Id) + require.NoError(err) + }) + + result, err = amClient.List(tc.Context(), global) + require.NoError(err) + require.Len(result.Items, 4) + assert.Empty(cmp.Diff(genOIDCAM, result.Items[0], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(oidcAM.Item, result.Items[1], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(genPWAM, result.Items[2], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(pwAM.Item, result.Items[3], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + + result, err = amClient.List(tc.Context(), global, + authmethods.WithFilter(`"/item/attributes/client_id"=="client-id"`)) + require.NoError(err) + require.Len(result.Items, 1) + assert.Empty(cmp.Diff(oidcAM.Item, result.Items[0], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + + result, err = amClient.List(tc.Context(), global, + authmethods.WithFilter(`"/item/attributes/min_login_name_length"==3`)) + require.NoError(err) + require.Len(result.Items, 2) + assert.Empty(cmp.Diff(genPWAM, result.Items[0], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + assert.Empty(cmp.Diff(pwAM.Item, result.Items[1], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) + + result, err = amClient.List(tc.Context(), global, + authmethods.WithFilter(`"/item/attributes/min_password_length"==10`)) + require.NoError(err) + require.Len(result.Items, 1) + assert.Empty(cmp.Diff(pwAM.Item, result.Items[0], cmpopts.IgnoreUnexported(authmethods.AuthMethod{}))) } func TestCustomMethods(t *testing.T) { @@ -193,11 +286,14 @@ func TestCustomMethods(t *testing.T) { reqDetails := tests_api.GetEventDetails(t, got, "request") tests_api.AssertRedactedValues(t, reqDetails) - tests_api.AssertRedactedValues(t, reqDetails["attributes"]) + tests_api.AssertRedactedValues(t, reqDetails["Attrs"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, reqDetails["Attrs"].(map[string]interface{})["OidcChangeStateAttributes"], "state") respItem := tests_api.GetEventDetails(t, got, "response")["item"].(map[string]interface{}) tests_api.AssertRedactedValues(t, respItem) - tests_api.AssertRedactedValues(t, respItem["attributes"]) + // TODO(johanbrandhorst): Not all of these fields will be redacted eventually + tests_api.AssertRedactedValues(t, respItem["Attrs"].(map[string]interface{})["OidcAuthMethodsAttributes"], "signing_algorithms", "callback_url", "idp_ca_certs", "state", "client_secret_hmac") _, err = amClient.ChangeState(tc.Context(), u.Item.Id, u.Item.Version, "", authmethods.WithOidcAuthMethodDisableDiscoveredConfigValidation(true)) assert.Error(err) diff --git a/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable_test.go b/internal/tests/api/authmethods/classification_test.go similarity index 50% rename from sdk/pbs/controller/api/resources/authmethods/auth_method_taggable_test.go rename to internal/tests/api/authmethods/classification_test.go index aab9f930d..bad427d65 100644 --- a/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable_test.go +++ b/internal/tests/api/authmethods/classification_test.go @@ -1,4 +1,4 @@ -package authmethods +package authmethods_test import ( "context" @@ -7,6 +7,7 @@ import ( "time" "github.com/hashicorp/boundary/sdk/pbs/controller/api" + pb "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/authmethods" "github.com/hashicorp/boundary/sdk/wrapper" "github.com/hashicorp/eventlogger" "github.com/hashicorp/eventlogger/filters/encrypt" @@ -32,29 +33,29 @@ func TestAuthMethod_Tags(t *testing.T) { testEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, - Payload: &AuthMethod{ + Payload: &pb.AuthMethod{ Id: "id", ScopeId: "scope-id", Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "oidc", - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "state": structpb.NewStringValue("public-state"), - "issuer": structpb.NewStringValue("public-issuer"), - "client_id": structpb.NewStringValue("public-client_id"), - "client_secret_hmac": structpb.NewStringValue("public-client_secret_hmac"), - "max_age": structpb.NewStringValue("public-max_age"), - "signing_algorithms": structpb.NewStringValue("public-signing_algorithms"), - "idp_ca_certs": structpb.NewStringValue("public-signing_algorithms"), - "api_url_prefix": structpb.NewStringValue("public-api_url_prefix"), - "callback_url": structpb.NewStringValue("public-callback_url"), - "allowed_audiences": structpb.NewStringValue("public-allowed_audiences"), - "claims_scopes": structpb.NewStringValue("public-claims_scopes"), - "account_claim_maps": structpb.NewStringValue("public-account_claim_maps"), - "disable_discovered_config_validation": structpb.NewStringValue("public-disable_discovered_config_validation"), - "dry_run": structpb.NewStringValue("public-dry_run"), - "client_secret": structpb.NewStringValue("secret-client_secret"), + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + State: "public-state", + Issuer: wrapperspb.String("public-issuer"), + ClientId: wrapperspb.String("public-client_id"), + ClientSecretHmac: "public-client_secret_hmac", + MaxAge: wrapperspb.UInt32(100), + SigningAlgorithms: []string{"public-signing_algorithms"}, + IdpCaCerts: []string{"public-idp_ca_certs"}, + ApiUrlPrefix: wrapperspb.String("public-api_url_prefix"), + CallbackUrl: "public-callback_url", + AllowedAudiences: []string{"public-allowed_audiences"}, + ClaimsScopes: []string{"public-claims_scopes"}, + AccountClaimMaps: []string{"public-account_claim_maps"}, + DisableDiscoveredConfigValidation: false, + DryRun: false, + ClientSecret: wrapperspb.String("secret-client_secret"), }, }, AuthorizedActions: []string{"action-1", "action-2"}, @@ -71,29 +72,30 @@ func TestAuthMethod_Tags(t *testing.T) { wantEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, - Payload: &AuthMethod{ + Payload: &pb.AuthMethod{ Id: "id", ScopeId: "scope-id", Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "oidc", - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "state": structpb.NewStringValue("public-state"), - "issuer": structpb.NewStringValue("public-issuer"), - "client_id": structpb.NewStringValue("public-client_id"), - "client_secret_hmac": structpb.NewStringValue("public-client_secret_hmac"), - "max_age": structpb.NewStringValue("public-max_age"), - "signing_algorithms": structpb.NewStringValue("public-signing_algorithms"), - "idp_ca_certs": structpb.NewStringValue("public-signing_algorithms"), - "api_url_prefix": structpb.NewStringValue("public-api_url_prefix"), - "callback_url": structpb.NewStringValue("public-callback_url"), - "allowed_audiences": structpb.NewStringValue("public-allowed_audiences"), - "claims_scopes": structpb.NewStringValue("public-claims_scopes"), - "account_claim_maps": structpb.NewStringValue("public-account_claim_maps"), - "disable_discovered_config_validation": structpb.NewStringValue("public-disable_discovered_config_validation"), - "dry_run": structpb.NewStringValue("public-dry_run"), - "client_secret": structpb.NewStringValue(encrypt.RedactedData), + // TODO(johanbrandhorst): update redaction once typed attributes are available + Attrs: &pb.AuthMethod_OidcAuthMethodsAttributes{ + OidcAuthMethodsAttributes: &pb.OidcAuthMethodAttributes{ + State: encrypt.RedactedData, + Issuer: wrapperspb.String(encrypt.RedactedData), + ClientId: wrapperspb.String(encrypt.RedactedData), + ClientSecretHmac: encrypt.RedactedData, + MaxAge: wrapperspb.UInt32(100), + SigningAlgorithms: []string{encrypt.RedactedData}, + IdpCaCerts: []string{encrypt.RedactedData}, + ApiUrlPrefix: wrapperspb.String(encrypt.RedactedData), + CallbackUrl: encrypt.RedactedData, + AllowedAudiences: []string{encrypt.RedactedData}, + ClaimsScopes: []string{encrypt.RedactedData}, + AccountClaimMaps: []string{encrypt.RedactedData}, + DisableDiscoveredConfigValidation: false, + DryRun: false, + ClientSecret: wrapperspb.String(encrypt.RedactedData), }, }, AuthorizedActions: []string{"action-1", "action-2"}, @@ -113,16 +115,16 @@ func TestAuthMethod_Tags(t *testing.T) { testEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, - Payload: &AuthMethod{ + Payload: &pb.AuthMethod{ Id: "id", ScopeId: "scope-id", Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "password", - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "min_login_name_length": structpb.NewStringValue("public-min_login_name_length"), - "min_password_length": structpb.NewStringValue("public-min_password_length"), + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinLoginNameLength: 100, + MinPasswordLength: 100, }, }, AuthorizedActions: []string{"action-1", "action-2"}, @@ -139,16 +141,17 @@ func TestAuthMethod_Tags(t *testing.T) { wantEvent: &eventlogger.Event{ Type: "test", CreatedAt: now, - Payload: &AuthMethod{ + Payload: &pb.AuthMethod{ Id: "id", ScopeId: "scope-id", Name: &wrapperspb.StringValue{Value: "name"}, Description: &wrapperspb.StringValue{Value: "description"}, Type: "password", - Attributes: &structpb.Struct{ - Fields: map[string]*structpb.Value{ - "min_login_name_length": structpb.NewStringValue("public-min_login_name_length"), - "min_password_length": structpb.NewStringValue("public-min_password_length"), + // TODO(johanbrandhorst): update redaction once typed attributes are available + Attrs: &pb.AuthMethod_PasswordAuthMethodAttributes{ + PasswordAuthMethodAttributes: &pb.PasswordAuthMethodAttributes{ + MinLoginNameLength: 100, + MinPasswordLength: 100, }, }, AuthorizedActions: []string{"action-1", "action-2"}, diff --git a/internal/gen/controller/api/services/auth_method_service_taggable_test.go b/internal/tests/api/authmethods/service_classification_test.go similarity index 73% rename from internal/gen/controller/api/services/auth_method_service_taggable_test.go rename to internal/tests/api/authmethods/service_classification_test.go index acd086e32..87b2d2253 100644 --- a/internal/gen/controller/api/services/auth_method_service_taggable_test.go +++ b/internal/tests/api/authmethods/service_classification_test.go @@ -1,4 +1,4 @@ -package services_test +package authmethods_test import ( "context" @@ -65,23 +65,24 @@ func TestAuthenticate_Tags(t *testing.T) { CreatedAt: now, Payload: &services.AuthenticateResponse{ Command: "public-command", + // TODO(johanbrandhorst): update redaction once typed attributes are available Attributes: &structpb.Struct{ Fields: map[string]*structpb.Value{ - "account_id": structpb.NewStringValue("public-account_id"), - "approximate_last_used_time": structpb.NewStringValue("public-approximate_last_used_time"), - "auth_method_id": structpb.NewStringValue("public-auth_method_id"), - "authorized_actions": structpb.NewStringValue("public-authorized_actions"), - "created_time": structpb.NewStringValue("public-created_time"), - "expiration_time": structpb.NewStringValue("public-expiration_time"), - "id": structpb.NewStringValue("public-id"), - "scope": structpb.NewStringValue("public-scope"), - "type": structpb.NewStringValue("public-type"), - "updated_time": structpb.NewStringValue("public-updated_time"), - "user_id": structpb.NewStringValue("public-user_id"), - "status": structpb.NewStringValue("public-status"), - "auth_url": structpb.NewStringValue("public-auth_url"), - "token_id": structpb.NewStringValue("public-token_id"), - "final_redirect_url": structpb.NewStringValue("public-final_redirect_url"), + "account_id": structpb.NewStringValue(encrypt.RedactedData), + "approximate_last_used_time": structpb.NewStringValue(encrypt.RedactedData), + "auth_method_id": structpb.NewStringValue(encrypt.RedactedData), + "authorized_actions": structpb.NewStringValue(encrypt.RedactedData), + "created_time": structpb.NewStringValue(encrypt.RedactedData), + "expiration_time": structpb.NewStringValue(encrypt.RedactedData), + "id": structpb.NewStringValue(encrypt.RedactedData), + "scope": structpb.NewStringValue(encrypt.RedactedData), + "type": structpb.NewStringValue(encrypt.RedactedData), + "updated_time": structpb.NewStringValue(encrypt.RedactedData), + "user_id": structpb.NewStringValue(encrypt.RedactedData), + "status": structpb.NewStringValue(encrypt.RedactedData), + "auth_url": structpb.NewStringValue(encrypt.RedactedData), + "token_id": structpb.NewStringValue(encrypt.RedactedData), + "final_redirect_url": structpb.NewStringValue(encrypt.RedactedData), "token": structpb.NewStringValue(encrypt.RedactedData), }, }, @@ -116,12 +117,13 @@ func TestAuthenticate_Tags(t *testing.T) { AuthMethodId: "public-auth-method-id", TokenType: "public-token-type", Command: "public-command", + // TODO(johanbrandhorst): update redaction once typed attributes are available Attributes: &structpb.Struct{ Fields: map[string]*structpb.Value{ - "login_name": structpb.NewStringValue("public-login_name"), - "auth_url": structpb.NewStringValue("public-auth_url"), - "token_id": structpb.NewStringValue("public-token_id"), - "state": structpb.NewStringValue("public-state"), + "login_name": structpb.NewStringValue(encrypt.RedactedData), + "auth_url": structpb.NewStringValue(encrypt.RedactedData), + "token_id": structpb.NewStringValue(encrypt.RedactedData), + "state": structpb.NewStringValue(encrypt.RedactedData), "password": structpb.NewStringValue(encrypt.RedactedData), "code": structpb.NewStringValue(encrypt.RedactedData), }, diff --git a/internal/types/subtypes/interceptor.go b/internal/types/subtypes/interceptor.go index ea4b1aad8..9fe7e8bae 100644 --- a/internal/types/subtypes/interceptor.go +++ b/internal/types/subtypes/interceptor.go @@ -295,14 +295,13 @@ func AttributeTransformerInterceptor(_ context.Context) grpc.UnaryServerIntercep } res, handlerErr := handler(interceptorCtx, req) - newRes := res if res, ok := res.(proto.Message); ok { - newRes, err = transformResponseAttributes(res) + res, err = transformResponseAttributes(res) if err != nil { return nil, handlers.ApiErrorWithCodeAndMessage(codes.Internal, "failed building attribute struct: %v", err) } } - return newRes, handlerErr + return res, handlerErr } } diff --git a/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go b/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go index a506c71f6..670625e6f 100644 --- a/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go +++ b/sdk/pbs/controller/api/resources/authmethods/auth_method.pb.go @@ -9,6 +9,7 @@ package authmethods import ( scopes "github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/scopes" _ "github.com/hashicorp/boundary/sdk/pbs/controller/protooptions" + _ "google.golang.org/genproto/googleapis/api/visibility" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" structpb "google.golang.org/protobuf/types/known/structpb" @@ -50,15 +51,18 @@ type AuthMethod struct { Version uint32 `protobuf:"varint,80,opt,name=version,proto3" json:"version,omitempty" class:"public"` // @gotags: `class:"public"` // The Auth Method type. Type string `protobuf:"bytes,90,opt,name=type,proto3" json:"type,omitempty" class:"public"` // @gotags: `class:"public"` - // The attributes that are applicable for the specific Auth Method type. - Attributes *structpb.Struct `protobuf:"bytes,100,opt,name=attributes,proto3" json:"attributes,omitempty"` + // Types that are assignable to Attrs: + // *AuthMethod_Attributes + // *AuthMethod_PasswordAuthMethodAttributes + // *AuthMethod_OidcAuthMethodsAttributes + Attrs isAuthMethod_Attrs `protobuf_oneof:"attrs"` // Output only. Whether this auth method is the primary auth method for it's scope. // To change this value update the primary_auth_method_id field on the scope. IsPrimary bool `protobuf:"varint,110,opt,name=is_primary,proto3" json:"is_primary,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The available actions on this resource for this user. AuthorizedActions []string `protobuf:"bytes,300,rep,name=authorized_actions,proto3" json:"authorized_actions,omitempty" class:"public"` // @gotags: `class:"public"` // Output only. The authorized actions for the scope's collections. - AuthorizedCollectionActions map[string]*structpb.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + AuthorizedCollectionActions map[string]*structpb.ListValue `protobuf:"bytes,310,rep,name=authorized_collection_actions,proto3" json:"authorized_collection_actions,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // classified as public via taggable implementation } func (x *AuthMethod) Reset() { @@ -156,13 +160,34 @@ func (x *AuthMethod) GetType() string { return "" } +func (m *AuthMethod) GetAttrs() isAuthMethod_Attrs { + if m != nil { + return m.Attrs + } + return nil +} + func (x *AuthMethod) GetAttributes() *structpb.Struct { - if x != nil { + if x, ok := x.GetAttrs().(*AuthMethod_Attributes); ok { return x.Attributes } return nil } +func (x *AuthMethod) GetPasswordAuthMethodAttributes() *PasswordAuthMethodAttributes { + if x, ok := x.GetAttrs().(*AuthMethod_PasswordAuthMethodAttributes); ok { + return x.PasswordAuthMethodAttributes + } + return nil +} + +func (x *AuthMethod) GetOidcAuthMethodsAttributes() *OidcAuthMethodAttributes { + if x, ok := x.GetAttrs().(*AuthMethod_OidcAuthMethodsAttributes); ok { + return x.OidcAuthMethodsAttributes + } + return nil +} + func (x *AuthMethod) GetIsPrimary() bool { if x != nil { return x.IsPrimary @@ -184,6 +209,29 @@ func (x *AuthMethod) GetAuthorizedCollectionActions() map[string]*structpb.ListV return nil } +type isAuthMethod_Attrs interface { + isAuthMethod_Attrs() +} + +type AuthMethod_Attributes struct { + // The attributes that are applicable for the specific Auth Method type. + Attributes *structpb.Struct `protobuf:"bytes,100,opt,name=attributes,proto3,oneof"` +} + +type AuthMethod_PasswordAuthMethodAttributes struct { + PasswordAuthMethodAttributes *PasswordAuthMethodAttributes `protobuf:"bytes,101,opt,name=password_auth_method_attributes,json=passwordAuthMethodAttributes,proto3,oneof"` +} + +type AuthMethod_OidcAuthMethodsAttributes struct { + OidcAuthMethodsAttributes *OidcAuthMethodAttributes `protobuf:"bytes,102,opt,name=oidc_auth_methods_attributes,json=oidcAuthMethodsAttributes,proto3,oneof"` +} + +func (*AuthMethod_Attributes) isAuthMethod_Attrs() {} + +func (*AuthMethod_PasswordAuthMethodAttributes) isAuthMethod_Attrs() {} + +func (*AuthMethod_OidcAuthMethodsAttributes) isAuthMethod_Attrs() {} + // The attributes of a password typed auth method. type PasswordAuthMethodAttributes struct { state protoimpl.MessageState @@ -750,201 +798,226 @@ var file_controller_api_resources_authmethods_v1_auth_method_proto_rawDesc = []b 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x2e, 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, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, - 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, - 0x31, 0x2f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xf1, 0x06, 0x0a, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, - 0x0a, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, - 0x6f, 0x70, 0x65, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, - 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x63, 0x6f, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, - 0x46, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, - 0x01, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x4e, 0x61, 0x6d, - 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, - 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x0b, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x5a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x61, 0x74, 0x74, - 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x0a, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x70, - 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, - 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 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, 0x12, 0x9b, 0x01, 0x0a, 0x1d, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x54, 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, 0x61, 0x75, - 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, - 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, - 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, - 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x83, 0x02, 0x0a, 0x1c, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x12, 0x74, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, - 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0d, 0x42, 0x3e, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x36, 0x0a, 0x20, 0x61, - 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, - 0x12, 0x4d, 0x69, 0x6e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x65, 0x6e, - 0x67, 0x74, 0x68, 0x52, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x6d, 0x0a, 0x13, 0x6d, 0x69, - 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x3b, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, - 0x33, 0x0a, 0x1e, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, - 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, - 0x68, 0x12, 0x11, 0x4d, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, - 0x6e, 0x67, 0x74, 0x68, 0x52, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, - 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0xe6, 0x09, 0x0a, 0x18, 0x4f, 0x69, - 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, - 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, - 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59, 0x0a, 0x06, - 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x23, 0xa0, 0xda, 0x29, 0x01, - 0xc2, 0xdd, 0x29, 0x1b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, - 0x2e, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x52, - 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, 0x72, 0x12, 0x64, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x2e, 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, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x1a, 0x2a, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x63, 0x75, 0x73, + 0x74, 0x6f, 0x6d, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdf, 0x09, 0x0a, + 0x0a, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, + 0x63, 0x6f, 0x70, 0x65, 0x5f, 0x69, 0x64, 0x12, 0x43, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, + 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, + 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x2e, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x63, 0x6f, 0x70, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x12, 0x46, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x28, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, - 0x29, 0x20, 0x0a, 0x14, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x52, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x74, 0x0a, - 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x28, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x42, 0x30, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x28, 0x0a, 0x18, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x52, 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, - 0x72, 0x65, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, - 0x63, 0x72, 0x65, 0x74, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x68, - 0x6d, 0x61, 0x63, 0x12, 0x5c, 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x3c, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x42, 0x24, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1c, 0x0a, 0x12, 0x61, 0x74, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, - 0x12, 0x06, 0x4d, 0x61, 0x78, 0x41, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, - 0x65, 0x12, 0x64, 0x0a, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x18, 0x46, 0x20, 0x03, 0x28, 0x09, 0x42, 0x34, 0xa0, - 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x2c, 0x0a, 0x1d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x2e, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, - 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x12, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, - 0x6c, 0x67, 0x73, 0x52, 0x12, 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, - 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x73, 0x12, 0x71, 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x75, - 0x72, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x14, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, + 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x22, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, + 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x4a, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x18, 0x64, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x75, 0x63, 0x74, 0x42, 0x0f, 0xa0, 0xda, 0x29, 0x01, 0x9a, 0xe3, 0x29, 0x07, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6c, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, + 0x65, 0x73, 0x12, 0xb0, 0x01, 0x0a, 0x1f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, + 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x65, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x45, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, + 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x42, 0x20, 0xa0, 0xda, 0x29, 0x01, 0x9a, 0xe3, 0x29, 0x08, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0xfa, 0xd2, 0xe4, 0x93, 0x02, 0x0a, 0x12, 0x08, 0x49, 0x4e, 0x54, + 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x48, 0x00, 0x52, 0x1c, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0xa2, 0x01, 0x0a, 0x1c, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x5f, 0x61, 0x74, 0x74, 0x72, + 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x66, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, + 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x42, + 0x1c, 0xa0, 0xda, 0x29, 0x01, 0x9a, 0xe3, 0x29, 0x04, 0x6f, 0x69, 0x64, 0x63, 0xfa, 0xd2, 0xe4, + 0x93, 0x02, 0x0a, 0x12, 0x08, 0x49, 0x4e, 0x54, 0x45, 0x52, 0x4e, 0x41, 0x4c, 0x48, 0x00, 0x52, + 0x19, 0x6f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, + 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x73, + 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x18, 0x6e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, + 0x69, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 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, 0x12, 0x9b, 0x01, 0x0a, 0x1d, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0xb6, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x54, 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, + 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x1d, 0x61, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x6a, 0x0a, 0x20, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x07, 0x0a, 0x05, 0x61, 0x74, 0x74, 0x72, 0x73, 0x22, 0x83, + 0x02, 0x0a, 0x1c, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x41, 0x75, 0x74, 0x68, 0x4d, + 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, + 0x74, 0x0a, 0x15, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x42, 0x3e, + 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x36, 0x0a, 0x20, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, + 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x12, 0x4d, 0x69, 0x6e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, 0x15, + 0x6d, 0x69, 0x6e, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x6c, + 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x6d, 0x0a, 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x14, 0x20, 0x01, + 0x28, 0x0d, 0x42, 0x3b, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x33, 0x0a, 0x1e, 0x61, 0x74, + 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x12, 0x11, 0x4d, 0x69, + 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x52, + 0x13, 0x6d, 0x69, 0x6e, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x5f, 0x6c, 0x65, + 0x6e, 0x67, 0x74, 0x68, 0x22, 0xe6, 0x09, 0x0a, 0x18, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, + 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, + 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x59, 0x0a, 0x06, 0x69, 0x73, 0x73, 0x75, 0x65, + 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x23, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1b, 0x0a, + 0x11, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x73, 0x73, 0x75, + 0x65, 0x72, 0x12, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, 0x72, 0x52, 0x06, 0x69, 0x73, 0x73, 0x75, + 0x65, 0x72, 0x12, 0x64, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x42, 0x28, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x20, 0x0a, 0x14, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x12, 0x08, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x52, 0x09, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x12, 0x74, 0x0a, 0x0d, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2b, 0xa0, - 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x23, 0x0a, 0x19, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, - 0x74, 0x65, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, - 0x69, 0x78, 0x12, 0x06, 0x41, 0x70, 0x69, 0x55, 0x72, 0x6c, 0x52, 0x0e, 0x61, 0x70, 0x69, 0x5f, - 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x12, 0x53, - 0x0a, 0x0c, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x64, - 0x20, 0x03, 0x28, 0x09, 0x42, 0x2f, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x27, 0x0a, 0x17, - 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x64, 0x70, 0x5f, 0x63, - 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x12, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x73, 0x52, 0x0c, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x65, - 0x72, 0x74, 0x73, 0x12, 0x5f, 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, - 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x18, 0x6e, 0x20, 0x03, 0x28, 0x09, 0x42, 0x31, - 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x29, 0x0a, 0x1c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, - 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x64, - 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x09, 0x41, 0x75, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, - 0x73, 0x52, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x65, - 0x6e, 0x63, 0x65, 0x73, 0x12, 0x56, 0x0a, 0x0d, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x73, - 0x63, 0x6f, 0x70, 0x65, 0x73, 0x18, 0x70, 0x20, 0x03, 0x28, 0x09, 0x42, 0x30, 0xa0, 0xda, 0x29, - 0x01, 0xc2, 0xdd, 0x29, 0x28, 0x0a, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, - 0x73, 0x2e, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, - 0x0c, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x0d, 0x63, - 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, + 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x30, 0xa0, + 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x28, 0x0a, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x12, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x52, + 0x0d, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x2e, + 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, + 0x68, 0x6d, 0x61, 0x63, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x5f, 0x68, 0x6d, 0x61, 0x63, 0x12, 0x5c, + 0x0a, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x24, 0xa0, + 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x1c, 0x0a, 0x12, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, + 0x74, 0x65, 0x73, 0x2e, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x12, 0x06, 0x4d, 0x61, 0x78, + 0x41, 0x67, 0x65, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x5f, 0x61, 0x67, 0x65, 0x12, 0x64, 0x0a, 0x12, + 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x73, 0x18, 0x46, 0x20, 0x03, 0x28, 0x09, 0x42, 0x34, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, + 0x29, 0x2c, 0x0a, 0x1d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x73, + 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, + 0x73, 0x12, 0x0b, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x41, 0x6c, 0x67, 0x73, 0x52, 0x12, + 0x73, 0x69, 0x67, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, + 0x6d, 0x73, 0x12, 0x71, 0x0a, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x72, + 0x65, 0x66, 0x69, 0x78, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x2b, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, + 0x29, 0x23, 0x0a, 0x19, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, + 0x70, 0x69, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x06, 0x41, + 0x70, 0x69, 0x55, 0x72, 0x6c, 0x52, 0x0e, 0x61, 0x70, 0x69, 0x5f, 0x75, 0x72, 0x6c, 0x5f, 0x70, + 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x22, 0x0a, 0x0c, 0x63, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, + 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x61, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x12, 0x53, 0x0a, 0x0c, 0x69, 0x64, 0x70, + 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x18, 0x64, 0x20, 0x03, 0x28, 0x09, 0x42, + 0x2f, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x27, 0x0a, 0x17, 0x61, 0x74, 0x74, 0x72, 0x69, + 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, + 0x74, 0x73, 0x12, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, + 0x52, 0x0c, 0x69, 0x64, 0x70, 0x5f, 0x63, 0x61, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x73, 0x12, 0x5f, + 0x0a, 0x11, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, + 0x63, 0x65, 0x73, 0x18, 0x6e, 0x20, 0x03, 0x28, 0x09, 0x42, 0x31, 0xa0, 0xda, 0x29, 0x01, 0xc2, + 0xdd, 0x29, 0x29, 0x0a, 0x1c, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, + 0x73, 0x12, 0x09, 0x41, 0x75, 0x64, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x52, 0x11, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x56, 0x0a, 0x0d, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, + 0x18, 0x70, 0x20, 0x03, 0x28, 0x09, 0x42, 0x30, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x28, + 0x0a, 0x18, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x63, 0x6c, 0x61, + 0x69, 0x6d, 0x73, 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x0c, 0x43, 0x6c, 0x61, 0x69, + 0x6d, 0x73, 0x53, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x52, 0x0d, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x73, + 0x5f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x18, 0x71, 0x20, + 0x03, 0x28, 0x09, 0x42, 0x39, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, 0x29, 0x31, 0x0a, 0x1d, 0x61, + 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x12, 0x10, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4d, 0x61, 0x70, 0x73, 0x52, 0x12, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6d, 0x61, - 0x70, 0x73, 0x18, 0x71, 0x20, 0x03, 0x28, 0x09, 0x42, 0x39, 0xa0, 0xda, 0x29, 0x01, 0xc2, 0xdd, - 0x29, 0x31, 0x0a, 0x1d, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x2e, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x61, 0x69, 0x6d, 0x5f, 0x6d, 0x61, 0x70, - 0x73, 0x12, 0x10, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6c, 0x61, 0x69, 0x6d, 0x4d, - 0x61, 0x70, 0x73, 0x52, 0x12, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x61, - 0x69, 0x6d, 0x5f, 0x6d, 0x61, 0x70, 0x73, 0x12, 0x58, 0x0a, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x78, 0x20, 0x01, 0x28, 0x08, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x24, 0x64, 0x69, 0x73, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1f, 0x0a, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x82, 0x01, 0x20, - 0x01, 0x28, 0x08, 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, - 0x75, 0x6e, 0x22, 0x61, 0x0a, 0x27, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, - 0x74, 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6b, - 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0xb7, 0x01, 0x0a, 0x29, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, - 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, - 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, - 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x32, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x22, - 0x5c, 0x0a, 0x2a, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, - 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, - 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, - 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, - 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, - 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x44, 0x0a, - 0x26, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x5f, 0x69, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, - 0x5f, 0x69, 0x64, 0x22, 0x41, 0x0a, 0x27, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, - 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x42, 0x58, 0x5a, 0x56, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, - 0x68, 0x6f, 0x64, 0x73, 0x3b, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x73, 0x12, 0x58, 0x0a, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x78, 0x20, 0x01, 0x28, 0x08, + 0x42, 0x04, 0xa0, 0xda, 0x29, 0x01, 0x52, 0x24, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x07, + 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x82, 0x01, 0x20, 0x01, 0x28, 0x08, 0x42, 0x04, + 0xa0, 0xda, 0x29, 0x01, 0x52, 0x07, 0x64, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x22, 0x61, 0x0a, + 0x27, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, + 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x75, 0x74, 0x68, + 0x5f, 0x75, 0x72, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, + 0x22, 0xb7, 0x01, 0x0a, 0x29, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, + 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, + 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, + 0x64, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x14, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2c, + 0x0a, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x32, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x22, 0x5c, 0x0a, 0x2a, 0x4f, 0x69, + 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, + 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x66, 0x69, 0x6e, 0x61, + 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x66, 0x69, 0x6e, 0x61, 0x6c, 0x5f, 0x72, 0x65, 0x64, 0x69, + 0x72, 0x65, 0x63, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x44, 0x0a, 0x26, 0x4f, 0x69, 0x64, 0x63, + 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x22, 0x41, + 0x0a, 0x27, 0x4f, 0x69, 0x64, 0x63, 0x41, 0x75, 0x74, 0x68, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, + 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x42, 0x60, 0x5a, 0x56, 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, 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x3b, + 0x61, 0x75, 0x74, 0x68, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0xa2, 0xe3, 0x29, 0x04, 0x61, + 0x75, 0x74, 0x68, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -984,18 +1057,20 @@ var file_controller_api_resources_authmethods_v1_auth_method_proto_depIdxs = []i 11, // 3: controller.api.resources.authmethods.v1.AuthMethod.created_time:type_name -> google.protobuf.Timestamp 11, // 4: controller.api.resources.authmethods.v1.AuthMethod.updated_time:type_name -> google.protobuf.Timestamp 12, // 5: controller.api.resources.authmethods.v1.AuthMethod.attributes:type_name -> google.protobuf.Struct - 8, // 6: controller.api.resources.authmethods.v1.AuthMethod.authorized_collection_actions:type_name -> controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry - 10, // 7: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.issuer:type_name -> google.protobuf.StringValue - 10, // 8: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.client_id:type_name -> google.protobuf.StringValue - 10, // 9: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.client_secret:type_name -> google.protobuf.StringValue - 13, // 10: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.max_age:type_name -> google.protobuf.UInt32Value - 10, // 11: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.api_url_prefix:type_name -> google.protobuf.StringValue - 14, // 12: controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry.value:type_name -> google.protobuf.ListValue - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 1, // 6: controller.api.resources.authmethods.v1.AuthMethod.password_auth_method_attributes:type_name -> controller.api.resources.authmethods.v1.PasswordAuthMethodAttributes + 2, // 7: controller.api.resources.authmethods.v1.AuthMethod.oidc_auth_methods_attributes:type_name -> controller.api.resources.authmethods.v1.OidcAuthMethodAttributes + 8, // 8: controller.api.resources.authmethods.v1.AuthMethod.authorized_collection_actions:type_name -> controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry + 10, // 9: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.issuer:type_name -> google.protobuf.StringValue + 10, // 10: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.client_id:type_name -> google.protobuf.StringValue + 10, // 11: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.client_secret:type_name -> google.protobuf.StringValue + 13, // 12: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.max_age:type_name -> google.protobuf.UInt32Value + 10, // 13: controller.api.resources.authmethods.v1.OidcAuthMethodAttributes.api_url_prefix:type_name -> google.protobuf.StringValue + 14, // 14: controller.api.resources.authmethods.v1.AuthMethod.AuthorizedCollectionActionsEntry.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 } func init() { file_controller_api_resources_authmethods_v1_auth_method_proto_init() } @@ -1101,6 +1176,11 @@ func file_controller_api_resources_authmethods_v1_auth_method_proto_init() { } } } + file_controller_api_resources_authmethods_v1_auth_method_proto_msgTypes[0].OneofWrappers = []interface{}{ + (*AuthMethod_Attributes)(nil), + (*AuthMethod_PasswordAuthMethodAttributes)(nil), + (*AuthMethod_OidcAuthMethodsAttributes)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable.go b/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable.go index 97ec05b15..6b6b53693 100644 --- a/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable.go +++ b/sdk/pbs/controller/api/resources/authmethods/auth_method_taggable.go @@ -16,87 +16,5 @@ func (req *AuthMethod) Tags() ([]encrypt.PointerTag, error) { Classification: encrypt.PublicClassification, }) } - if req.Attributes != nil { - switch req.Type { - case "oidc": - oidcTags := []encrypt.PointerTag{ - // public fields - { - Pointer: "/Attributes/Fields/state", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/issuer", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/client_id", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/client_secret_hmac", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/max_age", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/signing_algorithms", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/idp_ca_certs", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/api_url_prefix", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/callback_url", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/allowed_audiences", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/claims_scopes", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/account_claim_maps", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/disable_discovered_config_validation", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/dry_run", - Classification: encrypt.PublicClassification, - }, - // secrets - { - Pointer: "/Attributes/Fields/client_secret", - Classification: encrypt.SecretClassification, - }, - } - tags = append(tags, oidcTags...) - case "password": - pwTags := []encrypt.PointerTag{ - { - Pointer: "/Attributes/Fields/min_login_name_length", - Classification: encrypt.PublicClassification, - }, - { - Pointer: "/Attributes/Fields/min_password_length", - Classification: encrypt.PublicClassification, - }, - } - tags = append(tags, pwTags...) - } - } return tags, nil }