From 22b50149df13ac1326d4a8ae551714aa9548324f Mon Sep 17 00:00:00 2001 From: Grzegorz Zdunek Date: Wed, 23 Oct 2024 09:12:33 +0200 Subject: [PATCH] Support hardware keys prompts in Connect (#47652) * Add new protos for hardware key prompts * Implement hardware key prompts on the daemon side * Show prompts in the UI * `PromptHardwareKeyPINAsk` -> `PromptHardwareKeyPIN` * Improve proto docs * `PromptHardwareKeySlotOverwrite` -> `ConfirmHardwareKeySlotOverwrite` * Fix typo * Remove unnecessary `form` * Pass an enum to `AskPIN` instead of the entire message * Remove an invalid restriction of PIN/PUK to numbers only * Improve the copy --- api/utils/keys/cliprompt.go | 6 +- api/utils/keys/yubikey.go | 4 +- api/utils/keys/yubikey_common.go | 13 +- .../lib/teleterm/v1/tshd_events_service.pb.go | 703 +++++++++++++++--- .../v1/tshd_events_service_grpc.pb.go | 168 +++++ .../v1/tshd_events_service_pb.client.ts | 80 +- .../v1/tshd_events_service_pb.grpc-server.ts | 76 ++ .../lib/teleterm/v1/tshd_events_service_pb.ts | 505 +++++++++++++ lib/teleterm/daemon/hardwarekeyprompt.go | 108 +++ lib/teleterm/teleterm.go | 8 +- .../lib/teleterm/v1/tshd_events_service.proto | 66 ++ .../src/services/tshd/interceptors.ts | 2 +- .../teleterm/src/services/tshdEvents/index.ts | 12 + .../teleterm/src/ui/ModalsHost/ModalsHost.tsx | 51 ++ .../ModalsHost/modals/HardwareKeys/AskPin.tsx | 98 +++ .../modals/HardwareKeys/ChangePin.tsx | 257 +++++++ .../modals/HardwareKeys/CommonHeader.tsx | 46 ++ .../modals/HardwareKeys/OverwriteSlot.tsx | 68 ++ .../ModalsHost/modals/HardwareKeys/Touch.tsx | 63 ++ .../modals/HardwareKeys/index.story.tsx | 93 +++ .../ModalsHost/modals/HardwareKeys/index.ts | 22 + .../src/ui/services/modals/modalsService.ts | 31 + web/packages/teleterm/src/ui/tshdEvents.ts | 132 ++++ 23 files changed, 2498 insertions(+), 114 deletions(-) create mode 100644 lib/teleterm/daemon/hardwarekeyprompt.go create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/AskPin.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/ChangePin.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/CommonHeader.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/OverwriteSlot.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/Touch.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.story.tsx create mode 100644 web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.ts diff --git a/api/utils/keys/cliprompt.go b/api/utils/keys/cliprompt.go index 8ac27790efe41..7dce20d211a7c 100644 --- a/api/utils/keys/cliprompt.go +++ b/api/utils/keys/cliprompt.go @@ -29,7 +29,11 @@ import ( type cliPrompt struct{} -func (c *cliPrompt) AskPIN(ctx context.Context, message string) (string, error) { +func (c *cliPrompt) AskPIN(ctx context.Context, requirement PINPromptRequirement) (string, error) { + message := "Enter your YubiKey PIV PIN" + if requirement == PINOptional { + message = "Enter your YubiKey PIV PIN [blank to use default PIN]" + } password, err := prompt.Password(ctx, os.Stderr, prompt.Stdin(), message) return password, trace.Wrap(err) } diff --git a/api/utils/keys/yubikey.go b/api/utils/keys/yubikey.go index 790d9a2a626b4..15e12bfc7e3f6 100644 --- a/api/utils/keys/yubikey.go +++ b/api/utils/keys/yubikey.go @@ -374,7 +374,7 @@ func (y *YubiKeyPrivateKey) sign(ctx context.Context, rand io.Reader, digest []b defer touchPromptDelayTimer.Reset(signTouchPromptDelay) } } - pass, err := y.prompt.AskPIN(ctx, "Enter your YubiKey PIV PIN") + pass, err := y.prompt.AskPIN(ctx, PINRequired) return pass, trace.Wrap(err) } @@ -666,7 +666,7 @@ func (y *YubiKey) SetPIN(oldPin, newPin string) error { // If the user provides the default PIN, they will be prompted to set a // non-default PIN and PUK before continuing. func (y *YubiKey) checkOrSetPIN(ctx context.Context) error { - pin, err := y.prompt.AskPIN(ctx, "Enter your YubiKey PIV PIN [blank to use default PIN]") + pin, err := y.prompt.AskPIN(ctx, PINOptional) if err != nil { return trace.Wrap(err) } diff --git a/api/utils/keys/yubikey_common.go b/api/utils/keys/yubikey_common.go index 78ffd1f86c918..5ed36f814580d 100644 --- a/api/utils/keys/yubikey_common.go +++ b/api/utils/keys/yubikey_common.go @@ -22,7 +22,8 @@ import ( // HardwareKeyPrompt provides methods to interact with a YubiKey hardware key. type HardwareKeyPrompt interface { // AskPIN prompts the user for a PIN. - AskPIN(ctx context.Context, message string) (string, error) + // The requirement tells if the PIN is required or optional. + AskPIN(ctx context.Context, requirement PINPromptRequirement) (string, error) // Touch prompts the user to touch the hardware key. Touch(ctx context.Context) error // ChangePIN asks for a new PIN. @@ -35,6 +36,16 @@ type HardwareKeyPrompt interface { ConfirmSlotOverwrite(ctx context.Context, message string) (bool, error) } +// PINPromptRequirement specifies whether a PIN is required. +type PINPromptRequirement int + +const ( + // PINOptional allows the user to proceed without entering a PIN. + PINOptional PINPromptRequirement = iota + // PINRequired enforces that a PIN must be entered to proceed. + PINRequired +) + // PINAndPUK describes a response returned from HardwareKeyPrompt.ChangePIN. type PINAndPUK struct { // New PIN set by the user. diff --git a/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go b/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go index 4056f12e2433d..d9d0ce6c4cf5b 100644 --- a/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go +++ b/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service.pb.go @@ -742,6 +742,405 @@ func (x *PromptMFAResponse) GetTotpCode() string { return "" } +// Request for PromptHardwareKeyPIN. +type PromptHardwareKeyPINRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RootClusterUri string `protobuf:"bytes,1,opt,name=root_cluster_uri,json=rootClusterUri,proto3" json:"root_cluster_uri,omitempty"` + // Specifies if a PIN is optional, allowing the user to set it up if left empty. + PinOptional bool `protobuf:"varint,2,opt,name=pin_optional,json=pinOptional,proto3" json:"pin_optional,omitempty"` +} + +func (x *PromptHardwareKeyPINRequest) Reset() { + *x = PromptHardwareKeyPINRequest{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyPINRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyPINRequest) ProtoMessage() {} + +func (x *PromptHardwareKeyPINRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyPINRequest.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyPINRequest) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{12} +} + +func (x *PromptHardwareKeyPINRequest) GetRootClusterUri() string { + if x != nil { + return x.RootClusterUri + } + return "" +} + +func (x *PromptHardwareKeyPINRequest) GetPinOptional() bool { + if x != nil { + return x.PinOptional + } + return false +} + +// Response for PromptHardwareKeyPIN. +type PromptHardwareKeyPINResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // pin as inputted by the user in the Electron app. + Pin string `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` +} + +func (x *PromptHardwareKeyPINResponse) Reset() { + *x = PromptHardwareKeyPINResponse{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyPINResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyPINResponse) ProtoMessage() {} + +func (x *PromptHardwareKeyPINResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyPINResponse.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyPINResponse) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{13} +} + +func (x *PromptHardwareKeyPINResponse) GetPin() string { + if x != nil { + return x.Pin + } + return "" +} + +// Request for PromptHardwareKeyTouchRequest. +type PromptHardwareKeyTouchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RootClusterUri string `protobuf:"bytes,1,opt,name=root_cluster_uri,json=rootClusterUri,proto3" json:"root_cluster_uri,omitempty"` +} + +func (x *PromptHardwareKeyTouchRequest) Reset() { + *x = PromptHardwareKeyTouchRequest{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyTouchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyTouchRequest) ProtoMessage() {} + +func (x *PromptHardwareKeyTouchRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyTouchRequest.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyTouchRequest) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{14} +} + +func (x *PromptHardwareKeyTouchRequest) GetRootClusterUri() string { + if x != nil { + return x.RootClusterUri + } + return "" +} + +// Response for PromptHardwareKeyTouch. +type PromptHardwareKeyTouchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PromptHardwareKeyTouchResponse) Reset() { + *x = PromptHardwareKeyTouchResponse{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyTouchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyTouchResponse) ProtoMessage() {} + +func (x *PromptHardwareKeyTouchResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyTouchResponse.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyTouchResponse) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{15} +} + +// Response for PromptHardwareKeyPINChange. +type PromptHardwareKeyPINChangeRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RootClusterUri string `protobuf:"bytes,1,opt,name=root_cluster_uri,json=rootClusterUri,proto3" json:"root_cluster_uri,omitempty"` +} + +func (x *PromptHardwareKeyPINChangeRequest) Reset() { + *x = PromptHardwareKeyPINChangeRequest{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyPINChangeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyPINChangeRequest) ProtoMessage() {} + +func (x *PromptHardwareKeyPINChangeRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyPINChangeRequest.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyPINChangeRequest) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{16} +} + +func (x *PromptHardwareKeyPINChangeRequest) GetRootClusterUri() string { + if x != nil { + return x.RootClusterUri + } + return "" +} + +// Response for PromptHardwareKeyPINChange. +type PromptHardwareKeyPINChangeResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // New pin set by the user. + Pin string `protobuf:"bytes,1,opt,name=pin,proto3" json:"pin,omitempty"` + // PUK is needed to change the PIN. + // This is a new PUK if it has not been changed from the default PUK. + Puk string `protobuf:"bytes,2,opt,name=puk,proto3" json:"puk,omitempty"` + // puk_changed is true if the user changed the default PUK. + PukChanged bool `protobuf:"varint,3,opt,name=puk_changed,json=pukChanged,proto3" json:"puk_changed,omitempty"` +} + +func (x *PromptHardwareKeyPINChangeResponse) Reset() { + *x = PromptHardwareKeyPINChangeResponse{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *PromptHardwareKeyPINChangeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PromptHardwareKeyPINChangeResponse) ProtoMessage() {} + +func (x *PromptHardwareKeyPINChangeResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PromptHardwareKeyPINChangeResponse.ProtoReflect.Descriptor instead. +func (*PromptHardwareKeyPINChangeResponse) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{17} +} + +func (x *PromptHardwareKeyPINChangeResponse) GetPin() string { + if x != nil { + return x.Pin + } + return "" +} + +func (x *PromptHardwareKeyPINChangeResponse) GetPuk() string { + if x != nil { + return x.Puk + } + return "" +} + +func (x *PromptHardwareKeyPINChangeResponse) GetPukChanged() bool { + if x != nil { + return x.PukChanged + } + return false +} + +// Request for ConfirmHardwareKeySlotOverwrite. +type ConfirmHardwareKeySlotOverwriteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + RootClusterUri string `protobuf:"bytes,1,opt,name=root_cluster_uri,json=rootClusterUri,proto3" json:"root_cluster_uri,omitempty"` + // Message to display in the prompt. + Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"` +} + +func (x *ConfirmHardwareKeySlotOverwriteRequest) Reset() { + *x = ConfirmHardwareKeySlotOverwriteRequest{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfirmHardwareKeySlotOverwriteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfirmHardwareKeySlotOverwriteRequest) ProtoMessage() {} + +func (x *ConfirmHardwareKeySlotOverwriteRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfirmHardwareKeySlotOverwriteRequest.ProtoReflect.Descriptor instead. +func (*ConfirmHardwareKeySlotOverwriteRequest) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{18} +} + +func (x *ConfirmHardwareKeySlotOverwriteRequest) GetRootClusterUri() string { + if x != nil { + return x.RootClusterUri + } + return "" +} + +func (x *ConfirmHardwareKeySlotOverwriteRequest) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +// Response for ConfirmHardwareKeySlotOverwrite. +type ConfirmHardwareKeySlotOverwriteResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // If true, the slot will be overridden. + Confirmed bool `protobuf:"varint,1,opt,name=confirmed,proto3" json:"confirmed,omitempty"` +} + +func (x *ConfirmHardwareKeySlotOverwriteResponse) Reset() { + *x = ConfirmHardwareKeySlotOverwriteResponse{} + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ConfirmHardwareKeySlotOverwriteResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ConfirmHardwareKeySlotOverwriteResponse) ProtoMessage() {} + +func (x *ConfirmHardwareKeySlotOverwriteResponse) ProtoReflect() protoreflect.Message { + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ConfirmHardwareKeySlotOverwriteResponse.ProtoReflect.Descriptor instead. +func (*ConfirmHardwareKeySlotOverwriteResponse) Descriptor() ([]byte, []int) { + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{19} +} + +func (x *ConfirmHardwareKeySlotOverwriteResponse) GetConfirmed() bool { + if x != nil { + return x.Confirmed + } + return false +} + // Request for GetUsageReportingSettings. type GetUsageReportingSettingsRequest struct { state protoimpl.MessageState @@ -751,7 +1150,7 @@ type GetUsageReportingSettingsRequest struct { func (x *GetUsageReportingSettingsRequest) Reset() { *x = GetUsageReportingSettingsRequest{} - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[12] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -763,7 +1162,7 @@ func (x *GetUsageReportingSettingsRequest) String() string { func (*GetUsageReportingSettingsRequest) ProtoMessage() {} func (x *GetUsageReportingSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[12] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -776,7 +1175,7 @@ func (x *GetUsageReportingSettingsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUsageReportingSettingsRequest.ProtoReflect.Descriptor instead. func (*GetUsageReportingSettingsRequest) Descriptor() ([]byte, []int) { - return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{12} + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{20} } // Response for GetUsageReportingSettings. @@ -790,7 +1189,7 @@ type GetUsageReportingSettingsResponse struct { func (x *GetUsageReportingSettingsResponse) Reset() { *x = GetUsageReportingSettingsResponse{} - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[13] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -802,7 +1201,7 @@ func (x *GetUsageReportingSettingsResponse) String() string { func (*GetUsageReportingSettingsResponse) ProtoMessage() {} func (x *GetUsageReportingSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[13] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[21] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -815,7 +1214,7 @@ func (x *GetUsageReportingSettingsResponse) ProtoReflect() protoreflect.Message // Deprecated: Use GetUsageReportingSettingsResponse.ProtoReflect.Descriptor instead. func (*GetUsageReportingSettingsResponse) Descriptor() ([]byte, []int) { - return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{13} + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{21} } func (x *GetUsageReportingSettingsResponse) GetUsageReportingSettings() *UsageReportingSettings { @@ -837,7 +1236,7 @@ type UsageReportingSettings struct { func (x *UsageReportingSettings) Reset() { *x = UsageReportingSettings{} - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[14] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -849,7 +1248,7 @@ func (x *UsageReportingSettings) String() string { func (*UsageReportingSettings) ProtoMessage() {} func (x *UsageReportingSettings) ProtoReflect() protoreflect.Message { - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[14] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -862,7 +1261,7 @@ func (x *UsageReportingSettings) ProtoReflect() protoreflect.Message { // Deprecated: Use UsageReportingSettings.ProtoReflect.Descriptor instead. func (*UsageReportingSettings) Descriptor() ([]byte, []int) { - return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{14} + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{22} } func (x *UsageReportingSettings) GetEnabled() bool { @@ -885,7 +1284,7 @@ type ReportUnexpectedVnetShutdownRequest struct { func (x *ReportUnexpectedVnetShutdownRequest) Reset() { *x = ReportUnexpectedVnetShutdownRequest{} - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[15] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -897,7 +1296,7 @@ func (x *ReportUnexpectedVnetShutdownRequest) String() string { func (*ReportUnexpectedVnetShutdownRequest) ProtoMessage() {} func (x *ReportUnexpectedVnetShutdownRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[15] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[23] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -910,7 +1309,7 @@ func (x *ReportUnexpectedVnetShutdownRequest) ProtoReflect() protoreflect.Messag // Deprecated: Use ReportUnexpectedVnetShutdownRequest.ProtoReflect.Descriptor instead. func (*ReportUnexpectedVnetShutdownRequest) Descriptor() ([]byte, []int) { - return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{15} + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{23} } func (x *ReportUnexpectedVnetShutdownRequest) GetError() string { @@ -929,7 +1328,7 @@ type ReportUnexpectedVnetShutdownResponse struct { func (x *ReportUnexpectedVnetShutdownResponse) Reset() { *x = ReportUnexpectedVnetShutdownResponse{} - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[16] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -941,7 +1340,7 @@ func (x *ReportUnexpectedVnetShutdownResponse) String() string { func (*ReportUnexpectedVnetShutdownResponse) ProtoMessage() {} func (x *ReportUnexpectedVnetShutdownResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[16] + mi := &file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -954,7 +1353,7 @@ func (x *ReportUnexpectedVnetShutdownResponse) ProtoReflect() protoreflect.Messa // Deprecated: Use ReportUnexpectedVnetShutdownResponse.ProtoReflect.Descriptor instead. func (*ReportUnexpectedVnetShutdownResponse) Descriptor() ([]byte, []int) { - return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{16} + return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP(), []int{24} } var File_teleport_lib_teleterm_v1_tshd_events_service_proto protoreflect.FileDescriptor @@ -1056,85 +1455,163 @@ var file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDesc = []byte{ 0x5f, 0x75, 0x72, 0x69, 0x22, 0x30, 0x0a, 0x11, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x46, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x6f, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x6f, - 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x22, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x21, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x6a, 0x0a, 0x18, 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x69, 0x6e, 0x67, 0x5f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, - 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, + 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x22, 0x6a, 0x0a, 0x1b, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, + 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x12, + 0x21, 0x0a, 0x0c, 0x70, 0x69, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x70, 0x69, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x61, 0x6c, 0x22, 0x30, 0x0a, 0x1c, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, + 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x70, 0x69, 0x6e, 0x22, 0x49, 0x0a, 0x1d, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, + 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, + 0x20, 0x0a, 0x1e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, + 0x65, 0x4b, 0x65, 0x79, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x4d, 0x0a, 0x21, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, + 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0e, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, + 0x22, 0x69, 0x0a, 0x22, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, + 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x69, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x70, 0x75, 0x6b, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x70, 0x75, 0x6b, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x75, + 0x6b, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0a, 0x70, 0x75, 0x6b, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x22, 0x6c, 0x0a, 0x26, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, + 0x79, 0x53, 0x6c, 0x6f, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x72, 0x6f, 0x6f, 0x74, 0x5f, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0e, 0x72, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x47, 0x0a, 0x27, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x72, 0x6d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x53, + 0x6c, 0x6f, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x65, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x65, 0x64, 0x22, 0x22, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x21, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x52, 0x16, 0x75, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x32, 0x0a, 0x16, - 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x22, 0x3b, 0x0a, 0x23, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x26, 0x0a, - 0x24, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, - 0x64, 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xba, 0x06, 0x0a, 0x11, 0x54, 0x73, 0x68, 0x64, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x73, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x07, 0x52, - 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x6f, - 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x10, 0x53, - 0x65, 0x6e, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, - 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x6e, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xac, 0x01, 0x0a, 0x21, 0x53, 0x65, 0x6e, 0x64, 0x50, - 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x2e, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6a, 0x0a, 0x18, + 0x75, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x52, 0x16, 0x75, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x32, 0x0a, 0x16, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x3b, 0x0a, 0x23, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x26, 0x0a, 0x24, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, + 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x32, 0x93, 0x0b, 0x0a, 0x11, 0x54, 0x73, 0x68, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5e, 0x0a, 0x07, 0x52, 0x65, 0x6c, 0x6f, 0x67, + 0x69, 0x6e, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, + 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x79, 0x0a, 0x10, 0x53, 0x65, 0x6e, 0x64, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x4e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0xac, 0x01, 0x0a, 0x21, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x65, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x42, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, + 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x43, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x6e, 0x64, - 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x64, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4d, - 0x46, 0x41, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, - 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x46, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x64, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x46, 0x41, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, - 0x4d, 0x46, 0x41, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x19, - 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, - 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x4d, 0x46, 0x41, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x4d, 0x46, 0x41, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x85, 0x01, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x6d, + 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, + 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, + 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, + 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x8b, 0x01, 0x0a, 0x16, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, + 0x72, 0x65, 0x4b, 0x65, 0x79, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x12, 0x37, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, + 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x54, 0x6f, 0x75, 0x63, 0x68, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, + 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, + 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, + 0x54, 0x6f, 0x75, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x97, 0x01, + 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, + 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x3b, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, + 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, - 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, - 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x9d, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, - 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, - 0x6f, 0x77, 0x6e, 0x12, 0x3d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, - 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, - 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, - 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, - 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x42, 0x54, 0x5a, 0x52, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x69, - 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x48, 0x61, 0x72, 0x64, 0x77, + 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x50, 0x49, 0x4e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa6, 0x01, 0x0a, 0x1f, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x72, 0x6d, 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x6c, + 0x6f, 0x74, 0x4f, 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x12, 0x40, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x48, 0x61, + 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x6c, 0x6f, 0x74, 0x4f, 0x76, 0x65, + 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x41, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, + 0x48, 0x61, 0x72, 0x64, 0x77, 0x61, 0x72, 0x65, 0x4b, 0x65, 0x79, 0x53, 0x6c, 0x6f, 0x74, 0x4f, + 0x76, 0x65, 0x72, 0x77, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x94, 0x01, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x3a, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9d, 0x01, 0x0a, 0x1c, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, 0x74, + 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x12, 0x3d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, + 0x63, 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x6c, 0x69, 0x62, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2e, + 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x55, 0x6e, 0x65, 0x78, 0x70, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x56, 0x6e, 0x65, 0x74, 0x53, 0x68, 0x75, 0x74, 0x64, 0x6f, 0x77, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x54, 0x5a, 0x52, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x67, 0x65, 0x6e, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, + 0x76, 0x31, 0x3b, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x76, 0x31, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1149,7 +1626,7 @@ func file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescGZIP() []byt return file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDescData } -var file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes = make([]protoimpl.MessageInfo, 17) +var file_teleport_lib_teleterm_v1_tshd_events_service_proto_msgTypes = make([]protoimpl.MessageInfo, 25) var file_teleport_lib_teleterm_v1_tshd_events_service_proto_goTypes = []any{ (*ReloginRequest)(nil), // 0: teleport.lib.teleterm.v1.ReloginRequest (*GatewayCertExpired)(nil), // 1: teleport.lib.teleterm.v1.GatewayCertExpired @@ -1163,32 +1640,48 @@ var file_teleport_lib_teleterm_v1_tshd_events_service_proto_goTypes = []any{ (*SendPendingHeadlessAuthenticationResponse)(nil), // 9: teleport.lib.teleterm.v1.SendPendingHeadlessAuthenticationResponse (*PromptMFARequest)(nil), // 10: teleport.lib.teleterm.v1.PromptMFARequest (*PromptMFAResponse)(nil), // 11: teleport.lib.teleterm.v1.PromptMFAResponse - (*GetUsageReportingSettingsRequest)(nil), // 12: teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest - (*GetUsageReportingSettingsResponse)(nil), // 13: teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse - (*UsageReportingSettings)(nil), // 14: teleport.lib.teleterm.v1.UsageReportingSettings - (*ReportUnexpectedVnetShutdownRequest)(nil), // 15: teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownRequest - (*ReportUnexpectedVnetShutdownResponse)(nil), // 16: teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownResponse + (*PromptHardwareKeyPINRequest)(nil), // 12: teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest + (*PromptHardwareKeyPINResponse)(nil), // 13: teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse + (*PromptHardwareKeyTouchRequest)(nil), // 14: teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest + (*PromptHardwareKeyTouchResponse)(nil), // 15: teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse + (*PromptHardwareKeyPINChangeRequest)(nil), // 16: teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest + (*PromptHardwareKeyPINChangeResponse)(nil), // 17: teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse + (*ConfirmHardwareKeySlotOverwriteRequest)(nil), // 18: teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest + (*ConfirmHardwareKeySlotOverwriteResponse)(nil), // 19: teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse + (*GetUsageReportingSettingsRequest)(nil), // 20: teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest + (*GetUsageReportingSettingsResponse)(nil), // 21: teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse + (*UsageReportingSettings)(nil), // 22: teleport.lib.teleterm.v1.UsageReportingSettings + (*ReportUnexpectedVnetShutdownRequest)(nil), // 23: teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownRequest + (*ReportUnexpectedVnetShutdownResponse)(nil), // 24: teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownResponse } var file_teleport_lib_teleterm_v1_tshd_events_service_proto_depIdxs = []int32{ 1, // 0: teleport.lib.teleterm.v1.ReloginRequest.gateway_cert_expired:type_name -> teleport.lib.teleterm.v1.GatewayCertExpired 2, // 1: teleport.lib.teleterm.v1.ReloginRequest.vnet_cert_expired:type_name -> teleport.lib.teleterm.v1.VnetCertExpired 5, // 2: teleport.lib.teleterm.v1.SendNotificationRequest.cannot_proxy_gateway_connection:type_name -> teleport.lib.teleterm.v1.CannotProxyGatewayConnection 6, // 3: teleport.lib.teleterm.v1.SendNotificationRequest.cannot_proxy_vnet_connection:type_name -> teleport.lib.teleterm.v1.CannotProxyVnetConnection - 14, // 4: teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse.usage_reporting_settings:type_name -> teleport.lib.teleterm.v1.UsageReportingSettings + 22, // 4: teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse.usage_reporting_settings:type_name -> teleport.lib.teleterm.v1.UsageReportingSettings 0, // 5: teleport.lib.teleterm.v1.TshdEventsService.Relogin:input_type -> teleport.lib.teleterm.v1.ReloginRequest 4, // 6: teleport.lib.teleterm.v1.TshdEventsService.SendNotification:input_type -> teleport.lib.teleterm.v1.SendNotificationRequest 8, // 7: teleport.lib.teleterm.v1.TshdEventsService.SendPendingHeadlessAuthentication:input_type -> teleport.lib.teleterm.v1.SendPendingHeadlessAuthenticationRequest 10, // 8: teleport.lib.teleterm.v1.TshdEventsService.PromptMFA:input_type -> teleport.lib.teleterm.v1.PromptMFARequest - 12, // 9: teleport.lib.teleterm.v1.TshdEventsService.GetUsageReportingSettings:input_type -> teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest - 15, // 10: teleport.lib.teleterm.v1.TshdEventsService.ReportUnexpectedVnetShutdown:input_type -> teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownRequest - 3, // 11: teleport.lib.teleterm.v1.TshdEventsService.Relogin:output_type -> teleport.lib.teleterm.v1.ReloginResponse - 7, // 12: teleport.lib.teleterm.v1.TshdEventsService.SendNotification:output_type -> teleport.lib.teleterm.v1.SendNotificationResponse - 9, // 13: teleport.lib.teleterm.v1.TshdEventsService.SendPendingHeadlessAuthentication:output_type -> teleport.lib.teleterm.v1.SendPendingHeadlessAuthenticationResponse - 11, // 14: teleport.lib.teleterm.v1.TshdEventsService.PromptMFA:output_type -> teleport.lib.teleterm.v1.PromptMFAResponse - 13, // 15: teleport.lib.teleterm.v1.TshdEventsService.GetUsageReportingSettings:output_type -> teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse - 16, // 16: teleport.lib.teleterm.v1.TshdEventsService.ReportUnexpectedVnetShutdown:output_type -> teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownResponse - 11, // [11:17] is the sub-list for method output_type - 5, // [5:11] is the sub-list for method input_type + 12, // 9: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyPIN:input_type -> teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest + 14, // 10: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyTouch:input_type -> teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest + 16, // 11: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyPINChange:input_type -> teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest + 18, // 12: teleport.lib.teleterm.v1.TshdEventsService.ConfirmHardwareKeySlotOverwrite:input_type -> teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest + 20, // 13: teleport.lib.teleterm.v1.TshdEventsService.GetUsageReportingSettings:input_type -> teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest + 23, // 14: teleport.lib.teleterm.v1.TshdEventsService.ReportUnexpectedVnetShutdown:input_type -> teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownRequest + 3, // 15: teleport.lib.teleterm.v1.TshdEventsService.Relogin:output_type -> teleport.lib.teleterm.v1.ReloginResponse + 7, // 16: teleport.lib.teleterm.v1.TshdEventsService.SendNotification:output_type -> teleport.lib.teleterm.v1.SendNotificationResponse + 9, // 17: teleport.lib.teleterm.v1.TshdEventsService.SendPendingHeadlessAuthentication:output_type -> teleport.lib.teleterm.v1.SendPendingHeadlessAuthenticationResponse + 11, // 18: teleport.lib.teleterm.v1.TshdEventsService.PromptMFA:output_type -> teleport.lib.teleterm.v1.PromptMFAResponse + 13, // 19: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyPIN:output_type -> teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse + 15, // 20: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyTouch:output_type -> teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse + 17, // 21: teleport.lib.teleterm.v1.TshdEventsService.PromptHardwareKeyPINChange:output_type -> teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse + 19, // 22: teleport.lib.teleterm.v1.TshdEventsService.ConfirmHardwareKeySlotOverwrite:output_type -> teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse + 21, // 23: teleport.lib.teleterm.v1.TshdEventsService.GetUsageReportingSettings:output_type -> teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse + 24, // 24: teleport.lib.teleterm.v1.TshdEventsService.ReportUnexpectedVnetShutdown:output_type -> teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownResponse + 15, // [15:25] is the sub-list for method output_type + 5, // [5:15] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -1213,7 +1706,7 @@ func file_teleport_lib_teleterm_v1_tshd_events_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_lib_teleterm_v1_tshd_events_service_proto_rawDesc, NumEnums: 0, - NumMessages: 17, + NumMessages: 25, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service_grpc.pb.go b/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service_grpc.pb.go index 8ee0b2a271acd..da8f82e67af7e 100644 --- a/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service_grpc.pb.go +++ b/gen/proto/go/teleport/lib/teleterm/v1/tshd_events_service_grpc.pb.go @@ -40,6 +40,10 @@ const ( TshdEventsService_SendNotification_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/SendNotification" TshdEventsService_SendPendingHeadlessAuthentication_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/SendPendingHeadlessAuthentication" TshdEventsService_PromptMFA_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/PromptMFA" + TshdEventsService_PromptHardwareKeyPIN_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyPIN" + TshdEventsService_PromptHardwareKeyTouch_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyTouch" + TshdEventsService_PromptHardwareKeyPINChange_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyPINChange" + TshdEventsService_ConfirmHardwareKeySlotOverwrite_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/ConfirmHardwareKeySlotOverwrite" TshdEventsService_GetUsageReportingSettings_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/GetUsageReportingSettings" TshdEventsService_ReportUnexpectedVnetShutdown_FullMethodName = "/teleport.lib.teleterm.v1.TshdEventsService/ReportUnexpectedVnetShutdown" ) @@ -66,6 +70,18 @@ type TshdEventsServiceClient interface { // If TOTP is supported, tsh daemon expects that the Electron app responds to this RPC with the // code. PromptMFA(ctx context.Context, in *PromptMFARequest, opts ...grpc.CallOption) (*PromptMFAResponse, error) + // PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + // provide the hardware key PIN. + PromptHardwareKeyPIN(ctx context.Context, in *PromptHardwareKeyPINRequest, opts ...grpc.CallOption) (*PromptHardwareKeyPINResponse, error) + // PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + // When the daemon detects the touch, it cancels the prompt. + PromptHardwareKeyTouch(ctx context.Context, in *PromptHardwareKeyTouchRequest, opts ...grpc.CallOption) (*PromptHardwareKeyTouchResponse, error) + // PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + // change the hardware key PIN. + PromptHardwareKeyPINChange(ctx context.Context, in *PromptHardwareKeyPINChangeRequest, opts ...grpc.CallOption) (*PromptHardwareKeyPINChangeResponse, error) + // ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + // the slot's private key and certificate should be overwritten. + ConfirmHardwareKeySlotOverwrite(ctx context.Context, in *ConfirmHardwareKeySlotOverwriteRequest, opts ...grpc.CallOption) (*ConfirmHardwareKeySlotOverwriteResponse, error) // GetUsageReportingSettings returns the current state of usage reporting. // At the moment, the user cannot toggle usage reporting on and off without shutting down the app, // with the only exception being the first start of the app when they're prompted about telemetry. @@ -125,6 +141,46 @@ func (c *tshdEventsServiceClient) PromptMFA(ctx context.Context, in *PromptMFARe return out, nil } +func (c *tshdEventsServiceClient) PromptHardwareKeyPIN(ctx context.Context, in *PromptHardwareKeyPINRequest, opts ...grpc.CallOption) (*PromptHardwareKeyPINResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PromptHardwareKeyPINResponse) + err := c.cc.Invoke(ctx, TshdEventsService_PromptHardwareKeyPIN_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tshdEventsServiceClient) PromptHardwareKeyTouch(ctx context.Context, in *PromptHardwareKeyTouchRequest, opts ...grpc.CallOption) (*PromptHardwareKeyTouchResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PromptHardwareKeyTouchResponse) + err := c.cc.Invoke(ctx, TshdEventsService_PromptHardwareKeyTouch_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tshdEventsServiceClient) PromptHardwareKeyPINChange(ctx context.Context, in *PromptHardwareKeyPINChangeRequest, opts ...grpc.CallOption) (*PromptHardwareKeyPINChangeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(PromptHardwareKeyPINChangeResponse) + err := c.cc.Invoke(ctx, TshdEventsService_PromptHardwareKeyPINChange_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *tshdEventsServiceClient) ConfirmHardwareKeySlotOverwrite(ctx context.Context, in *ConfirmHardwareKeySlotOverwriteRequest, opts ...grpc.CallOption) (*ConfirmHardwareKeySlotOverwriteResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ConfirmHardwareKeySlotOverwriteResponse) + err := c.cc.Invoke(ctx, TshdEventsService_ConfirmHardwareKeySlotOverwrite_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *tshdEventsServiceClient) GetUsageReportingSettings(ctx context.Context, in *GetUsageReportingSettingsRequest, opts ...grpc.CallOption) (*GetUsageReportingSettingsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(GetUsageReportingSettingsResponse) @@ -167,6 +223,18 @@ type TshdEventsServiceServer interface { // If TOTP is supported, tsh daemon expects that the Electron app responds to this RPC with the // code. PromptMFA(context.Context, *PromptMFARequest) (*PromptMFAResponse, error) + // PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + // provide the hardware key PIN. + PromptHardwareKeyPIN(context.Context, *PromptHardwareKeyPINRequest) (*PromptHardwareKeyPINResponse, error) + // PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + // When the daemon detects the touch, it cancels the prompt. + PromptHardwareKeyTouch(context.Context, *PromptHardwareKeyTouchRequest) (*PromptHardwareKeyTouchResponse, error) + // PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + // change the hardware key PIN. + PromptHardwareKeyPINChange(context.Context, *PromptHardwareKeyPINChangeRequest) (*PromptHardwareKeyPINChangeResponse, error) + // ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + // the slot's private key and certificate should be overwritten. + ConfirmHardwareKeySlotOverwrite(context.Context, *ConfirmHardwareKeySlotOverwriteRequest) (*ConfirmHardwareKeySlotOverwriteResponse, error) // GetUsageReportingSettings returns the current state of usage reporting. // At the moment, the user cannot toggle usage reporting on and off without shutting down the app, // with the only exception being the first start of the app when they're prompted about telemetry. @@ -198,6 +266,18 @@ func (UnimplementedTshdEventsServiceServer) SendPendingHeadlessAuthentication(co func (UnimplementedTshdEventsServiceServer) PromptMFA(context.Context, *PromptMFARequest) (*PromptMFAResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method PromptMFA not implemented") } +func (UnimplementedTshdEventsServiceServer) PromptHardwareKeyPIN(context.Context, *PromptHardwareKeyPINRequest) (*PromptHardwareKeyPINResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PromptHardwareKeyPIN not implemented") +} +func (UnimplementedTshdEventsServiceServer) PromptHardwareKeyTouch(context.Context, *PromptHardwareKeyTouchRequest) (*PromptHardwareKeyTouchResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PromptHardwareKeyTouch not implemented") +} +func (UnimplementedTshdEventsServiceServer) PromptHardwareKeyPINChange(context.Context, *PromptHardwareKeyPINChangeRequest) (*PromptHardwareKeyPINChangeResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method PromptHardwareKeyPINChange not implemented") +} +func (UnimplementedTshdEventsServiceServer) ConfirmHardwareKeySlotOverwrite(context.Context, *ConfirmHardwareKeySlotOverwriteRequest) (*ConfirmHardwareKeySlotOverwriteResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ConfirmHardwareKeySlotOverwrite not implemented") +} func (UnimplementedTshdEventsServiceServer) GetUsageReportingSettings(context.Context, *GetUsageReportingSettingsRequest) (*GetUsageReportingSettingsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUsageReportingSettings not implemented") } @@ -297,6 +377,78 @@ func _TshdEventsService_PromptMFA_Handler(srv interface{}, ctx context.Context, return interceptor(ctx, in, info, handler) } +func _TshdEventsService_PromptHardwareKeyPIN_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PromptHardwareKeyPINRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TshdEventsServiceServer).PromptHardwareKeyPIN(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TshdEventsService_PromptHardwareKeyPIN_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TshdEventsServiceServer).PromptHardwareKeyPIN(ctx, req.(*PromptHardwareKeyPINRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TshdEventsService_PromptHardwareKeyTouch_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PromptHardwareKeyTouchRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TshdEventsServiceServer).PromptHardwareKeyTouch(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TshdEventsService_PromptHardwareKeyTouch_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TshdEventsServiceServer).PromptHardwareKeyTouch(ctx, req.(*PromptHardwareKeyTouchRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TshdEventsService_PromptHardwareKeyPINChange_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PromptHardwareKeyPINChangeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TshdEventsServiceServer).PromptHardwareKeyPINChange(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TshdEventsService_PromptHardwareKeyPINChange_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TshdEventsServiceServer).PromptHardwareKeyPINChange(ctx, req.(*PromptHardwareKeyPINChangeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TshdEventsService_ConfirmHardwareKeySlotOverwrite_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ConfirmHardwareKeySlotOverwriteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TshdEventsServiceServer).ConfirmHardwareKeySlotOverwrite(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TshdEventsService_ConfirmHardwareKeySlotOverwrite_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TshdEventsServiceServer).ConfirmHardwareKeySlotOverwrite(ctx, req.(*ConfirmHardwareKeySlotOverwriteRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _TshdEventsService_GetUsageReportingSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(GetUsageReportingSettingsRequest) if err := dec(in); err != nil { @@ -356,6 +508,22 @@ var TshdEventsService_ServiceDesc = grpc.ServiceDesc{ MethodName: "PromptMFA", Handler: _TshdEventsService_PromptMFA_Handler, }, + { + MethodName: "PromptHardwareKeyPIN", + Handler: _TshdEventsService_PromptHardwareKeyPIN_Handler, + }, + { + MethodName: "PromptHardwareKeyTouch", + Handler: _TshdEventsService_PromptHardwareKeyTouch_Handler, + }, + { + MethodName: "PromptHardwareKeyPINChange", + Handler: _TshdEventsService_PromptHardwareKeyPINChange_Handler, + }, + { + MethodName: "ConfirmHardwareKeySlotOverwrite", + Handler: _TshdEventsService_ConfirmHardwareKeySlotOverwrite_Handler, + }, { MethodName: "GetUsageReportingSettings", Handler: _TshdEventsService_GetUsageReportingSettings_Handler, diff --git a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.client.ts b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.client.ts index 762ad049fc740..639353d5e19a7 100644 --- a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.client.ts +++ b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.client.ts @@ -28,6 +28,14 @@ import type { ReportUnexpectedVnetShutdownResponse } from "./tshd_events_service import type { ReportUnexpectedVnetShutdownRequest } from "./tshd_events_service_pb"; import type { GetUsageReportingSettingsResponse } from "./tshd_events_service_pb"; import type { GetUsageReportingSettingsRequest } from "./tshd_events_service_pb"; +import type { ConfirmHardwareKeySlotOverwriteResponse } from "./tshd_events_service_pb"; +import type { ConfirmHardwareKeySlotOverwriteRequest } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyPINChangeResponse } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyPINChangeRequest } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyTouchResponse } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyTouchRequest } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyPINResponse } from "./tshd_events_service_pb"; +import type { PromptHardwareKeyPINRequest } from "./tshd_events_service_pb"; import type { PromptMFAResponse } from "./tshd_events_service_pb"; import type { PromptMFARequest } from "./tshd_events_service_pb"; import type { SendPendingHeadlessAuthenticationResponse } from "./tshd_events_service_pb"; @@ -77,6 +85,34 @@ export interface ITshdEventsServiceClient { * @generated from protobuf rpc: PromptMFA(teleport.lib.teleterm.v1.PromptMFARequest) returns (teleport.lib.teleterm.v1.PromptMFAResponse); */ promptMFA(input: PromptMFARequest, options?: RpcOptions): UnaryCall; + /** + * PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + * provide the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPIN(teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse); + */ + promptHardwareKeyPIN(input: PromptHardwareKeyPINRequest, options?: RpcOptions): UnaryCall; + /** + * PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + * When the daemon detects the touch, it cancels the prompt. + * + * @generated from protobuf rpc: PromptHardwareKeyTouch(teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse); + */ + promptHardwareKeyTouch(input: PromptHardwareKeyTouchRequest, options?: RpcOptions): UnaryCall; + /** + * PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + * change the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPINChange(teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse); + */ + promptHardwareKeyPINChange(input: PromptHardwareKeyPINChangeRequest, options?: RpcOptions): UnaryCall; + /** + * ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + * the slot's private key and certificate should be overwritten. + * + * @generated from protobuf rpc: ConfirmHardwareKeySlotOverwrite(teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest) returns (teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse); + */ + confirmHardwareKeySlotOverwrite(input: ConfirmHardwareKeySlotOverwriteRequest, options?: RpcOptions): UnaryCall; /** * GetUsageReportingSettings returns the current state of usage reporting. * At the moment, the user cannot toggle usage reporting on and off without shutting down the app, @@ -150,6 +186,46 @@ export class TshdEventsServiceClient implements ITshdEventsServiceClient, Servic const method = this.methods[3], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } + /** + * PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + * provide the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPIN(teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse); + */ + promptHardwareKeyPIN(input: PromptHardwareKeyPINRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[4], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } + /** + * PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + * When the daemon detects the touch, it cancels the prompt. + * + * @generated from protobuf rpc: PromptHardwareKeyTouch(teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse); + */ + promptHardwareKeyTouch(input: PromptHardwareKeyTouchRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[5], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } + /** + * PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + * change the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPINChange(teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse); + */ + promptHardwareKeyPINChange(input: PromptHardwareKeyPINChangeRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[6], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } + /** + * ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + * the slot's private key and certificate should be overwritten. + * + * @generated from protobuf rpc: ConfirmHardwareKeySlotOverwrite(teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest) returns (teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse); + */ + confirmHardwareKeySlotOverwrite(input: ConfirmHardwareKeySlotOverwriteRequest, options?: RpcOptions): UnaryCall { + const method = this.methods[7], opt = this._transport.mergeOptions(options); + return stackIntercept("unary", this._transport, method, opt, input); + } /** * GetUsageReportingSettings returns the current state of usage reporting. * At the moment, the user cannot toggle usage reporting on and off without shutting down the app, @@ -159,7 +235,7 @@ export class TshdEventsServiceClient implements ITshdEventsServiceClient, Servic * @generated from protobuf rpc: GetUsageReportingSettings(teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest) returns (teleport.lib.teleterm.v1.GetUsageReportingSettingsResponse); */ getUsageReportingSettings(input: GetUsageReportingSettingsRequest, options?: RpcOptions): UnaryCall { - const method = this.methods[4], opt = this._transport.mergeOptions(options); + const method = this.methods[8], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } /** @@ -170,7 +246,7 @@ export class TshdEventsServiceClient implements ITshdEventsServiceClient, Servic * @generated from protobuf rpc: ReportUnexpectedVnetShutdown(teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownRequest) returns (teleport.lib.teleterm.v1.ReportUnexpectedVnetShutdownResponse); */ reportUnexpectedVnetShutdown(input: ReportUnexpectedVnetShutdownRequest, options?: RpcOptions): UnaryCall { - const method = this.methods[5], opt = this._transport.mergeOptions(options); + const method = this.methods[9], opt = this._transport.mergeOptions(options); return stackIntercept("unary", this._transport, method, opt, input); } } diff --git a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server.ts b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server.ts index 7f71d9adf0d4a..110fa4c7d1c33 100644 --- a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server.ts +++ b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.grpc-server.ts @@ -25,6 +25,14 @@ import { ReportUnexpectedVnetShutdownResponse } from "./tshd_events_service_pb"; import { ReportUnexpectedVnetShutdownRequest } from "./tshd_events_service_pb"; import { GetUsageReportingSettingsResponse } from "./tshd_events_service_pb"; import { GetUsageReportingSettingsRequest } from "./tshd_events_service_pb"; +import { ConfirmHardwareKeySlotOverwriteResponse } from "./tshd_events_service_pb"; +import { ConfirmHardwareKeySlotOverwriteRequest } from "./tshd_events_service_pb"; +import { PromptHardwareKeyPINChangeResponse } from "./tshd_events_service_pb"; +import { PromptHardwareKeyPINChangeRequest } from "./tshd_events_service_pb"; +import { PromptHardwareKeyTouchResponse } from "./tshd_events_service_pb"; +import { PromptHardwareKeyTouchRequest } from "./tshd_events_service_pb"; +import { PromptHardwareKeyPINResponse } from "./tshd_events_service_pb"; +import { PromptHardwareKeyPINRequest } from "./tshd_events_service_pb"; import { PromptMFAResponse } from "./tshd_events_service_pb"; import { PromptMFARequest } from "./tshd_events_service_pb"; import { SendPendingHeadlessAuthenticationResponse } from "./tshd_events_service_pb"; @@ -72,6 +80,34 @@ export interface ITshdEventsService extends grpc.UntypedServiceImplementation { * @generated from protobuf rpc: PromptMFA(teleport.lib.teleterm.v1.PromptMFARequest) returns (teleport.lib.teleterm.v1.PromptMFAResponse); */ promptMFA: grpc.handleUnaryCall; + /** + * PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + * provide the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPIN(teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse); + */ + promptHardwareKeyPIN: grpc.handleUnaryCall; + /** + * PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + * When the daemon detects the touch, it cancels the prompt. + * + * @generated from protobuf rpc: PromptHardwareKeyTouch(teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse); + */ + promptHardwareKeyTouch: grpc.handleUnaryCall; + /** + * PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + * change the hardware key PIN. + * + * @generated from protobuf rpc: PromptHardwareKeyPINChange(teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest) returns (teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse); + */ + promptHardwareKeyPINChange: grpc.handleUnaryCall; + /** + * ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + * the slot's private key and certificate should be overwritten. + * + * @generated from protobuf rpc: ConfirmHardwareKeySlotOverwrite(teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest) returns (teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse); + */ + confirmHardwareKeySlotOverwrite: grpc.handleUnaryCall; /** * GetUsageReportingSettings returns the current state of usage reporting. * At the moment, the user cannot toggle usage reporting on and off without shutting down the app, @@ -142,6 +178,46 @@ export const tshdEventsServiceDefinition: grpc.ServiceDefinition Buffer.from(PromptMFAResponse.toBinary(value)), requestSerialize: value => Buffer.from(PromptMFARequest.toBinary(value)) }, + promptHardwareKeyPIN: { + path: "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyPIN", + originalName: "PromptHardwareKeyPIN", + requestStream: false, + responseStream: false, + responseDeserialize: bytes => PromptHardwareKeyPINResponse.fromBinary(bytes), + requestDeserialize: bytes => PromptHardwareKeyPINRequest.fromBinary(bytes), + responseSerialize: value => Buffer.from(PromptHardwareKeyPINResponse.toBinary(value)), + requestSerialize: value => Buffer.from(PromptHardwareKeyPINRequest.toBinary(value)) + }, + promptHardwareKeyTouch: { + path: "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyTouch", + originalName: "PromptHardwareKeyTouch", + requestStream: false, + responseStream: false, + responseDeserialize: bytes => PromptHardwareKeyTouchResponse.fromBinary(bytes), + requestDeserialize: bytes => PromptHardwareKeyTouchRequest.fromBinary(bytes), + responseSerialize: value => Buffer.from(PromptHardwareKeyTouchResponse.toBinary(value)), + requestSerialize: value => Buffer.from(PromptHardwareKeyTouchRequest.toBinary(value)) + }, + promptHardwareKeyPINChange: { + path: "/teleport.lib.teleterm.v1.TshdEventsService/PromptHardwareKeyPINChange", + originalName: "PromptHardwareKeyPINChange", + requestStream: false, + responseStream: false, + responseDeserialize: bytes => PromptHardwareKeyPINChangeResponse.fromBinary(bytes), + requestDeserialize: bytes => PromptHardwareKeyPINChangeRequest.fromBinary(bytes), + responseSerialize: value => Buffer.from(PromptHardwareKeyPINChangeResponse.toBinary(value)), + requestSerialize: value => Buffer.from(PromptHardwareKeyPINChangeRequest.toBinary(value)) + }, + confirmHardwareKeySlotOverwrite: { + path: "/teleport.lib.teleterm.v1.TshdEventsService/ConfirmHardwareKeySlotOverwrite", + originalName: "ConfirmHardwareKeySlotOverwrite", + requestStream: false, + responseStream: false, + responseDeserialize: bytes => ConfirmHardwareKeySlotOverwriteResponse.fromBinary(bytes), + requestDeserialize: bytes => ConfirmHardwareKeySlotOverwriteRequest.fromBinary(bytes), + responseSerialize: value => Buffer.from(ConfirmHardwareKeySlotOverwriteResponse.toBinary(value)), + requestSerialize: value => Buffer.from(ConfirmHardwareKeySlotOverwriteRequest.toBinary(value)) + }, getUsageReportingSettings: { path: "/teleport.lib.teleterm.v1.TshdEventsService/GetUsageReportingSettings", originalName: "GetUsageReportingSettings", diff --git a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts index 1fc11883d6438..6bc1ef96ed469 100644 --- a/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts +++ b/gen/proto/ts/teleport/lib/teleterm/v1/tshd_events_service_pb.ts @@ -246,6 +246,121 @@ export interface PromptMFAResponse { */ totpCode: string; } +/** + * Request for PromptHardwareKeyPIN. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest + */ +export interface PromptHardwareKeyPINRequest { + /** + * @generated from protobuf field: string root_cluster_uri = 1; + */ + rootClusterUri: string; + /** + * Specifies if a PIN is optional, allowing the user to set it up if left empty. + * + * @generated from protobuf field: bool pin_optional = 2; + */ + pinOptional: boolean; +} +/** + * Response for PromptHardwareKeyPIN. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse + */ +export interface PromptHardwareKeyPINResponse { + /** + * pin as inputted by the user in the Electron app. + * + * @generated from protobuf field: string pin = 1; + */ + pin: string; +} +/** + * Request for PromptHardwareKeyTouchRequest. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest + */ +export interface PromptHardwareKeyTouchRequest { + /** + * @generated from protobuf field: string root_cluster_uri = 1; + */ + rootClusterUri: string; +} +/** + * Response for PromptHardwareKeyTouch. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse + */ +export interface PromptHardwareKeyTouchResponse { +} +/** + * Response for PromptHardwareKeyPINChange. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest + */ +export interface PromptHardwareKeyPINChangeRequest { + /** + * @generated from protobuf field: string root_cluster_uri = 1; + */ + rootClusterUri: string; +} +/** + * Response for PromptHardwareKeyPINChange. + * + * @generated from protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse + */ +export interface PromptHardwareKeyPINChangeResponse { + /** + * New pin set by the user. + * + * @generated from protobuf field: string pin = 1; + */ + pin: string; + /** + * PUK is needed to change the PIN. + * This is a new PUK if it has not been changed from the default PUK. + * + * @generated from protobuf field: string puk = 2; + */ + puk: string; + /** + * puk_changed is true if the user changed the default PUK. + * + * @generated from protobuf field: bool puk_changed = 3; + */ + pukChanged: boolean; +} +/** + * Request for ConfirmHardwareKeySlotOverwrite. + * + * @generated from protobuf message teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest + */ +export interface ConfirmHardwareKeySlotOverwriteRequest { + /** + * @generated from protobuf field: string root_cluster_uri = 1; + */ + rootClusterUri: string; + /** + * Message to display in the prompt. + * + * @generated from protobuf field: string message = 2; + */ + message: string; +} +/** + * Response for ConfirmHardwareKeySlotOverwrite. + * + * @generated from protobuf message teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse + */ +export interface ConfirmHardwareKeySlotOverwriteResponse { + /** + * If true, the slot will be overridden. + * + * @generated from protobuf field: bool confirmed = 1; + */ + confirmed: boolean; +} /** * Request for GetUsageReportingSettings. * @@ -918,6 +1033,392 @@ class PromptMFAResponse$Type extends MessageType { */ export const PromptMFAResponse = new PromptMFAResponse$Type(); // @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyPINRequest$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest", [ + { no: 1, name: "root_cluster_uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 2, name: "pin_optional", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + ]); + } + create(value?: PartialMessage): PromptHardwareKeyPINRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootClusterUri = ""; + message.pinOptional = false; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyPINRequest): PromptHardwareKeyPINRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string root_cluster_uri */ 1: + message.rootClusterUri = reader.string(); + break; + case /* bool pin_optional */ 2: + message.pinOptional = reader.bool(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: PromptHardwareKeyPINRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string root_cluster_uri = 1; */ + if (message.rootClusterUri !== "") + writer.tag(1, WireType.LengthDelimited).string(message.rootClusterUri); + /* bool pin_optional = 2; */ + if (message.pinOptional !== false) + writer.tag(2, WireType.Varint).bool(message.pinOptional); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINRequest + */ +export const PromptHardwareKeyPINRequest = new PromptHardwareKeyPINRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyPINResponse$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse", [ + { no: 1, name: "pin", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): PromptHardwareKeyPINResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.pin = ""; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyPINResponse): PromptHardwareKeyPINResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string pin */ 1: + message.pin = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: PromptHardwareKeyPINResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string pin = 1; */ + if (message.pin !== "") + writer.tag(1, WireType.LengthDelimited).string(message.pin); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINResponse + */ +export const PromptHardwareKeyPINResponse = new PromptHardwareKeyPINResponse$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyTouchRequest$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest", [ + { no: 1, name: "root_cluster_uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): PromptHardwareKeyTouchRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootClusterUri = ""; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyTouchRequest): PromptHardwareKeyTouchRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string root_cluster_uri */ 1: + message.rootClusterUri = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: PromptHardwareKeyTouchRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string root_cluster_uri = 1; */ + if (message.rootClusterUri !== "") + writer.tag(1, WireType.LengthDelimited).string(message.rootClusterUri); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyTouchRequest + */ +export const PromptHardwareKeyTouchRequest = new PromptHardwareKeyTouchRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyTouchResponse$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse", []); + } + create(value?: PartialMessage): PromptHardwareKeyTouchResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyTouchResponse): PromptHardwareKeyTouchResponse { + return target ?? this.create(); + } + internalBinaryWrite(message: PromptHardwareKeyTouchResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyTouchResponse + */ +export const PromptHardwareKeyTouchResponse = new PromptHardwareKeyTouchResponse$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyPINChangeRequest$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest", [ + { no: 1, name: "root_cluster_uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): PromptHardwareKeyPINChangeRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootClusterUri = ""; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyPINChangeRequest): PromptHardwareKeyPINChangeRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string root_cluster_uri */ 1: + message.rootClusterUri = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: PromptHardwareKeyPINChangeRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string root_cluster_uri = 1; */ + if (message.rootClusterUri !== "") + writer.tag(1, WireType.LengthDelimited).string(message.rootClusterUri); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeRequest + */ +export const PromptHardwareKeyPINChangeRequest = new PromptHardwareKeyPINChangeRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class PromptHardwareKeyPINChangeResponse$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse", [ + { no: 1, name: "pin", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 2, name: "puk", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 3, name: "puk_changed", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + ]); + } + create(value?: PartialMessage): PromptHardwareKeyPINChangeResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.pin = ""; + message.puk = ""; + message.pukChanged = false; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: PromptHardwareKeyPINChangeResponse): PromptHardwareKeyPINChangeResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string pin */ 1: + message.pin = reader.string(); + break; + case /* string puk */ 2: + message.puk = reader.string(); + break; + case /* bool puk_changed */ 3: + message.pukChanged = reader.bool(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: PromptHardwareKeyPINChangeResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string pin = 1; */ + if (message.pin !== "") + writer.tag(1, WireType.LengthDelimited).string(message.pin); + /* string puk = 2; */ + if (message.puk !== "") + writer.tag(2, WireType.LengthDelimited).string(message.puk); + /* bool puk_changed = 3; */ + if (message.pukChanged !== false) + writer.tag(3, WireType.Varint).bool(message.pukChanged); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.PromptHardwareKeyPINChangeResponse + */ +export const PromptHardwareKeyPINChangeResponse = new PromptHardwareKeyPINChangeResponse$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class ConfirmHardwareKeySlotOverwriteRequest$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest", [ + { no: 1, name: "root_cluster_uri", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 2, name: "message", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): ConfirmHardwareKeySlotOverwriteRequest { + const message = globalThis.Object.create((this.messagePrototype!)); + message.rootClusterUri = ""; + message.message = ""; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConfirmHardwareKeySlotOverwriteRequest): ConfirmHardwareKeySlotOverwriteRequest { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string root_cluster_uri */ 1: + message.rootClusterUri = reader.string(); + break; + case /* string message */ 2: + message.message = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: ConfirmHardwareKeySlotOverwriteRequest, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string root_cluster_uri = 1; */ + if (message.rootClusterUri !== "") + writer.tag(1, WireType.LengthDelimited).string(message.rootClusterUri); + /* string message = 2; */ + if (message.message !== "") + writer.tag(2, WireType.LengthDelimited).string(message.message); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteRequest + */ +export const ConfirmHardwareKeySlotOverwriteRequest = new ConfirmHardwareKeySlotOverwriteRequest$Type(); +// @generated message type with reflection information, may provide speed optimized methods +class ConfirmHardwareKeySlotOverwriteResponse$Type extends MessageType { + constructor() { + super("teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse", [ + { no: 1, name: "confirmed", kind: "scalar", T: 8 /*ScalarType.BOOL*/ } + ]); + } + create(value?: PartialMessage): ConfirmHardwareKeySlotOverwriteResponse { + const message = globalThis.Object.create((this.messagePrototype!)); + message.confirmed = false; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ConfirmHardwareKeySlotOverwriteResponse): ConfirmHardwareKeySlotOverwriteResponse { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* bool confirmed */ 1: + message.confirmed = reader.bool(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: ConfirmHardwareKeySlotOverwriteResponse, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* bool confirmed = 1; */ + if (message.confirmed !== false) + writer.tag(1, WireType.Varint).bool(message.confirmed); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message teleport.lib.teleterm.v1.ConfirmHardwareKeySlotOverwriteResponse + */ +export const ConfirmHardwareKeySlotOverwriteResponse = new ConfirmHardwareKeySlotOverwriteResponse$Type(); +// @generated message type with reflection information, may provide speed optimized methods class GetUsageReportingSettingsRequest$Type extends MessageType { constructor() { super("teleport.lib.teleterm.v1.GetUsageReportingSettingsRequest", []); @@ -1115,6 +1616,10 @@ export const TshdEventsService = new ServiceType("teleport.lib.teleterm.v1.TshdE { name: "SendNotification", options: {}, I: SendNotificationRequest, O: SendNotificationResponse }, { name: "SendPendingHeadlessAuthentication", options: {}, I: SendPendingHeadlessAuthenticationRequest, O: SendPendingHeadlessAuthenticationResponse }, { name: "PromptMFA", options: {}, I: PromptMFARequest, O: PromptMFAResponse }, + { name: "PromptHardwareKeyPIN", options: {}, I: PromptHardwareKeyPINRequest, O: PromptHardwareKeyPINResponse }, + { name: "PromptHardwareKeyTouch", options: {}, I: PromptHardwareKeyTouchRequest, O: PromptHardwareKeyTouchResponse }, + { name: "PromptHardwareKeyPINChange", options: {}, I: PromptHardwareKeyPINChangeRequest, O: PromptHardwareKeyPINChangeResponse }, + { name: "ConfirmHardwareKeySlotOverwrite", options: {}, I: ConfirmHardwareKeySlotOverwriteRequest, O: ConfirmHardwareKeySlotOverwriteResponse }, { name: "GetUsageReportingSettings", options: {}, I: GetUsageReportingSettingsRequest, O: GetUsageReportingSettingsResponse }, { name: "ReportUnexpectedVnetShutdown", options: {}, I: ReportUnexpectedVnetShutdownRequest, O: ReportUnexpectedVnetShutdownResponse } ]); diff --git a/lib/teleterm/daemon/hardwarekeyprompt.go b/lib/teleterm/daemon/hardwarekeyprompt.go new file mode 100644 index 0000000000000..4c8b5838a3b01 --- /dev/null +++ b/lib/teleterm/daemon/hardwarekeyprompt.go @@ -0,0 +1,108 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package daemon + +import ( + "context" + + "github.com/gravitational/trace" + + "github.com/gravitational/teleport/api/utils/keys" + api "github.com/gravitational/teleport/gen/proto/go/teleport/lib/teleterm/v1" + "github.com/gravitational/teleport/lib/teleterm/api/uri" +) + +// NewHardwareKeyPromptConstructor returns a new hardware key prompt constructor +// for this service and the given root cluster URI. +func (s *Service) NewHardwareKeyPromptConstructor(rootClusterURI uri.ResourceURI) keys.HardwareKeyPrompt { + return &hardwareKeyPrompter{s: s, rootClusterURI: rootClusterURI} +} + +type hardwareKeyPrompter struct { + s *Service + rootClusterURI uri.ResourceURI +} + +// Touch prompts the user to touch the hardware key. +func (h *hardwareKeyPrompter) Touch(ctx context.Context) error { + if err := h.s.importantModalSemaphore.Acquire(ctx); err != nil { + return trace.Wrap(err) + } + defer h.s.importantModalSemaphore.Release() + _, err := h.s.tshdEventsClient.PromptHardwareKeyTouch(ctx, &api.PromptHardwareKeyTouchRequest{ + RootClusterUri: h.rootClusterURI.String(), + }) + if err != nil { + return trace.Wrap(err) + } + return nil +} + +// AskPIN prompts the user for a PIN. +func (h *hardwareKeyPrompter) AskPIN(ctx context.Context, requirement keys.PINPromptRequirement) (string, error) { + if err := h.s.importantModalSemaphore.Acquire(ctx); err != nil { + return "", trace.Wrap(err) + } + defer h.s.importantModalSemaphore.Release() + res, err := h.s.tshdEventsClient.PromptHardwareKeyPIN(ctx, &api.PromptHardwareKeyPINRequest{ + RootClusterUri: h.rootClusterURI.String(), + PinOptional: requirement == keys.PINOptional, + }) + if err != nil { + return "", trace.Wrap(err) + } + return res.Pin, nil +} + +// ChangePIN asks for a new PIN. +// The Electron app prompt must handle default values for PIN and PUK, +// preventing the user from submitting empty/default values. +func (h *hardwareKeyPrompter) ChangePIN(ctx context.Context) (*keys.PINAndPUK, error) { + if err := h.s.importantModalSemaphore.Acquire(ctx); err != nil { + return nil, trace.Wrap(err) + } + defer h.s.importantModalSemaphore.Release() + res, err := h.s.tshdEventsClient.PromptHardwareKeyPINChange(ctx, &api.PromptHardwareKeyPINChangeRequest{ + RootClusterUri: h.rootClusterURI.String(), + }) + if err != nil { + return nil, trace.Wrap(err) + } + return &keys.PINAndPUK{ + PIN: res.Pin, + PUK: res.Puk, + PUKChanged: res.PukChanged, + }, nil +} + +// ConfirmSlotOverwrite asks the user if the slot's private key and certificate can be overridden. +func (h *hardwareKeyPrompter) ConfirmSlotOverwrite(ctx context.Context, message string) (bool, error) { + if err := h.s.importantModalSemaphore.Acquire(ctx); err != nil { + return false, trace.Wrap(err) + } + defer h.s.importantModalSemaphore.Release() + res, err := h.s.tshdEventsClient.ConfirmHardwareKeySlotOverwrite(ctx, &api.ConfirmHardwareKeySlotOverwriteRequest{ + RootClusterUri: h.rootClusterURI.String(), + Message: message, + }) + if err != nil { + return false, trace.Wrap(err) + } + return res.Confirmed, nil +} diff --git a/lib/teleterm/teleterm.go b/lib/teleterm/teleterm.go index fd868169642e0..c8bc92b4e0e8a 100644 --- a/lib/teleterm/teleterm.go +++ b/lib/teleterm/teleterm.go @@ -42,6 +42,7 @@ import ( // Serve starts daemon service func Serve(ctx context.Context, cfg Config) error { + var hardwareKeyPromptConstructor func(clusterURI uri.ResourceURI) keys.HardwareKeyPrompt if err := cfg.CheckAndSetDefaults(); err != nil { return trace.Wrap(err) } @@ -58,8 +59,8 @@ func Serve(ctx context.Context, cfg Config) error { Clock: clock, InsecureSkipVerify: cfg.InsecureSkipVerify, AddKeysToAgent: cfg.AddKeysToAgent, - HardwareKeyPromptConstructor: func(clusterURI uri.ResourceURI) keys.HardwareKeyPrompt { - return nil + HardwareKeyPromptConstructor: func(rootClusterURI uri.ResourceURI) keys.HardwareKeyPrompt { + return hardwareKeyPromptConstructor(rootClusterURI) }, }) if err != nil { @@ -80,6 +81,9 @@ func Serve(ctx context.Context, cfg Config) error { return trace.Wrap(err) } + // TODO(gzdunek): Move tshdEventsClient out of daemonService so that we can + // construct the prompt before creating Storage. + hardwareKeyPromptConstructor = daemonService.NewHardwareKeyPromptConstructor apiServer, err := apiserver.New(apiserver.Config{ HostAddr: cfg.Addr, InsecureSkipVerify: cfg.InsecureSkipVerify, diff --git a/proto/teleport/lib/teleterm/v1/tshd_events_service.proto b/proto/teleport/lib/teleterm/v1/tshd_events_service.proto index 1e5b6b6a53d45..de3f127c62a2d 100644 --- a/proto/teleport/lib/teleterm/v1/tshd_events_service.proto +++ b/proto/teleport/lib/teleterm/v1/tshd_events_service.proto @@ -44,6 +44,22 @@ service TshdEventsService { // code. rpc PromptMFA(PromptMFARequest) returns (PromptMFAResponse); + // PromptHardwareKeyPIN notifies the Electron app that the daemon is waiting for the user to + // provide the hardware key PIN. + rpc PromptHardwareKeyPIN(PromptHardwareKeyPINRequest) returns (PromptHardwareKeyPINResponse); + + // PromptHardwareKeyTouch notifies the Electron app that the daemon is waiting for the user to touch the hardware key. + // When the daemon detects the touch, it cancels the prompt. + rpc PromptHardwareKeyTouch(PromptHardwareKeyTouchRequest) returns (PromptHardwareKeyTouchResponse); + + // PromptHardwareKeyPINChange notifies the Electron app that the daemon is waiting for the user to + // change the hardware key PIN. + rpc PromptHardwareKeyPINChange(PromptHardwareKeyPINChangeRequest) returns (PromptHardwareKeyPINChangeResponse); + + // ConfirmHardwareKeySlotOverwrite displays a dialog prompting the user to confirm whether + // the slot's private key and certificate should be overwritten. + rpc ConfirmHardwareKeySlotOverwrite(ConfirmHardwareKeySlotOverwriteRequest) returns (ConfirmHardwareKeySlotOverwriteResponse); + // GetUsageReportingSettings returns the current state of usage reporting. // At the moment, the user cannot toggle usage reporting on and off without shutting down the app, // with the only exception being the first start of the app when they're prompted about telemetry. @@ -146,6 +162,56 @@ message PromptMFAResponse { string totp_code = 1; } +// Request for PromptHardwareKeyPIN. +message PromptHardwareKeyPINRequest { + string root_cluster_uri = 1; + // Specifies if a PIN is optional, allowing the user to set it up if left empty. + bool pin_optional = 2; +} + +// Response for PromptHardwareKeyPIN. +message PromptHardwareKeyPINResponse { + // pin as inputted by the user in the Electron app. + string pin = 1; +} + +// Request for PromptHardwareKeyTouchRequest. +message PromptHardwareKeyTouchRequest { + string root_cluster_uri = 1; +} + +// Response for PromptHardwareKeyTouch. +message PromptHardwareKeyTouchResponse {} + +// Response for PromptHardwareKeyPINChange. +message PromptHardwareKeyPINChangeRequest { + string root_cluster_uri = 1; +} + +// Response for PromptHardwareKeyPINChange. +message PromptHardwareKeyPINChangeResponse { + // New pin set by the user. + string pin = 1; + // PUK is needed to change the PIN. + // This is a new PUK if it has not been changed from the default PUK. + string puk = 2; + // puk_changed is true if the user changed the default PUK. + bool puk_changed = 3; +} + +// Request for ConfirmHardwareKeySlotOverwrite. +message ConfirmHardwareKeySlotOverwriteRequest { + string root_cluster_uri = 1; + // Message to display in the prompt. + string message = 2; +} + +// Response for ConfirmHardwareKeySlotOverwrite. +message ConfirmHardwareKeySlotOverwriteResponse { + // If true, the slot will be overridden. + bool confirmed = 1; +} + // Request for GetUsageReportingSettings. message GetUsageReportingSettingsRequest {} diff --git a/web/packages/teleterm/src/services/tshd/interceptors.ts b/web/packages/teleterm/src/services/tshd/interceptors.ts index a3375ea1f32a2..3acd92d81feef 100644 --- a/web/packages/teleterm/src/services/tshd/interceptors.ts +++ b/web/packages/teleterm/src/services/tshd/interceptors.ts @@ -22,7 +22,7 @@ import { isObject } from 'shared/utils/highbar'; import Logger from 'teleterm/logger'; -const SENSITIVE_PROPERTIES = ['password', 'authClusterId', 'pin']; +const SENSITIVE_PROPERTIES = ['password', 'authClusterId', 'pin', 'puk']; export function loggingInterceptor(logger: Logger): RpcInterceptor { return { diff --git a/web/packages/teleterm/src/services/tshdEvents/index.ts b/web/packages/teleterm/src/services/tshdEvents/index.ts index eb63c14cb9a3d..a8744d9a7c576 100644 --- a/web/packages/teleterm/src/services/tshdEvents/index.ts +++ b/web/packages/teleterm/src/services/tshdEvents/index.ts @@ -206,6 +206,18 @@ function createService(logger: Logger): { const service: apiService.ITshdEventsService = { relogin: (call, callback) => processEvent('relogin', call, callback), + promptHardwareKeyPIN: (call, callback) => + processEvent('promptHardwareKeyPIN', call, callback), + + promptHardwareKeyTouch: (call, callback) => + processEvent('promptHardwareKeyTouch', call, callback), + + promptHardwareKeyPINChange: (call, callback) => + processEvent('promptHardwareKeyPINChange', call, callback), + + confirmHardwareKeySlotOverwrite: (call, callback) => + processEvent('confirmHardwareKeySlotOverwrite', call, callback), + sendNotification: (call, callback) => processEvent('sendNotification', call, callback), diff --git a/web/packages/teleterm/src/ui/ModalsHost/ModalsHost.tsx b/web/packages/teleterm/src/ui/ModalsHost/ModalsHost.tsx index 582eaa09a49b9..09e1c09a94cd3 100644 --- a/web/packages/teleterm/src/ui/ModalsHost/ModalsHost.tsx +++ b/web/packages/teleterm/src/ui/ModalsHost/ModalsHost.tsx @@ -34,6 +34,7 @@ import { UserJobRole } from './modals/UserJobRole'; import { ReAuthenticate } from './modals/ReAuthenticate'; import { AuthenticateWebDevice } from './modals/AuthenticateWebDevice/AuthenticateWebDevice'; import { ChangeAccessRequestKind } from './modals/ChangeAccessRequestKind'; +import { AskPin, ChangePin, OverwriteSlot, Touch } from './modals/HardwareKeys'; export default function ModalsHost() { const { modalsService } = useAppContext(); @@ -202,6 +203,56 @@ function renderDialog(dialog: Dialog, handleClose: () => void) { /> ); } + case 'hardware-key-pin': { + return ( + { + handleClose(); + dialog.onSuccess(res); + }} + onCancel={() => { + handleClose(); + dialog.onCancel(); + }} + /> + ); + } + case 'hardware-key-touch': { + return ( + { + handleClose(); + dialog.onCancel(); + }} + /> + ); + } + case 'hardware-key-pin-change': { + return ( + { + handleClose(); + dialog.onCancel(); + }} + /> + ); + } + case 'hardware-key-slot-overwrite': { + return ( + { + handleClose(); + dialog.onCancel(); + }} + /> + ); + } case 'none': { return null; diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/AskPin.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/AskPin.tsx new file mode 100644 index 0000000000000..2dbf6da7e1472 --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/AskPin.tsx @@ -0,0 +1,98 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { useState } from 'react'; + +import DialogConfirmation, { + DialogContent, + DialogFooter, +} from 'design/DialogConfirmation'; +import { ButtonPrimary, Flex, P2 } from 'design'; +import FieldInput from 'shared/components/FieldInput'; +import Validation from 'shared/components/Validation'; +import { requiredField } from 'shared/components/Validation/rules'; + +import { PromptHardwareKeyPINRequest } from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb'; + +import { CommonHeader } from './CommonHeader'; + +export function AskPin(props: { + req: PromptHardwareKeyPINRequest; + onCancel(): void; + onSuccess(pin: string): void; +}) { + const [pin, setPin] = useState(''); + + return ( + ({ + maxWidth: '450px', + width: '100%', + })} + > + + {({ validator }) => ( +
{ + e.preventDefault(); + validator.validate() && props.onSuccess(pin); + }} + > + + + + + + Enter your YubiKey PIV PIN. +
+ {props.req.pinOptional && + 'To change the default PIN, leave the field blank.'} +
+ + setPin(e.target.value)} + placeholder="123 456" + mb={0} + /> +
+
+ + + Continue + + + )} +
+
+ ); +} diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/ChangePin.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/ChangePin.tsx new file mode 100644 index 0000000000000..64fb239cc6f6e --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/ChangePin.tsx @@ -0,0 +1,257 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { useState } from 'react'; + +import DialogConfirmation, { + DialogContent, + DialogFooter, +} from 'design/DialogConfirmation'; +import { ButtonPrimary, Flex, Toggle, P2 } from 'design'; +import Validation from 'shared/components/Validation'; +import FieldInput from 'shared/components/FieldInput'; +import { + PromptHardwareKeyPINChangeRequest, + PromptHardwareKeyPINChangeResponse, +} from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb'; + +import { + requiredField, + Rule, + requiredAll, +} from 'shared/components/Validation/rules'; + +import { CommonHeader } from './CommonHeader'; + +const DEFAULT_PIN = '123456'; +const DEFAULT_PUK = '12345678'; + +export function ChangePin(props: { + req: PromptHardwareKeyPINChangeRequest; + onCancel(): void; + onSuccess(response: PromptHardwareKeyPINChangeResponse): void; +}) { + const [pin, setPin] = useState(''); + const [confirmPin, setConfirmPin] = useState(''); + const [puk, setPuk] = useState(''); + const [newPuk, setNewPuk] = useState(''); + const [confirmNewPuk, setConfirmNewPuk] = useState(''); + const [pukChanged, setPukChanged] = useState(false); + + return ( + ({ + maxWidth: '450px', + width: '100%', + })} + > + + {({ validator }) => ( +
{ + e.preventDefault(); + validator.validate() && + props.onSuccess({ + pin, + pukChanged: pukChanged, + puk: pukChanged ? newPuk : puk, + }); + }} + > + + + + + + The default PIV PIN is not allowed. +
+ Please set a new PIV PIN for your hardware key before + proceeding. Both the PIN and PUK must be 4-6 characters long. +
+ + setPin(e.target.value)} + mb={0} + rule={requiredAll( + requiredField('New PIV PIN is required'), + notDefaultPin(), + correctLength('PIV PIN must be 4-6 characters long') + )} + /> + setConfirmPin(e.target.value)} + mb={0} + rule={requiredAll( + requiredConfirmed(pin, { + confirm: 'Confirm New PIV PIN is required', + doesNotMatch: 'PIV PIN does not match', + }), + notDefaultPin(), + correctLength('PIV PIN must be 4-6 characters long') + )} + /> + + + To change the PIN, please provide your PUK code. +
+ For security purposes, the default PUK ({DEFAULT_PUK}) cannot + be used. If you haven't changed your PUK yet, you'll need to + update it now. +
+ setPukChanged(p => !p)} + > + + Set up new PUK + + + + {!pukChanged ? ( + setPuk(e.target.value)} + mb={0} + rule={requiredAll( + requiredField('PUK is required'), + notDefaultPuk(), + correctLength('PUK must be 4-6 characters long') + )} + /> + ) : ( + <> + setNewPuk(e.target.value)} + mb={0} + rule={requiredAll( + requiredField('New PUK is required'), + notDefaultPuk(), + correctLength('PUK must be 4-6 characters long') + )} + /> + setConfirmNewPuk(e.target.value)} + mb={0} + rule={requiredAll( + requiredConfirmed(pin, { + confirm: 'Confirm New PUK is required', + doesNotMatch: 'PUK does not match', + }), + notDefaultPuk(), + correctLength('PUK must be 4-6 characters long') + )} + /> + + )} +
+
+ + + Continue + + + )} +
+
+ ); +} + +const notDefaultPin = + (): Rule => + value => + () => { + const message = 'Default PIN is not allowed'; + const valid = value !== DEFAULT_PIN; + return { + valid, + message: !valid ? message : '', + }; + }; + +const notDefaultPuk = + (): Rule => + value => + () => { + const message = 'Default PUK is not allowed'; + const valid = value !== DEFAULT_PUK; + return { + valid, + message: !valid ? message : '', + }; + }; + +const correctLength = + (message: string): Rule => + value => + () => { + const valid = + typeof value === 'string' && value.length >= 4 && value.length <= 6; + return { + valid, + message: !valid ? message : '', + }; + }; + +const requiredConfirmed = + ( + code: string, + messages: { + confirm: string; + doesNotMatch: string; + } + ): Rule => + (confirmedCode: string) => + () => { + if (!confirmedCode) { + return { + valid: false, + message: messages.confirm, + }; + } + + if (confirmedCode !== code) { + return { + valid: false, + message: messages.doesNotMatch, + }; + } + + return { + valid: true, + }; + }; diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/CommonHeader.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/CommonHeader.tsx new file mode 100644 index 0000000000000..8027886e8fa64 --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/CommonHeader.tsx @@ -0,0 +1,46 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { H2, ButtonIcon } from 'design'; +import * as icons from 'design/Icon'; +import { DialogHeader } from 'design/Dialog'; + +import { RootClusterUri, routing } from 'teleterm/ui/uri'; + +export function CommonHeader(props: { + onCancel(): void; + rootClusterUri: RootClusterUri; +}) { + const rootClusterName = routing.parseClusterName(props.rootClusterUri); + + return ( + +

+ Unlock hardware key to access {rootClusterName} +

+ + + + +
+ ); +} diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/OverwriteSlot.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/OverwriteSlot.tsx new file mode 100644 index 0000000000000..1a67d691c9747 --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/OverwriteSlot.tsx @@ -0,0 +1,68 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import DialogConfirmation, { + DialogContent, + DialogFooter, +} from 'design/DialogConfirmation'; +import { ButtonPrimary, ButtonSecondary, Flex, P2 } from 'design'; +import { ConfirmHardwareKeySlotOverwriteRequest } from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb'; + +import { CommonHeader } from './CommonHeader'; + +export function OverwriteSlot(props: { + req: ConfirmHardwareKeySlotOverwriteRequest; + onCancel(): void; + onConfirm(): void; +}) { + return ( + ({ + maxWidth: '450px', + width: '100%', + })} + > +
{ + e.preventDefault(); + props.onConfirm(); + }} + > + + + + {props.req.message} + + + + + Yes + + No + + + + +
+ ); +} diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/Touch.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/Touch.tsx new file mode 100644 index 0000000000000..a25e1f42dc5fd --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/Touch.tsx @@ -0,0 +1,63 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import DialogConfirmation, { DialogContent } from 'design/DialogConfirmation'; +import { Flex, Image, P2 } from 'design'; + +import { PromptHardwareKeyTouchRequest } from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb'; + +import svgHardwareKey from 'teleterm/ui/ClusterConnect/ClusterLogin/FormLogin/PromptWebauthn/hardware.svg'; +import LinearProgress from 'teleterm/ui/components/LinearProgress'; + +import { CommonHeader } from './CommonHeader'; + +export function Touch(props: { + req: PromptHardwareKeyTouchRequest; + onCancel(): void; +}) { + return ( + ({ + maxWidth: '450px', + width: '100%', + })} + > + + + + + + Touch your YubiKey + + + + + ); +} diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.story.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.story.tsx new file mode 100644 index 0000000000000..835e3b17606b6 --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.story.tsx @@ -0,0 +1,93 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { Meta } from '@storybook/react'; + +import { makeRootCluster } from 'teleterm/services/tshd/testHelpers'; + +import { Touch as TouchComponent } from './Touch'; +import { OverwriteSlot as OverwriteSlotComponent } from './OverwriteSlot'; +import { ChangePin as ChangePinComponent } from './ChangePin'; +import { AskPin as AskPinComponent } from './AskPin'; + +const rootCluster = makeRootCluster(); + +export default { + title: 'Teleterm/ModalsHost/HardwareKeys', +} satisfies Meta; + +export function AskPinOptional() { + return ( + {}} + onCancel={() => {}} + req={{ + rootClusterUri: rootCluster.uri, + pinOptional: true, + }} + /> + ); +} + +export function AskPinRequired() { + return ( + {}} + onCancel={() => {}} + req={{ + rootClusterUri: rootCluster.uri, + pinOptional: false, + }} + /> + ); +} + +export function Touch() { + return ( + {}} + req={{ + rootClusterUri: rootCluster.uri, + }} + /> + ); +} + +export function ChangePin() { + return ( + {}} + onCancel={() => {}} + req={{ rootClusterUri: rootCluster.uri }} + /> + ); +} + +export function OverwriteSlot() { + return ( + {}} + onCancel={() => {}} + req={{ + rootClusterUri: rootCluster.uri, + message: + "Would you like to overwrite this slot's private key and certificate?", + }} + /> + ); +} diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.ts b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.ts new file mode 100644 index 0000000000000..473dcd5d9694a --- /dev/null +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/HardwareKeys/index.ts @@ -0,0 +1,22 @@ +/** + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +export * from './Touch'; +export * from './AskPin'; +export * from './ChangePin'; +export * from './OverwriteSlot'; diff --git a/web/packages/teleterm/src/ui/services/modals/modalsService.ts b/web/packages/teleterm/src/ui/services/modals/modalsService.ts index 6078e49dd2079..421a45c94398f 100644 --- a/web/packages/teleterm/src/ui/services/modals/modalsService.ts +++ b/web/packages/teleterm/src/ui/services/modals/modalsService.ts @@ -220,6 +220,33 @@ export interface DialogChangeAccessRequestKind { onCancel(): void; } +export interface DialogHardwareKeyPin { + kind: 'hardware-key-pin'; + req: tshdEventsApi.PromptHardwareKeyPINRequest; + onSuccess(pin: string): void; + onCancel(): void; +} + +export interface DialogHardwareKeyTouch { + kind: 'hardware-key-touch'; + req: tshdEventsApi.PromptHardwareKeyTouchRequest; + onCancel(): void; +} + +export interface DialogHardwareKeyPinChange { + kind: 'hardware-key-pin-change'; + req: tshdEventsApi.PromptHardwareKeyPINChangeRequest; + onSuccess(res: tshdEventsApi.PromptHardwareKeyPINChangeResponse): void; + onCancel(): void; +} + +export interface DialogHardwareKeySlotOverwrite { + kind: 'hardware-key-slot-overwrite'; + req: tshdEventsApi.ConfirmHardwareKeySlotOverwriteRequest; + onConfirm(): void; + onCancel(): void; +} + export type Dialog = | DialogClusterConnect | DialogClusterLogout @@ -231,4 +258,8 @@ export type Dialog = | DialogHeadlessAuthentication | DialogReAuthenticate | DialogChangeAccessRequestKind + | DialogHardwareKeyPin + | DialogHardwareKeyTouch + | DialogHardwareKeyPinChange + | DialogHardwareKeySlotOverwrite | DialogNone; diff --git a/web/packages/teleterm/src/ui/tshdEvents.ts b/web/packages/teleterm/src/ui/tshdEvents.ts index c48e48faa1481..b06aa73196b9e 100644 --- a/web/packages/teleterm/src/ui/tshdEvents.ts +++ b/web/packages/teleterm/src/ui/tshdEvents.ts @@ -16,6 +16,8 @@ * along with this program. If not, see . */ +import { PromptHardwareKeyPINChangeResponse } from 'gen-proto-ts/teleport/lib/teleterm/v1/tshd_events_service_pb'; + import { TshdEventContextBridgeService } from 'teleterm/types'; import { IAppContext } from 'teleterm/ui/types'; import Logger from 'teleterm/logger'; @@ -101,5 +103,135 @@ export function createTshdEventsContextBridgeService( } return {}; }, + + promptHardwareKeyPIN: async ({ request, onRequestCancelled }) => { + ctx.mainProcessClient.forceFocusWindow(); + const { pin, hasCanceledModal } = await new Promise<{ + pin: string; + hasCanceledModal: boolean; + }>(resolve => { + const { closeDialog } = ctx.modalsService.openImportantDialog({ + kind: 'hardware-key-pin', + req: request, + onSuccess: pin => resolve({ hasCanceledModal: false, pin }), + onCancel: () => + resolve({ + hasCanceledModal: true, + pin: undefined, + }), + }); + + // tshd can cancel the request + onRequestCancelled(closeDialog); + }); + + if (hasCanceledModal) { + throw { + isCrossContextError: true, + name: 'AbortError', + message: 'hardware key PIN modal closed by user', + }; + } + + return { pin: pin }; + }, + + promptHardwareKeyTouch: async ({ request, onRequestCancelled }) => { + ctx.mainProcessClient.forceFocusWindow(); + const { hasCanceledModal } = await new Promise<{ + hasCanceledModal: boolean; + }>(resolve => { + const { closeDialog } = ctx.modalsService.openImportantDialog({ + kind: 'hardware-key-touch', + req: request, + onCancel: () => + resolve({ + hasCanceledModal: true, + }), + }); + + // When a tap is detected, tshd cancels this request. + onRequestCancelled(closeDialog); + }); + + if (hasCanceledModal) { + throw { + isCrossContextError: true, + name: 'AbortError', + message: 'hardware key touch modal closed by user', + }; + } + + return {}; + }, + + promptHardwareKeyPINChange: async ({ request, onRequestCancelled }) => { + const { hasCanceledModal, res } = await new Promise<{ + hasCanceledModal: boolean; + res: PromptHardwareKeyPINChangeResponse; + }>(resolve => { + const { closeDialog } = ctx.modalsService.openImportantDialog({ + kind: 'hardware-key-pin-change', + req: request, + onSuccess: res => { + resolve({ hasCanceledModal: false, res }); + }, + onCancel: () => + resolve({ + hasCanceledModal: true, + res: undefined, + }), + }); + + // tshd can cancel the request + onRequestCancelled(closeDialog); + }); + + if (hasCanceledModal) { + throw { + isCrossContextError: true, + name: 'AbortError', + message: 'hardware key change PIN modal closed by user', + }; + } + + return res; + }, + + confirmHardwareKeySlotOverwrite: async ({ + request, + onRequestCancelled, + }) => { + const { hasCanceledModal, confirmed } = await new Promise<{ + hasCanceledModal: boolean; + confirmed: boolean; + }>(resolve => { + const { closeDialog } = ctx.modalsService.openImportantDialog({ + kind: 'hardware-key-slot-overwrite', + req: request, + onConfirm: () => { + resolve({ hasCanceledModal: false, confirmed: true }); + }, + onCancel: () => + resolve({ + hasCanceledModal: true, + confirmed: false, + }), + }); + + // tshd can cancel the request + onRequestCancelled(closeDialog); + }); + + if (hasCanceledModal) { + throw { + isCrossContextError: true, + name: 'AbortError', + message: 'hardware key slot overwrite modal closed by user', + }; + } + + return { confirmed }; + }, }; }