diff --git a/lib/srv/alpnproxy/local_proxy.go b/lib/srv/alpnproxy/local_proxy.go index 86fd64b246ea7..b863a2fae22a4 100644 --- a/lib/srv/alpnproxy/local_proxy.go +++ b/lib/srv/alpnproxy/local_proxy.go @@ -34,6 +34,10 @@ import ( "github.com/gravitational/teleport/lib/utils/aws" ) +// OnNewConnectionFunc is a callback triggered when a new downstream connection is +// accepted by the local proxy. +type OnNewConnectionFunc func(lp *LocalProxy, conn net.Conn) + // LocalProxy allows upgrading incoming connection to TLS where custom TLS values are set SNI ALPN and // updated connection is forwarded to remote ALPN SNI teleport proxy service. type LocalProxy struct { @@ -71,6 +75,11 @@ type LocalProxyConfig struct { Certs []tls.Certificate // AWSCredentials are AWS Credentials used by LocalProxy for request's signature verification. AWSCredentials *credentials.Credentials + // OnNewConnection is a callback triggered when a new downstream connection + // is accepted by the local proxy. + // + // Note that the callback blocks handling of the connection. + OnNewConnection OnNewConnectionFunc } // CheckAndSetDefaults verifies the constraints for LocalProxyConfig. @@ -128,6 +137,11 @@ func (l *LocalProxy) Start(ctx context.Context) error { log.WithError(err).Errorf("Failed to accept client connection.") return trace.Wrap(err) } + + if l.cfg.OnNewConnection != nil { + l.cfg.OnNewConnection(l, conn) + } + go func() { if err := l.handleDownstreamConnection(ctx, conn, l.cfg.SNI); err != nil { if utils.IsOKNetworkError(err) { diff --git a/lib/teleterm/api/proto/v1/service.proto b/lib/teleterm/api/proto/v1/service.proto index 70cc41ccc1a64..b28863713920b 100644 --- a/lib/teleterm/api/proto/v1/service.proto +++ b/lib/teleterm/api/proto/v1/service.proto @@ -91,6 +91,9 @@ service TerminalService { rpc LoginPasswordless(stream LoginPasswordlessRequest) returns (stream LoginPasswordlessResponse); // ClusterLogin logs out a user from cluster rpc Logout(LogoutRequest) returns (EmptyResponse); + + // TODO: Add comment. + rpc ClusterEvents(ClusterEventsRequest) returns (stream ClusterEvent); } // RemoveClusterRequest describes RemoveClusterRequest @@ -287,4 +290,21 @@ message GetAuthSettingsRequest { string cluster_uri = 1; } +message ClusterEventsRequest {} + +message ClusterEvent { + string cluster_uri = 1; + oneof event { + CertExpired cert_expired = 2; + NewGatewayConnectionAccepted new_gateway_connection_accepted = 3; + } +} + +message CertExpired {} + +message NewGatewayConnectionAccepted { + string gateway_uri = 1; + string target_uri = 2; +} + message EmptyResponse {} diff --git a/lib/teleterm/api/protogen/golang/v1/service.pb.go b/lib/teleterm/api/protogen/golang/v1/service.pb.go index 2880eaa8ea286..c391e5af1f148 100644 --- a/lib/teleterm/api/protogen/golang/v1/service.pb.go +++ b/lib/teleterm/api/protogen/golang/v1/service.pb.go @@ -1602,6 +1602,225 @@ func (x *GetAuthSettingsRequest) GetClusterUri() string { return "" } +type ClusterEventsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ClusterEventsRequest) Reset() { + *x = ClusterEventsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterEventsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterEventsRequest) ProtoMessage() {} + +func (x *ClusterEventsRequest) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterEventsRequest.ProtoReflect.Descriptor instead. +func (*ClusterEventsRequest) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{29} +} + +type ClusterEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ClusterUri string `protobuf:"bytes,1,opt,name=cluster_uri,json=clusterUri,proto3" json:"cluster_uri,omitempty"` + // Types that are assignable to Event: + // *ClusterEvent_CertExpired + // *ClusterEvent_NewGatewayConnectionAccepted + Event isClusterEvent_Event `protobuf_oneof:"event"` +} + +func (x *ClusterEvent) Reset() { + *x = ClusterEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ClusterEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ClusterEvent) ProtoMessage() {} + +func (x *ClusterEvent) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ClusterEvent.ProtoReflect.Descriptor instead. +func (*ClusterEvent) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{30} +} + +func (x *ClusterEvent) GetClusterUri() string { + if x != nil { + return x.ClusterUri + } + return "" +} + +func (m *ClusterEvent) GetEvent() isClusterEvent_Event { + if m != nil { + return m.Event + } + return nil +} + +func (x *ClusterEvent) GetCertExpired() *CertExpired { + if x, ok := x.GetEvent().(*ClusterEvent_CertExpired); ok { + return x.CertExpired + } + return nil +} + +func (x *ClusterEvent) GetNewGatewayConnectionAccepted() *NewGatewayConnectionAccepted { + if x, ok := x.GetEvent().(*ClusterEvent_NewGatewayConnectionAccepted); ok { + return x.NewGatewayConnectionAccepted + } + return nil +} + +type isClusterEvent_Event interface { + isClusterEvent_Event() +} + +type ClusterEvent_CertExpired struct { + CertExpired *CertExpired `protobuf:"bytes,2,opt,name=cert_expired,json=certExpired,proto3,oneof"` +} + +type ClusterEvent_NewGatewayConnectionAccepted struct { + NewGatewayConnectionAccepted *NewGatewayConnectionAccepted `protobuf:"bytes,3,opt,name=new_gateway_connection_accepted,json=newGatewayConnectionAccepted,proto3,oneof"` +} + +func (*ClusterEvent_CertExpired) isClusterEvent_Event() {} + +func (*ClusterEvent_NewGatewayConnectionAccepted) isClusterEvent_Event() {} + +type CertExpired struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *CertExpired) Reset() { + *x = CertExpired{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CertExpired) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CertExpired) ProtoMessage() {} + +func (x *CertExpired) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CertExpired.ProtoReflect.Descriptor instead. +func (*CertExpired) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{31} +} + +type NewGatewayConnectionAccepted struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + GatewayUri string `protobuf:"bytes,1,opt,name=gateway_uri,json=gatewayUri,proto3" json:"gateway_uri,omitempty"` + TargetUri string `protobuf:"bytes,2,opt,name=target_uri,json=targetUri,proto3" json:"target_uri,omitempty"` +} + +func (x *NewGatewayConnectionAccepted) Reset() { + *x = NewGatewayConnectionAccepted{} + if protoimpl.UnsafeEnabled { + mi := &file_v1_service_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NewGatewayConnectionAccepted) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NewGatewayConnectionAccepted) ProtoMessage() {} + +func (x *NewGatewayConnectionAccepted) ProtoReflect() protoreflect.Message { + mi := &file_v1_service_proto_msgTypes[32] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NewGatewayConnectionAccepted.ProtoReflect.Descriptor instead. +func (*NewGatewayConnectionAccepted) Descriptor() ([]byte, []int) { + return file_v1_service_proto_rawDescGZIP(), []int{32} +} + +func (x *NewGatewayConnectionAccepted) GetGatewayUri() string { + if x != nil { + return x.GatewayUri + } + return "" +} + +func (x *NewGatewayConnectionAccepted) GetTargetUri() string { + if x != nil { + return x.TargetUri + } + return "" +} + type EmptyResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1611,7 +1830,7 @@ type EmptyResponse struct { func (x *EmptyResponse) Reset() { *x = EmptyResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[29] + mi := &file_v1_service_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1624,7 +1843,7 @@ func (x *EmptyResponse) String() string { func (*EmptyResponse) ProtoMessage() {} func (x *EmptyResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[29] + mi := &file_v1_service_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1637,7 +1856,7 @@ func (x *EmptyResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use EmptyResponse.ProtoReflect.Descriptor instead. func (*EmptyResponse) Descriptor() ([]byte, []int) { - return file_v1_service_proto_rawDescGZIP(), []int{29} + return file_v1_service_proto_rawDescGZIP(), []int{33} } // LoginPasswordlessRequestInit contains fields needed to init the stream request. @@ -1653,7 +1872,7 @@ type LoginPasswordlessRequest_LoginPasswordlessRequestInit struct { func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) Reset() { *x = LoginPasswordlessRequest_LoginPasswordlessRequestInit{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[30] + mi := &file_v1_service_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1666,7 +1885,7 @@ func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) String() string func (*LoginPasswordlessRequest_LoginPasswordlessRequestInit) ProtoMessage() {} func (x *LoginPasswordlessRequest_LoginPasswordlessRequestInit) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[30] + mi := &file_v1_service_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1702,7 +1921,7 @@ type LoginPasswordlessRequest_LoginPasswordlessPINResponse struct { func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) Reset() { *x = LoginPasswordlessRequest_LoginPasswordlessPINResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[31] + mi := &file_v1_service_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1715,7 +1934,7 @@ func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) String() string func (*LoginPasswordlessRequest_LoginPasswordlessPINResponse) ProtoMessage() {} func (x *LoginPasswordlessRequest_LoginPasswordlessPINResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[31] + mi := &file_v1_service_proto_msgTypes[35] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1753,7 +1972,7 @@ type LoginPasswordlessRequest_LoginPasswordlessCredentialResponse struct { func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) Reset() { *x = LoginPasswordlessRequest_LoginPasswordlessCredentialResponse{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[32] + mi := &file_v1_service_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1766,7 +1985,7 @@ func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) String() func (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) ProtoMessage() {} func (x *LoginPasswordlessRequest_LoginPasswordlessCredentialResponse) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[32] + mi := &file_v1_service_proto_msgTypes[36] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1806,7 +2025,7 @@ type LoginRequest_LocalParams struct { func (x *LoginRequest_LocalParams) Reset() { *x = LoginRequest_LocalParams{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[33] + mi := &file_v1_service_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1819,7 +2038,7 @@ func (x *LoginRequest_LocalParams) String() string { func (*LoginRequest_LocalParams) ProtoMessage() {} func (x *LoginRequest_LocalParams) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[33] + mi := &file_v1_service_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1871,7 +2090,7 @@ type LoginRequest_SsoParams struct { func (x *LoginRequest_SsoParams) Reset() { *x = LoginRequest_SsoParams{} if protoimpl.UnsafeEnabled { - mi := &file_v1_service_proto_msgTypes[34] + mi := &file_v1_service_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1884,7 +2103,7 @@ func (x *LoginRequest_SsoParams) String() string { func (*LoginRequest_SsoParams) ProtoMessage() {} func (x *LoginRequest_SsoParams) ProtoReflect() protoreflect.Message { - mi := &file_v1_service_proto_msgTypes[34] + mi := &file_v1_service_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2103,148 +2322,179 @@ var file_v1_service_proto_rawDesc = []byte{ 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x0f, 0x0a, 0x0d, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x97, 0x01, 0x0a, 0x12, 0x50, - 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x70, - 0x74, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, - 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, - 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, - 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x50, 0x49, - 0x4e, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, - 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x54, 0x41, 0x50, 0x10, 0x02, - 0x12, 0x22, 0x0a, 0x1e, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, - 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x43, 0x52, 0x45, 0x44, 0x45, 0x4e, 0x54, 0x49, - 0x41, 0x4c, 0x10, 0x03, 0x32, 0xec, 0x0f, 0x0a, 0x0f, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x69, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x55, 0x72, 0x69, 0x22, 0x16, 0x0a, 0x14, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xfd, 0x01, 0x0a, 0x0c, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x75, 0x72, + 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x55, 0x72, 0x69, 0x12, 0x46, 0x0a, 0x0c, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x65, 0x72, 0x74, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x48, 0x00, 0x52, 0x0b, + 0x63, 0x65, 0x72, 0x74, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, 0x12, 0x7b, 0x0a, 0x1f, 0x6e, + 0x65, 0x77, 0x5f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x65, 0x77, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x48, 0x00, 0x52, 0x1c, 0x6e, 0x65, 0x77, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x22, 0x0d, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x64, + 0x22, 0x5e, 0x0a, 0x1c, 0x4e, 0x65, 0x77, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x65, 0x64, + 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x75, 0x72, 0x69, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x55, 0x72, + 0x69, 0x12, 0x1d, 0x0a, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x75, 0x72, 0x69, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x55, 0x72, 0x69, + 0x22, 0x0f, 0x0a, 0x0d, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x2a, 0x97, 0x01, 0x0a, 0x12, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, + 0x73, 0x73, 0x50, 0x72, 0x6f, 0x6d, 0x70, 0x74, 0x12, 0x23, 0x0a, 0x1f, 0x50, 0x41, 0x53, 0x53, + 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, + 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, + 0x17, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, + 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x50, 0x49, 0x4e, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x50, 0x41, + 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, + 0x54, 0x5f, 0x54, 0x41, 0x50, 0x10, 0x02, 0x12, 0x22, 0x0a, 0x1e, 0x50, 0x41, 0x53, 0x53, 0x57, + 0x4f, 0x52, 0x44, 0x4c, 0x45, 0x53, 0x53, 0x5f, 0x50, 0x52, 0x4f, 0x4d, 0x50, 0x54, 0x5f, 0x43, + 0x52, 0x45, 0x44, 0x45, 0x4e, 0x54, 0x49, 0x41, 0x4c, 0x10, 0x03, 0x32, 0xcf, 0x10, 0x0a, 0x0f, + 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x69, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x10, 0x4c, 0x69, + 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2d, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4c, 0x65, 0x61, 0x66, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x4c, 0x69, 0x73, + 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, + 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x73, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, - 0x62, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, - 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, - 0x12, 0x25, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0b, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, + 0x09, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4b, 0x75, + 0x62, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x59, 0x0a, 0x08, 0x4c, + 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x12, 0x25, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x54, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, + 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0a, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x60, 0x0a, 0x0d, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, - 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, + 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x12, 0x29, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, + 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, + 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x47, - 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x12, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, - 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5a, - 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, - 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, - 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x60, 0x0a, 0x0d, 0x52, 0x65, - 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x1f, 0x53, 0x65, 0x74, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, + 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x66, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x30, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, + 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, + 0x63, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, + 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x05, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, + 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0e, - 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x2b, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x47, 0x61, 0x74, - 0x65, 0x77, 0x61, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x7e, 0x0a, 0x1f, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, - 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x53, 0x75, 0x62, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, - 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x12, 0x66, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, - 0x63, 0x61, 0x6c, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x53, - 0x65, 0x74, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x50, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x63, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, - 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x41, 0x75, 0x74, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x54, 0x0a, - 0x0a, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x74, 0x65, + 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x11, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, + 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, + 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, + 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, + 0x12, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, + 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x61, 0x0a, 0x0d, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, - 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x12, 0x50, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x22, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, - 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x78, 0x0a, 0x11, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, - 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x6c, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x12, - 0x52, 0x0a, 0x06, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x12, 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x42, 0x33, 0x5a, 0x31, 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, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x76, 0x31, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x42, 0x33, 0x5a, + 0x31, 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, 0x6c, 0x69, 0x62, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x72, 0x6d, 0x2f, + 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -2260,7 +2510,7 @@ func file_v1_service_proto_rawDescGZIP() []byte { } var file_v1_service_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 35) +var file_v1_service_proto_msgTypes = make([]protoimpl.MessageInfo, 39) var file_v1_service_proto_goTypes = []interface{}{ (PasswordlessPrompt)(0), // 0: teleport.terminal.v1.PasswordlessPrompt (*RemoveClusterRequest)(nil), // 1: teleport.terminal.v1.RemoveClusterRequest @@ -2292,79 +2542,87 @@ var file_v1_service_proto_goTypes = []interface{}{ (*ListKubesResponse)(nil), // 27: teleport.terminal.v1.ListKubesResponse (*ListAppsResponse)(nil), // 28: teleport.terminal.v1.ListAppsResponse (*GetAuthSettingsRequest)(nil), // 29: teleport.terminal.v1.GetAuthSettingsRequest - (*EmptyResponse)(nil), // 30: teleport.terminal.v1.EmptyResponse - (*LoginPasswordlessRequest_LoginPasswordlessRequestInit)(nil), // 31: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit - (*LoginPasswordlessRequest_LoginPasswordlessPINResponse)(nil), // 32: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse - (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse)(nil), // 33: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse - (*LoginRequest_LocalParams)(nil), // 34: teleport.terminal.v1.LoginRequest.LocalParams - (*LoginRequest_SsoParams)(nil), // 35: teleport.terminal.v1.LoginRequest.SsoParams - (*Cluster)(nil), // 36: teleport.terminal.v1.Cluster - (*Database)(nil), // 37: teleport.terminal.v1.Database - (*Gateway)(nil), // 38: teleport.terminal.v1.Gateway - (*Server)(nil), // 39: teleport.terminal.v1.Server - (*Kube)(nil), // 40: teleport.terminal.v1.Kube - (*App)(nil), // 41: teleport.terminal.v1.App - (*AuthSettings)(nil), // 42: teleport.terminal.v1.AuthSettings + (*ClusterEventsRequest)(nil), // 30: teleport.terminal.v1.ClusterEventsRequest + (*ClusterEvent)(nil), // 31: teleport.terminal.v1.ClusterEvent + (*CertExpired)(nil), // 32: teleport.terminal.v1.CertExpired + (*NewGatewayConnectionAccepted)(nil), // 33: teleport.terminal.v1.NewGatewayConnectionAccepted + (*EmptyResponse)(nil), // 34: teleport.terminal.v1.EmptyResponse + (*LoginPasswordlessRequest_LoginPasswordlessRequestInit)(nil), // 35: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit + (*LoginPasswordlessRequest_LoginPasswordlessPINResponse)(nil), // 36: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse + (*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse)(nil), // 37: teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse + (*LoginRequest_LocalParams)(nil), // 38: teleport.terminal.v1.LoginRequest.LocalParams + (*LoginRequest_SsoParams)(nil), // 39: teleport.terminal.v1.LoginRequest.SsoParams + (*Cluster)(nil), // 40: teleport.terminal.v1.Cluster + (*Database)(nil), // 41: teleport.terminal.v1.Database + (*Gateway)(nil), // 42: teleport.terminal.v1.Gateway + (*Server)(nil), // 43: teleport.terminal.v1.Server + (*Kube)(nil), // 44: teleport.terminal.v1.Kube + (*App)(nil), // 45: teleport.terminal.v1.App + (*AuthSettings)(nil), // 46: teleport.terminal.v1.AuthSettings } var file_v1_service_proto_depIdxs = []int32{ 0, // 0: teleport.terminal.v1.LoginPasswordlessResponse.prompt:type_name -> teleport.terminal.v1.PasswordlessPrompt 4, // 1: teleport.terminal.v1.LoginPasswordlessResponse.credentials:type_name -> teleport.terminal.v1.CredentialInfo - 31, // 2: teleport.terminal.v1.LoginPasswordlessRequest.init:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit - 32, // 3: teleport.terminal.v1.LoginPasswordlessRequest.pin:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse - 33, // 4: teleport.terminal.v1.LoginPasswordlessRequest.credential:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse - 34, // 5: teleport.terminal.v1.LoginRequest.local:type_name -> teleport.terminal.v1.LoginRequest.LocalParams - 35, // 6: teleport.terminal.v1.LoginRequest.sso:type_name -> teleport.terminal.v1.LoginRequest.SsoParams - 36, // 7: teleport.terminal.v1.ListClustersResponse.clusters:type_name -> teleport.terminal.v1.Cluster - 37, // 8: teleport.terminal.v1.ListDatabasesResponse.databases:type_name -> teleport.terminal.v1.Database - 38, // 9: teleport.terminal.v1.ListGatewaysResponse.gateways:type_name -> teleport.terminal.v1.Gateway - 39, // 10: teleport.terminal.v1.ListServersResponse.servers:type_name -> teleport.terminal.v1.Server - 40, // 11: teleport.terminal.v1.ListKubesResponse.kubes:type_name -> teleport.terminal.v1.Kube - 41, // 12: teleport.terminal.v1.ListAppsResponse.apps:type_name -> teleport.terminal.v1.App - 11, // 13: teleport.terminal.v1.TerminalService.ListRootClusters:input_type -> teleport.terminal.v1.ListClustersRequest - 14, // 14: teleport.terminal.v1.TerminalService.ListLeafClusters:input_type -> teleport.terminal.v1.ListLeafClustersRequest - 13, // 15: teleport.terminal.v1.TerminalService.ListDatabases:input_type -> teleport.terminal.v1.ListDatabasesRequest - 16, // 16: teleport.terminal.v1.TerminalService.ListDatabaseUsers:input_type -> teleport.terminal.v1.ListDatabaseUsersRequest - 25, // 17: teleport.terminal.v1.TerminalService.ListServers:input_type -> teleport.terminal.v1.ListServersRequest - 9, // 18: teleport.terminal.v1.TerminalService.ListKubes:input_type -> teleport.terminal.v1.ListKubesRequest - 10, // 19: teleport.terminal.v1.TerminalService.ListApps:input_type -> teleport.terminal.v1.ListAppsRequest - 8, // 20: teleport.terminal.v1.TerminalService.AddCluster:input_type -> teleport.terminal.v1.AddClusterRequest - 1, // 21: teleport.terminal.v1.TerminalService.RemoveCluster:input_type -> teleport.terminal.v1.RemoveClusterRequest - 19, // 22: teleport.terminal.v1.TerminalService.ListGateways:input_type -> teleport.terminal.v1.ListGatewaysRequest - 18, // 23: teleport.terminal.v1.TerminalService.CreateGateway:input_type -> teleport.terminal.v1.CreateGatewayRequest - 21, // 24: teleport.terminal.v1.TerminalService.RemoveGateway:input_type -> teleport.terminal.v1.RemoveGatewayRequest - 22, // 25: teleport.terminal.v1.TerminalService.RestartGateway:input_type -> teleport.terminal.v1.RestartGatewayRequest - 23, // 26: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:input_type -> teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest - 24, // 27: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:input_type -> teleport.terminal.v1.SetGatewayLocalPortRequest - 29, // 28: teleport.terminal.v1.TerminalService.GetAuthSettings:input_type -> teleport.terminal.v1.GetAuthSettingsRequest - 2, // 29: teleport.terminal.v1.TerminalService.GetCluster:input_type -> teleport.terminal.v1.GetClusterRequest - 7, // 30: teleport.terminal.v1.TerminalService.Login:input_type -> teleport.terminal.v1.LoginRequest - 6, // 31: teleport.terminal.v1.TerminalService.LoginPasswordless:input_type -> teleport.terminal.v1.LoginPasswordlessRequest - 3, // 32: teleport.terminal.v1.TerminalService.Logout:input_type -> teleport.terminal.v1.LogoutRequest - 12, // 33: teleport.terminal.v1.TerminalService.ListRootClusters:output_type -> teleport.terminal.v1.ListClustersResponse - 12, // 34: teleport.terminal.v1.TerminalService.ListLeafClusters:output_type -> teleport.terminal.v1.ListClustersResponse - 15, // 35: teleport.terminal.v1.TerminalService.ListDatabases:output_type -> teleport.terminal.v1.ListDatabasesResponse - 17, // 36: teleport.terminal.v1.TerminalService.ListDatabaseUsers:output_type -> teleport.terminal.v1.ListDatabaseUsersResponse - 26, // 37: teleport.terminal.v1.TerminalService.ListServers:output_type -> teleport.terminal.v1.ListServersResponse - 27, // 38: teleport.terminal.v1.TerminalService.ListKubes:output_type -> teleport.terminal.v1.ListKubesResponse - 28, // 39: teleport.terminal.v1.TerminalService.ListApps:output_type -> teleport.terminal.v1.ListAppsResponse - 36, // 40: teleport.terminal.v1.TerminalService.AddCluster:output_type -> teleport.terminal.v1.Cluster - 30, // 41: teleport.terminal.v1.TerminalService.RemoveCluster:output_type -> teleport.terminal.v1.EmptyResponse - 20, // 42: teleport.terminal.v1.TerminalService.ListGateways:output_type -> teleport.terminal.v1.ListGatewaysResponse - 38, // 43: teleport.terminal.v1.TerminalService.CreateGateway:output_type -> teleport.terminal.v1.Gateway - 30, // 44: teleport.terminal.v1.TerminalService.RemoveGateway:output_type -> teleport.terminal.v1.EmptyResponse - 30, // 45: teleport.terminal.v1.TerminalService.RestartGateway:output_type -> teleport.terminal.v1.EmptyResponse - 38, // 46: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:output_type -> teleport.terminal.v1.Gateway - 38, // 47: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:output_type -> teleport.terminal.v1.Gateway - 42, // 48: teleport.terminal.v1.TerminalService.GetAuthSettings:output_type -> teleport.terminal.v1.AuthSettings - 36, // 49: teleport.terminal.v1.TerminalService.GetCluster:output_type -> teleport.terminal.v1.Cluster - 30, // 50: teleport.terminal.v1.TerminalService.Login:output_type -> teleport.terminal.v1.EmptyResponse - 5, // 51: teleport.terminal.v1.TerminalService.LoginPasswordless:output_type -> teleport.terminal.v1.LoginPasswordlessResponse - 30, // 52: teleport.terminal.v1.TerminalService.Logout:output_type -> teleport.terminal.v1.EmptyResponse - 33, // [33:53] is the sub-list for method output_type - 13, // [13:33] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name + 35, // 2: teleport.terminal.v1.LoginPasswordlessRequest.init:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessRequestInit + 36, // 3: teleport.terminal.v1.LoginPasswordlessRequest.pin:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessPINResponse + 37, // 4: teleport.terminal.v1.LoginPasswordlessRequest.credential:type_name -> teleport.terminal.v1.LoginPasswordlessRequest.LoginPasswordlessCredentialResponse + 38, // 5: teleport.terminal.v1.LoginRequest.local:type_name -> teleport.terminal.v1.LoginRequest.LocalParams + 39, // 6: teleport.terminal.v1.LoginRequest.sso:type_name -> teleport.terminal.v1.LoginRequest.SsoParams + 40, // 7: teleport.terminal.v1.ListClustersResponse.clusters:type_name -> teleport.terminal.v1.Cluster + 41, // 8: teleport.terminal.v1.ListDatabasesResponse.databases:type_name -> teleport.terminal.v1.Database + 42, // 9: teleport.terminal.v1.ListGatewaysResponse.gateways:type_name -> teleport.terminal.v1.Gateway + 43, // 10: teleport.terminal.v1.ListServersResponse.servers:type_name -> teleport.terminal.v1.Server + 44, // 11: teleport.terminal.v1.ListKubesResponse.kubes:type_name -> teleport.terminal.v1.Kube + 45, // 12: teleport.terminal.v1.ListAppsResponse.apps:type_name -> teleport.terminal.v1.App + 32, // 13: teleport.terminal.v1.ClusterEvent.cert_expired:type_name -> teleport.terminal.v1.CertExpired + 33, // 14: teleport.terminal.v1.ClusterEvent.new_gateway_connection_accepted:type_name -> teleport.terminal.v1.NewGatewayConnectionAccepted + 11, // 15: teleport.terminal.v1.TerminalService.ListRootClusters:input_type -> teleport.terminal.v1.ListClustersRequest + 14, // 16: teleport.terminal.v1.TerminalService.ListLeafClusters:input_type -> teleport.terminal.v1.ListLeafClustersRequest + 13, // 17: teleport.terminal.v1.TerminalService.ListDatabases:input_type -> teleport.terminal.v1.ListDatabasesRequest + 16, // 18: teleport.terminal.v1.TerminalService.ListDatabaseUsers:input_type -> teleport.terminal.v1.ListDatabaseUsersRequest + 25, // 19: teleport.terminal.v1.TerminalService.ListServers:input_type -> teleport.terminal.v1.ListServersRequest + 9, // 20: teleport.terminal.v1.TerminalService.ListKubes:input_type -> teleport.terminal.v1.ListKubesRequest + 10, // 21: teleport.terminal.v1.TerminalService.ListApps:input_type -> teleport.terminal.v1.ListAppsRequest + 8, // 22: teleport.terminal.v1.TerminalService.AddCluster:input_type -> teleport.terminal.v1.AddClusterRequest + 1, // 23: teleport.terminal.v1.TerminalService.RemoveCluster:input_type -> teleport.terminal.v1.RemoveClusterRequest + 19, // 24: teleport.terminal.v1.TerminalService.ListGateways:input_type -> teleport.terminal.v1.ListGatewaysRequest + 18, // 25: teleport.terminal.v1.TerminalService.CreateGateway:input_type -> teleport.terminal.v1.CreateGatewayRequest + 21, // 26: teleport.terminal.v1.TerminalService.RemoveGateway:input_type -> teleport.terminal.v1.RemoveGatewayRequest + 22, // 27: teleport.terminal.v1.TerminalService.RestartGateway:input_type -> teleport.terminal.v1.RestartGatewayRequest + 23, // 28: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:input_type -> teleport.terminal.v1.SetGatewayTargetSubresourceNameRequest + 24, // 29: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:input_type -> teleport.terminal.v1.SetGatewayLocalPortRequest + 29, // 30: teleport.terminal.v1.TerminalService.GetAuthSettings:input_type -> teleport.terminal.v1.GetAuthSettingsRequest + 2, // 31: teleport.terminal.v1.TerminalService.GetCluster:input_type -> teleport.terminal.v1.GetClusterRequest + 7, // 32: teleport.terminal.v1.TerminalService.Login:input_type -> teleport.terminal.v1.LoginRequest + 6, // 33: teleport.terminal.v1.TerminalService.LoginPasswordless:input_type -> teleport.terminal.v1.LoginPasswordlessRequest + 3, // 34: teleport.terminal.v1.TerminalService.Logout:input_type -> teleport.terminal.v1.LogoutRequest + 30, // 35: teleport.terminal.v1.TerminalService.ClusterEvents:input_type -> teleport.terminal.v1.ClusterEventsRequest + 12, // 36: teleport.terminal.v1.TerminalService.ListRootClusters:output_type -> teleport.terminal.v1.ListClustersResponse + 12, // 37: teleport.terminal.v1.TerminalService.ListLeafClusters:output_type -> teleport.terminal.v1.ListClustersResponse + 15, // 38: teleport.terminal.v1.TerminalService.ListDatabases:output_type -> teleport.terminal.v1.ListDatabasesResponse + 17, // 39: teleport.terminal.v1.TerminalService.ListDatabaseUsers:output_type -> teleport.terminal.v1.ListDatabaseUsersResponse + 26, // 40: teleport.terminal.v1.TerminalService.ListServers:output_type -> teleport.terminal.v1.ListServersResponse + 27, // 41: teleport.terminal.v1.TerminalService.ListKubes:output_type -> teleport.terminal.v1.ListKubesResponse + 28, // 42: teleport.terminal.v1.TerminalService.ListApps:output_type -> teleport.terminal.v1.ListAppsResponse + 40, // 43: teleport.terminal.v1.TerminalService.AddCluster:output_type -> teleport.terminal.v1.Cluster + 34, // 44: teleport.terminal.v1.TerminalService.RemoveCluster:output_type -> teleport.terminal.v1.EmptyResponse + 20, // 45: teleport.terminal.v1.TerminalService.ListGateways:output_type -> teleport.terminal.v1.ListGatewaysResponse + 42, // 46: teleport.terminal.v1.TerminalService.CreateGateway:output_type -> teleport.terminal.v1.Gateway + 34, // 47: teleport.terminal.v1.TerminalService.RemoveGateway:output_type -> teleport.terminal.v1.EmptyResponse + 34, // 48: teleport.terminal.v1.TerminalService.RestartGateway:output_type -> teleport.terminal.v1.EmptyResponse + 42, // 49: teleport.terminal.v1.TerminalService.SetGatewayTargetSubresourceName:output_type -> teleport.terminal.v1.Gateway + 42, // 50: teleport.terminal.v1.TerminalService.SetGatewayLocalPort:output_type -> teleport.terminal.v1.Gateway + 46, // 51: teleport.terminal.v1.TerminalService.GetAuthSettings:output_type -> teleport.terminal.v1.AuthSettings + 40, // 52: teleport.terminal.v1.TerminalService.GetCluster:output_type -> teleport.terminal.v1.Cluster + 34, // 53: teleport.terminal.v1.TerminalService.Login:output_type -> teleport.terminal.v1.EmptyResponse + 5, // 54: teleport.terminal.v1.TerminalService.LoginPasswordless:output_type -> teleport.terminal.v1.LoginPasswordlessResponse + 34, // 55: teleport.terminal.v1.TerminalService.Logout:output_type -> teleport.terminal.v1.EmptyResponse + 31, // 56: teleport.terminal.v1.TerminalService.ClusterEvents:output_type -> teleport.terminal.v1.ClusterEvent + 36, // [36:57] is the sub-list for method output_type + 15, // [15:36] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_v1_service_proto_init() } @@ -2729,7 +2987,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*EmptyResponse); i { + switch v := v.(*ClusterEventsRequest); i { case 0: return &v.state case 1: @@ -2741,7 +2999,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessRequestInit); i { + switch v := v.(*ClusterEvent); i { case 0: return &v.state case 1: @@ -2753,7 +3011,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessPINResponse); i { + switch v := v.(*CertExpired); i { case 0: return &v.state case 1: @@ -2765,7 +3023,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse); i { + switch v := v.(*NewGatewayConnectionAccepted); i { case 0: return &v.state case 1: @@ -2777,7 +3035,7 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*LoginRequest_LocalParams); i { + switch v := v.(*EmptyResponse); i { case 0: return &v.state case 1: @@ -2789,6 +3047,54 @@ func file_v1_service_proto_init() { } } file_v1_service_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessRequestInit); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessPINResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginPasswordlessRequest_LoginPasswordlessCredentialResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*LoginRequest_LocalParams); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_v1_service_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*LoginRequest_SsoParams); i { case 0: return &v.state @@ -2810,13 +3116,17 @@ func file_v1_service_proto_init() { (*LoginRequest_Local)(nil), (*LoginRequest_Sso)(nil), } + file_v1_service_proto_msgTypes[30].OneofWrappers = []interface{}{ + (*ClusterEvent_CertExpired)(nil), + (*ClusterEvent_NewGatewayConnectionAccepted)(nil), + } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_v1_service_proto_rawDesc, NumEnums: 1, - NumMessages: 35, + NumMessages: 39, NumExtensions: 0, NumServices: 1, }, @@ -2904,6 +3214,8 @@ type TerminalServiceClient interface { LoginPasswordless(ctx context.Context, opts ...grpc.CallOption) (TerminalService_LoginPasswordlessClient, error) // ClusterLogin logs out a user from cluster Logout(ctx context.Context, in *LogoutRequest, opts ...grpc.CallOption) (*EmptyResponse, error) + // TODO: Add comment. + ClusterEvents(ctx context.Context, in *ClusterEventsRequest, opts ...grpc.CallOption) (TerminalService_ClusterEventsClient, error) } type terminalServiceClient struct { @@ -3116,6 +3428,38 @@ func (c *terminalServiceClient) Logout(ctx context.Context, in *LogoutRequest, o return out, nil } +func (c *terminalServiceClient) ClusterEvents(ctx context.Context, in *ClusterEventsRequest, opts ...grpc.CallOption) (TerminalService_ClusterEventsClient, error) { + stream, err := c.cc.NewStream(ctx, &_TerminalService_serviceDesc.Streams[1], "/teleport.terminal.v1.TerminalService/ClusterEvents", opts...) + if err != nil { + return nil, err + } + x := &terminalServiceClusterEventsClient{stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +type TerminalService_ClusterEventsClient interface { + Recv() (*ClusterEvent, error) + grpc.ClientStream +} + +type terminalServiceClusterEventsClient struct { + grpc.ClientStream +} + +func (x *terminalServiceClusterEventsClient) Recv() (*ClusterEvent, error) { + m := new(ClusterEvent) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil +} + // TerminalServiceServer is the server API for TerminalService service. type TerminalServiceServer interface { // ListRootClusters lists root clusters @@ -3179,6 +3523,8 @@ type TerminalServiceServer interface { LoginPasswordless(TerminalService_LoginPasswordlessServer) error // ClusterLogin logs out a user from cluster Logout(context.Context, *LogoutRequest) (*EmptyResponse, error) + // TODO: Add comment. + ClusterEvents(*ClusterEventsRequest, TerminalService_ClusterEventsServer) error } // UnimplementedTerminalServiceServer can be embedded to have forward compatible implementations. @@ -3245,6 +3591,9 @@ func (*UnimplementedTerminalServiceServer) LoginPasswordless(TerminalService_Log func (*UnimplementedTerminalServiceServer) Logout(context.Context, *LogoutRequest) (*EmptyResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method Logout not implemented") } +func (*UnimplementedTerminalServiceServer) ClusterEvents(*ClusterEventsRequest, TerminalService_ClusterEventsServer) error { + return status.Errorf(codes.Unimplemented, "method ClusterEvents not implemented") +} func RegisterTerminalServiceServer(s *grpc.Server, srv TerminalServiceServer) { s.RegisterService(&_TerminalService_serviceDesc, srv) @@ -3618,6 +3967,27 @@ func _TerminalService_Logout_Handler(srv interface{}, ctx context.Context, dec f return interceptor(ctx, in, info, handler) } +func _TerminalService_ClusterEvents_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(ClusterEventsRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(TerminalServiceServer).ClusterEvents(m, &terminalServiceClusterEventsServer{stream}) +} + +type TerminalService_ClusterEventsServer interface { + Send(*ClusterEvent) error + grpc.ServerStream +} + +type terminalServiceClusterEventsServer struct { + grpc.ServerStream +} + +func (x *terminalServiceClusterEventsServer) Send(m *ClusterEvent) error { + return x.ServerStream.SendMsg(m) +} + var _TerminalService_serviceDesc = grpc.ServiceDesc{ ServiceName: "teleport.terminal.v1.TerminalService", HandlerType: (*TerminalServiceServer)(nil), @@ -3706,6 +4076,11 @@ var _TerminalService_serviceDesc = grpc.ServiceDesc{ ServerStreams: true, ClientStreams: true, }, + { + StreamName: "ClusterEvents", + Handler: _TerminalService_ClusterEvents_Handler, + ServerStreams: true, + }, }, Metadata: "v1/service.proto", } diff --git a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts index 8d15635b2c1dc..e7d6d03d160c0 100644 --- a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts +++ b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.d.ts @@ -35,6 +35,7 @@ interface ITerminalServiceService extends grpc.ServiceDefinition { @@ -217,6 +218,15 @@ interface ITerminalServiceService_ILogout extends grpc.MethodDefinition; responseDeserialize: grpc.deserialize; } +interface ITerminalServiceService_IClusterEvents extends grpc.MethodDefinition { + path: "/teleport.terminal.v1.TerminalService/ClusterEvents"; + requestStream: false; + responseStream: true; + requestSerialize: grpc.serialize; + requestDeserialize: grpc.deserialize; + responseSerialize: grpc.serialize; + responseDeserialize: grpc.deserialize; +} export const TerminalServiceService: ITerminalServiceService; @@ -241,6 +251,7 @@ export interface ITerminalServiceServer { login: grpc.handleUnaryCall; loginPasswordless: grpc.handleBidiStreamingCall; logout: grpc.handleUnaryCall; + clusterEvents: grpc.handleServerStreamingCall; } export interface ITerminalServiceClient { @@ -304,6 +315,8 @@ export interface ITerminalServiceClient { logout(request: v1_service_pb.LogoutRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; + clusterEvents(request: v1_service_pb.ClusterEventsRequest, options?: Partial): grpc.ClientReadableStream; + clusterEvents(request: v1_service_pb.ClusterEventsRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream; } export class TerminalServiceClient extends grpc.Client implements ITerminalServiceClient { @@ -367,4 +380,6 @@ export class TerminalServiceClient extends grpc.Client implements ITerminalServi public logout(request: v1_service_pb.LogoutRequest, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; public logout(request: v1_service_pb.LogoutRequest, metadata: grpc.Metadata, options: Partial, callback: (error: grpc.ServiceError | null, response: v1_service_pb.EmptyResponse) => void): grpc.ClientUnaryCall; + public clusterEvents(request: v1_service_pb.ClusterEventsRequest, options?: Partial): grpc.ClientReadableStream; + public clusterEvents(request: v1_service_pb.ClusterEventsRequest, metadata?: grpc.Metadata, options?: Partial): grpc.ClientReadableStream; } diff --git a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js index 5c26581215393..45c51aa557077 100644 --- a/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js +++ b/lib/teleterm/api/protogen/js/v1/service_grpc_pb.js @@ -59,6 +59,28 @@ function deserialize_teleport_terminal_v1_Cluster(buffer_arg) { return v1_cluster_pb.Cluster.deserializeBinary(new Uint8Array(buffer_arg)); } +function serialize_teleport_terminal_v1_ClusterEvent(arg) { + if (!(arg instanceof v1_service_pb.ClusterEvent)) { + throw new Error('Expected argument of type teleport.terminal.v1.ClusterEvent'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_teleport_terminal_v1_ClusterEvent(buffer_arg) { + return v1_service_pb.ClusterEvent.deserializeBinary(new Uint8Array(buffer_arg)); +} + +function serialize_teleport_terminal_v1_ClusterEventsRequest(arg) { + if (!(arg instanceof v1_service_pb.ClusterEventsRequest)) { + throw new Error('Expected argument of type teleport.terminal.v1.ClusterEventsRequest'); + } + return Buffer.from(arg.serializeBinary()); +} + +function deserialize_teleport_terminal_v1_ClusterEventsRequest(buffer_arg) { + return v1_service_pb.ClusterEventsRequest.deserializeBinary(new Uint8Array(buffer_arg)); +} + function serialize_teleport_terminal_v1_CreateGatewayRequest(arg) { if (!(arg instanceof v1_service_pb.CreateGatewayRequest)) { throw new Error('Expected argument of type teleport.terminal.v1.CreateGatewayRequest'); @@ -642,6 +664,18 @@ logout: { responseSerialize: serialize_teleport_terminal_v1_EmptyResponse, responseDeserialize: deserialize_teleport_terminal_v1_EmptyResponse, }, + // TODO: Add comment. +clusterEvents: { + path: '/teleport.terminal.v1.TerminalService/ClusterEvents', + requestStream: false, + responseStream: true, + requestType: v1_service_pb.ClusterEventsRequest, + responseType: v1_service_pb.ClusterEvent, + requestSerialize: serialize_teleport_terminal_v1_ClusterEventsRequest, + requestDeserialize: deserialize_teleport_terminal_v1_ClusterEventsRequest, + responseSerialize: serialize_teleport_terminal_v1_ClusterEvent, + responseDeserialize: deserialize_teleport_terminal_v1_ClusterEvent, + }, }; exports.TerminalServiceClient = grpc.makeGenericClientConstructor(TerminalServiceService); diff --git a/lib/teleterm/api/protogen/js/v1/service_pb.d.ts b/lib/teleterm/api/protogen/js/v1/service_pb.d.ts index 23f8e87e8f280..dba3ee6854a07 100644 --- a/lib/teleterm/api/protogen/js/v1/service_pb.d.ts +++ b/lib/teleterm/api/protogen/js/v1/service_pb.d.ts @@ -838,6 +838,112 @@ export namespace GetAuthSettingsRequest { } } +export class ClusterEventsRequest extends jspb.Message { + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ClusterEventsRequest.AsObject; + static toObject(includeInstance: boolean, msg: ClusterEventsRequest): ClusterEventsRequest.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ClusterEventsRequest, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ClusterEventsRequest; + static deserializeBinaryFromReader(message: ClusterEventsRequest, reader: jspb.BinaryReader): ClusterEventsRequest; +} + +export namespace ClusterEventsRequest { + export type AsObject = { + } +} + +export class ClusterEvent extends jspb.Message { + getClusterUri(): string; + setClusterUri(value: string): ClusterEvent; + + + hasCertExpired(): boolean; + clearCertExpired(): void; + getCertExpired(): CertExpired | undefined; + setCertExpired(value?: CertExpired): ClusterEvent; + + + hasNewGatewayConnectionAccepted(): boolean; + clearNewGatewayConnectionAccepted(): void; + getNewGatewayConnectionAccepted(): NewGatewayConnectionAccepted | undefined; + setNewGatewayConnectionAccepted(value?: NewGatewayConnectionAccepted): ClusterEvent; + + + getEventCase(): ClusterEvent.EventCase; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): ClusterEvent.AsObject; + static toObject(includeInstance: boolean, msg: ClusterEvent): ClusterEvent.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: ClusterEvent, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): ClusterEvent; + static deserializeBinaryFromReader(message: ClusterEvent, reader: jspb.BinaryReader): ClusterEvent; +} + +export namespace ClusterEvent { + export type AsObject = { + clusterUri: string, + certExpired?: CertExpired.AsObject, + newGatewayConnectionAccepted?: NewGatewayConnectionAccepted.AsObject, + } + + export enum EventCase { + EVENT_NOT_SET = 0, + + CERT_EXPIRED = 2, + + NEW_GATEWAY_CONNECTION_ACCEPTED = 3, + + } + +} + +export class CertExpired extends jspb.Message { + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): CertExpired.AsObject; + static toObject(includeInstance: boolean, msg: CertExpired): CertExpired.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: CertExpired, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): CertExpired; + static deserializeBinaryFromReader(message: CertExpired, reader: jspb.BinaryReader): CertExpired; +} + +export namespace CertExpired { + export type AsObject = { + } +} + +export class NewGatewayConnectionAccepted extends jspb.Message { + getGatewayUri(): string; + setGatewayUri(value: string): NewGatewayConnectionAccepted; + + getTargetUri(): string; + setTargetUri(value: string): NewGatewayConnectionAccepted; + + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): NewGatewayConnectionAccepted.AsObject; + static toObject(includeInstance: boolean, msg: NewGatewayConnectionAccepted): NewGatewayConnectionAccepted.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: NewGatewayConnectionAccepted, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): NewGatewayConnectionAccepted; + static deserializeBinaryFromReader(message: NewGatewayConnectionAccepted, reader: jspb.BinaryReader): NewGatewayConnectionAccepted; +} + +export namespace NewGatewayConnectionAccepted { + export type AsObject = { + gatewayUri: string, + targetUri: string, + } +} + export class EmptyResponse extends jspb.Message { serializeBinary(): Uint8Array; diff --git a/lib/teleterm/api/protogen/js/v1/service_pb.js b/lib/teleterm/api/protogen/js/v1/service_pb.js index 6a8d8a65f87cd..90752fc1b1ad7 100644 --- a/lib/teleterm/api/protogen/js/v1/service_pb.js +++ b/lib/teleterm/api/protogen/js/v1/service_pb.js @@ -30,6 +30,10 @@ goog.object.extend(proto, v1_kube_pb); var v1_server_pb = require('../v1/server_pb.js'); goog.object.extend(proto, v1_server_pb); goog.exportSymbol('proto.teleport.terminal.v1.AddClusterRequest', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.CertExpired', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.ClusterEvent', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.ClusterEvent.EventCase', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.ClusterEventsRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.CreateGatewayRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.CredentialInfo', null, global); goog.exportSymbol('proto.teleport.terminal.v1.EmptyResponse', null, global); @@ -61,6 +65,7 @@ goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.LocalParams', null, g goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.ParamsCase', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LoginRequest.SsoParams', null, global); goog.exportSymbol('proto.teleport.terminal.v1.LogoutRequest', null, global); +goog.exportSymbol('proto.teleport.terminal.v1.NewGatewayConnectionAccepted', null, global); goog.exportSymbol('proto.teleport.terminal.v1.PasswordlessPrompt', null, global); goog.exportSymbol('proto.teleport.terminal.v1.RemoveClusterRequest', null, global); goog.exportSymbol('proto.teleport.terminal.v1.RemoveGatewayRequest', null, global); @@ -781,6 +786,90 @@ if (goog.DEBUG && !COMPILED) { */ proto.teleport.terminal.v1.GetAuthSettingsRequest.displayName = 'proto.teleport.terminal.v1.GetAuthSettingsRequest'; } +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.ClusterEventsRequest = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.ClusterEventsRequest, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.ClusterEventsRequest.displayName = 'proto.teleport.terminal.v1.ClusterEventsRequest'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.ClusterEvent = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, proto.teleport.terminal.v1.ClusterEvent.oneofGroups_); +}; +goog.inherits(proto.teleport.terminal.v1.ClusterEvent, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.ClusterEvent.displayName = 'proto.teleport.terminal.v1.ClusterEvent'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.CertExpired = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.CertExpired, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.CertExpired.displayName = 'proto.teleport.terminal.v1.CertExpired'; +} +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.teleport.terminal.v1.NewGatewayConnectionAccepted, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.teleport.terminal.v1.NewGatewayConnectionAccepted.displayName = 'proto.teleport.terminal.v1.NewGatewayConnectionAccepted'; +} /** * Generated by JsPbCodeGenerator. * @param {Array=} opt_data Optional initial data array, typically from a @@ -6006,6 +6095,626 @@ proto.teleport.terminal.v1.GetAuthSettingsRequest.prototype.setClusterUri = func +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.ClusterEventsRequest.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.ClusterEventsRequest.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.ClusterEventsRequest} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.ClusterEventsRequest.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.ClusterEventsRequest} + */ +proto.teleport.terminal.v1.ClusterEventsRequest.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.ClusterEventsRequest; + return proto.teleport.terminal.v1.ClusterEventsRequest.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.ClusterEventsRequest} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.ClusterEventsRequest} + */ +proto.teleport.terminal.v1.ClusterEventsRequest.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.ClusterEventsRequest.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.ClusterEventsRequest.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.ClusterEventsRequest} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.ClusterEventsRequest.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + +/** + * Oneof group definitions for this message. Each group defines the field + * numbers belonging to that group. When of these fields' value is set, all + * other fields in the group are cleared. During deserialization, if multiple + * fields are encountered for a group, only the last value seen will be kept. + * @private {!Array>} + * @const + */ +proto.teleport.terminal.v1.ClusterEvent.oneofGroups_ = [[2,3]]; + +/** + * @enum {number} + */ +proto.teleport.terminal.v1.ClusterEvent.EventCase = { + EVENT_NOT_SET: 0, + CERT_EXPIRED: 2, + NEW_GATEWAY_CONNECTION_ACCEPTED: 3 +}; + +/** + * @return {proto.teleport.terminal.v1.ClusterEvent.EventCase} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.getEventCase = function() { + return /** @type {proto.teleport.terminal.v1.ClusterEvent.EventCase} */(jspb.Message.computeOneofCase(this, proto.teleport.terminal.v1.ClusterEvent.oneofGroups_[0])); +}; + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.ClusterEvent.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.ClusterEvent} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.ClusterEvent.toObject = function(includeInstance, msg) { + var f, obj = { + clusterUri: jspb.Message.getFieldWithDefault(msg, 1, ""), + certExpired: (f = msg.getCertExpired()) && proto.teleport.terminal.v1.CertExpired.toObject(includeInstance, f), + newGatewayConnectionAccepted: (f = msg.getNewGatewayConnectionAccepted()) && proto.teleport.terminal.v1.NewGatewayConnectionAccepted.toObject(includeInstance, f) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.ClusterEvent} + */ +proto.teleport.terminal.v1.ClusterEvent.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.ClusterEvent; + return proto.teleport.terminal.v1.ClusterEvent.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.ClusterEvent} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.ClusterEvent} + */ +proto.teleport.terminal.v1.ClusterEvent.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setClusterUri(value); + break; + case 2: + var value = new proto.teleport.terminal.v1.CertExpired; + reader.readMessage(value,proto.teleport.terminal.v1.CertExpired.deserializeBinaryFromReader); + msg.setCertExpired(value); + break; + case 3: + var value = new proto.teleport.terminal.v1.NewGatewayConnectionAccepted; + reader.readMessage(value,proto.teleport.terminal.v1.NewGatewayConnectionAccepted.deserializeBinaryFromReader); + msg.setNewGatewayConnectionAccepted(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.ClusterEvent.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.ClusterEvent} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.ClusterEvent.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getClusterUri(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getCertExpired(); + if (f != null) { + writer.writeMessage( + 2, + f, + proto.teleport.terminal.v1.CertExpired.serializeBinaryToWriter + ); + } + f = message.getNewGatewayConnectionAccepted(); + if (f != null) { + writer.writeMessage( + 3, + f, + proto.teleport.terminal.v1.NewGatewayConnectionAccepted.serializeBinaryToWriter + ); + } +}; + + +/** + * optional string cluster_uri = 1; + * @return {string} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.getClusterUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.ClusterEvent} returns this + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.setClusterUri = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional CertExpired cert_expired = 2; + * @return {?proto.teleport.terminal.v1.CertExpired} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.getCertExpired = function() { + return /** @type{?proto.teleport.terminal.v1.CertExpired} */ ( + jspb.Message.getWrapperField(this, proto.teleport.terminal.v1.CertExpired, 2)); +}; + + +/** + * @param {?proto.teleport.terminal.v1.CertExpired|undefined} value + * @return {!proto.teleport.terminal.v1.ClusterEvent} returns this +*/ +proto.teleport.terminal.v1.ClusterEvent.prototype.setCertExpired = function(value) { + return jspb.Message.setOneofWrapperField(this, 2, proto.teleport.terminal.v1.ClusterEvent.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.teleport.terminal.v1.ClusterEvent} returns this + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.clearCertExpired = function() { + return this.setCertExpired(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.hasCertExpired = function() { + return jspb.Message.getField(this, 2) != null; +}; + + +/** + * optional NewGatewayConnectionAccepted new_gateway_connection_accepted = 3; + * @return {?proto.teleport.terminal.v1.NewGatewayConnectionAccepted} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.getNewGatewayConnectionAccepted = function() { + return /** @type{?proto.teleport.terminal.v1.NewGatewayConnectionAccepted} */ ( + jspb.Message.getWrapperField(this, proto.teleport.terminal.v1.NewGatewayConnectionAccepted, 3)); +}; + + +/** + * @param {?proto.teleport.terminal.v1.NewGatewayConnectionAccepted|undefined} value + * @return {!proto.teleport.terminal.v1.ClusterEvent} returns this +*/ +proto.teleport.terminal.v1.ClusterEvent.prototype.setNewGatewayConnectionAccepted = function(value) { + return jspb.Message.setOneofWrapperField(this, 3, proto.teleport.terminal.v1.ClusterEvent.oneofGroups_[0], value); +}; + + +/** + * Clears the message field making it undefined. + * @return {!proto.teleport.terminal.v1.ClusterEvent} returns this + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.clearNewGatewayConnectionAccepted = function() { + return this.setNewGatewayConnectionAccepted(undefined); +}; + + +/** + * Returns whether this field is set. + * @return {boolean} + */ +proto.teleport.terminal.v1.ClusterEvent.prototype.hasNewGatewayConnectionAccepted = function() { + return jspb.Message.getField(this, 3) != null; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.CertExpired.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.CertExpired.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.CertExpired} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.CertExpired.toObject = function(includeInstance, msg) { + var f, obj = { + + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.CertExpired} + */ +proto.teleport.terminal.v1.CertExpired.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.CertExpired; + return proto.teleport.terminal.v1.CertExpired.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.CertExpired} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.CertExpired} + */ +proto.teleport.terminal.v1.CertExpired.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.CertExpired.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.CertExpired.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.CertExpired} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.CertExpired.serializeBinaryToWriter = function(message, writer) { + var f = undefined; +}; + + + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.toObject = function(opt_includeInstance) { + return proto.teleport.terminal.v1.NewGatewayConnectionAccepted.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.toObject = function(includeInstance, msg) { + var f, obj = { + gatewayUri: jspb.Message.getFieldWithDefault(msg, 1, ""), + targetUri: jspb.Message.getFieldWithDefault(msg, 2, "") + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.teleport.terminal.v1.NewGatewayConnectionAccepted; + return proto.teleport.terminal.v1.NewGatewayConnectionAccepted.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setGatewayUri(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setTargetUri(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.teleport.terminal.v1.NewGatewayConnectionAccepted.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getGatewayUri(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getTargetUri(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } +}; + + +/** + * optional string gateway_uri = 1; + * @return {string} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.getGatewayUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} returns this + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.setGatewayUri = function(value) { + return jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string target_uri = 2; + * @return {string} + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.getTargetUri = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** + * @param {string} value + * @return {!proto.teleport.terminal.v1.NewGatewayConnectionAccepted} returns this + */ +proto.teleport.terminal.v1.NewGatewayConnectionAccepted.prototype.setTargetUri = function(value) { + return jspb.Message.setProto3StringField(this, 2, value); +}; + + + + + if (jspb.Message.GENERATE_TO_OBJECT) { /** * Creates an object representation of this proto. diff --git a/lib/teleterm/apiserver/handler/handler_cluster_events.go b/lib/teleterm/apiserver/handler/handler_cluster_events.go new file mode 100644 index 0000000000000..05088e8d1b5ac --- /dev/null +++ b/lib/teleterm/apiserver/handler/handler_cluster_events.go @@ -0,0 +1,62 @@ +// Copyright 2022 Gravitational, Inc +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package handler + +import ( + "time" + + api "github.com/gravitational/teleport/lib/teleterm/api/protogen/golang/v1" + + "github.com/gravitational/trace" +) + +func (s *Handler) ClusterEvents(_ *api.ClusterEventsRequest, stream api.TerminalService_ClusterEventsServer) error { + // TODO: Move the logic from this handler to a separate place. + log := s.DaemonService.Log().WithField(trace.Component, "conn:cevents") + + select { + case <-time.After(time.Second): + message := "Couldn't acquire lock within a second, another stream is already active." + log.Info(message) + return trace.AlreadyExists(message) + case <-stream.Context().Done(): + log.Info("The client has disconnected while waiting for the lock, closing the stream.") + return nil + case s.DaemonService.ClusterEventsSem <- struct{}{}: + defer func() { <-s.DaemonService.ClusterEventsSem }() + } + + log.Info("Opened the stream.") + + for { + select { + case <-stream.Context().Done(): + log.Info("The client has disconnected, closing the stream.") + return nil + case clusterEvent, ok := <-s.DaemonService.ClusterEventsC(): + if !ok { + log.Info("The ClusterEvents channel has been closed, closing the stream.") + return nil + } + + log.Debugf("Sending a message: %v", clusterEvent) + + if err := stream.Send(clusterEvent); err != nil { + log.WithError(err).Error("Failed to send a message, closing the stream.") + return err + } + } + } +} diff --git a/lib/teleterm/clusters/cluster_gateways.go b/lib/teleterm/clusters/cluster_gateways.go index a1558501cd713..4c1883946e8f8 100644 --- a/lib/teleterm/clusters/cluster_gateways.go +++ b/lib/teleterm/clusters/cluster_gateways.go @@ -36,6 +36,7 @@ type CreateGatewayParams struct { LocalPort string CLICommandProvider gateway.CLICommandProvider TCPPortAllocator gateway.TCPPortAllocator + OnNewConnection gateway.OnNewConnectionFunc } // CreateGateway creates a gateway @@ -60,9 +61,10 @@ func (c *Cluster) CreateGateway(ctx context.Context, params CreateGatewayParams) CertPath: c.status.DatabaseCertPathForCluster(c.clusterClient.SiteName, db.GetName()), Insecure: c.clusterClient.InsecureSkipVerify, WebProxyAddr: c.clusterClient.WebProxyAddr, - Log: c.Log.WithField("gateway", params.TargetURI), + Log: c.Log, CLICommandProvider: params.CLICommandProvider, TCPPortAllocator: params.TCPPortAllocator, + OnNewConnection: params.OnNewConnection, }) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/teleterm/daemon/daemon.go b/lib/teleterm/daemon/daemon.go index b6ddf9083c1e8..8c6f997c79511 100644 --- a/lib/teleterm/daemon/daemon.go +++ b/lib/teleterm/daemon/daemon.go @@ -19,10 +19,13 @@ import ( "sync" "github.com/gravitational/teleport/lib/client/db/dbcmd" + api "github.com/gravitational/teleport/lib/teleterm/api/protogen/golang/v1" + "github.com/gravitational/teleport/lib/teleterm/api/uri" "github.com/gravitational/teleport/lib/teleterm/clusters" "github.com/gravitational/teleport/lib/teleterm/gateway" "github.com/gravitational/trace" + "github.com/sirupsen/logrus" ) // New creates an instance of Daemon service @@ -32,8 +35,10 @@ func New(cfg Config) (*Service, error) { } return &Service{ - cfg: &cfg, - gateways: make(map[string]*gateway.Gateway), + cfg: &cfg, + gateways: make(map[string]*gateway.Gateway), + clusterEventsC: make(chan *api.ClusterEvent), + ClusterEventsSem: make(chan struct{}, 1), }, nil } @@ -148,6 +153,35 @@ func (s *Service) createGateway(ctx context.Context, params CreateGatewayParams) LocalPort: params.LocalPort, CLICommandProvider: cliCommandProvider, TCPPortAllocator: s.cfg.TCPPortAllocator, + // TODO: Add test that makes sure NewWithLocalPort properly copies OnNewConnection. + OnNewConnection: func(gatewayURI uri.ResourceURI, targetURI string) { + // TODO Refactor targetURI from string to uri.ResourceURI. + // https://github.com/gravitational/teleport/issues/15953 + clusterURI, err := uri.ParseClusterURI(targetURI) + if err != nil { + s.Log().WithError(err).Warnf( + "Malformed gateway target URI (%s), could not parse it into uri.ResourceURI", + targetURI, + ) + return + } + + clusterEvent := &api.ClusterEvent{ + ClusterUri: clusterURI.String(), + Event: &api.ClusterEvent_NewGatewayConnectionAccepted{ + NewGatewayConnectionAccepted: &api.NewGatewayConnectionAccepted{ + GatewayUri: gatewayURI.String(), + TargetUri: targetURI, + }, + }, + } + + s.Log().Debug("Sending ClusterEvent to clusterEventsC") + + s.clusterEventsC <- clusterEvent + + s.Log().Debug("Message sent to clusterEventsC") + }, } gateway, err := s.cfg.GatewayCreator.CreateGateway(ctx, clusterCreateGatewayParams) @@ -372,9 +406,21 @@ func (s *Service) Stop() { s.mu.RLock() defer s.mu.RUnlock() + s.Log().Info("Stopping") + for _, gateway := range s.gateways { gateway.Close() } + + close(s.clusterEventsC) +} + +func (s *Service) Log() *logrus.Entry { + return s.cfg.Log +} + +func (s *Service) ClusterEventsC() <-chan *api.ClusterEvent { + return s.clusterEventsC } // Service is the daemon service @@ -383,7 +429,9 @@ type Service struct { mu sync.RWMutex // gateways holds the long-running gateways for resources on different clusters. So far it's been // used mostly for database gateways but it has potential to be used for app access as well. - gateways map[string]*gateway.Gateway + gateways map[string]*gateway.Gateway + clusterEventsC chan *api.ClusterEvent + ClusterEventsSem chan struct{} } type CreateGatewayParams struct { diff --git a/lib/teleterm/daemon/daemon_test.go b/lib/teleterm/daemon/daemon_test.go index e99d2ccd740ab..d60b0dd5a3a72 100644 --- a/lib/teleterm/daemon/daemon_test.go +++ b/lib/teleterm/daemon/daemon_test.go @@ -62,7 +62,9 @@ func (m *mockGatewayCreator) CreateGateway(ctx context.Context, params clusters. return nil, trace.Wrap(err) } m.t.Cleanup(func() { - gateway.Close() + if err := gateway.Close(); err != nil { + m.t.Logf("Ignoring error from gateway.Close() during cleanup, it appears the gateway was already closed. The error was: %s", err) + } }) return gateway, nil diff --git a/lib/teleterm/gateway/config.go b/lib/teleterm/gateway/config.go index 2c103afa3a930..cf2e2375cc2e9 100644 --- a/lib/teleterm/gateway/config.go +++ b/lib/teleterm/gateway/config.go @@ -63,8 +63,18 @@ type Config struct { // TCPPortAllocator creates listeners on the given ports. This interface lets us avoid occupying // hardcoded ports in tests. TCPPortAllocator TCPPortAllocator + // OnNewConnection is a callback called when a new downstream connection is accepted by the + // gateway. The full gateway struct is not passed as an argument to the callback on purpose to + // avoid callsites mutating the gateway without acquiring a lock on daemon.Service.mu. + // + // Note that the callback blocks handling of the connection. + // + // OnNewConnection is copied between gateways when calling gateway.NewWithLocalPort. + OnNewConnection OnNewConnectionFunc } +type OnNewConnectionFunc func(gatewayURI uri.ResourceURI, targetURI string) + // CheckAndSetDefaults checks and sets the defaults func (c *Config) CheckAndSetDefaults() error { if c.URI.String() == "" { @@ -84,9 +94,11 @@ func (c *Config) CheckAndSetDefaults() error { } if c.Log == nil { - c.Log = logrus.WithField("gateway", c.URI.String()) + c.Log = logrus.NewEntry(logrus.StandardLogger()) } + c.Log = c.Log.WithField("resource", c.TargetURI).WithField("gateway", c.URI.String()) + if c.TargetName == "" { return trace.BadParameter("missing target name") } diff --git a/lib/teleterm/gateway/gateway.go b/lib/teleterm/gateway/gateway.go index 3f9840fc91a99..5ec5f67661685 100644 --- a/lib/teleterm/gateway/gateway.go +++ b/lib/teleterm/gateway/gateway.go @@ -80,7 +80,7 @@ func New(cfg Config) (*Gateway, error) { return nil, trace.Wrap(err) } - localProxy, err := alpn.NewLocalProxy(alpn.LocalProxyConfig{ + localProxyConfig := alpn.LocalProxyConfig{ InsecureSkipVerify: cfg.Insecure, RemoteProxyAddr: cfg.WebProxyAddr, Protocols: []alpncommon.Protocol{protocol}, @@ -88,7 +88,18 @@ func New(cfg Config) (*Gateway, error) { ParentContext: closeContext, SNI: address.Host(), Certs: []tls.Certificate{tlsCert}, - }) + } + + // TODO: Add tests for OnNewConnection. + if cfg.OnNewConnection != nil { + localProxyConfig.OnNewConnection = func(lp *alpn.LocalProxy, conn net.Conn) { + cfg.Log.Debug("New connection") + cfg.OnNewConnection(cfg.URI, cfg.TargetURI) + cfg.Log.Debug("OnNewConnection finished") + } + } + + localProxy, err := alpn.NewLocalProxy(localProxyConfig) if err != nil { return nil, trace.Wrap(err) } diff --git a/lib/teleterm/gateway/gateway_test.go b/lib/teleterm/gateway/gateway_test.go index b55b14cbc0e7e..9e1574f81f987 100644 --- a/lib/teleterm/gateway/gateway_test.go +++ b/lib/teleterm/gateway/gateway_test.go @@ -67,7 +67,11 @@ func TestGatewayStart(t *testing.T) { }, ) require.NoError(t, err) - t.Cleanup(func() { gateway.Close() }) + t.Cleanup(func() { + if err := gateway.Close(); err != nil { + t.Logf("Ignoring error from gateway.Close() during cleanup, it appears the gateway was already closed. The error was: %s", err) + } + }) gatewayAddress := net.JoinHostPort(gateway.LocalAddress(), gateway.LocalPort()) require.NotEmpty(t, gateway.LocalPort()) @@ -171,7 +175,9 @@ func serveGatewayAndBlockUntilItAcceptsConnections(t *testing.T, gateway *Gatewa serveErr <- err }() t.Cleanup(func() { - gateway.Close() + if err := gateway.Close(); err != nil { + t.Logf("Ignoring error from gateway.Close() during cleanup, it appears the gateway was already closed. The error was: %s", err) + } require.NoError(t, <-serveErr, "Gateway %s returned error from Serve()", gateway.URI()) }) diff --git a/tool/tsh/db.go b/tool/tsh/db.go index 060f917a772bc..fceb4b8536ea3 100644 --- a/tool/tsh/db.go +++ b/tool/tsh/db.go @@ -18,6 +18,7 @@ package main import ( "context" + "crypto/x509" "encoding/base64" "fmt" "io" @@ -35,6 +36,7 @@ import ( "github.com/gravitational/teleport/lib/client/db/dbcmd" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/srv/alpnproxy" "github.com/gravitational/teleport/lib/srv/alpnproxy/common" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" @@ -625,6 +627,12 @@ type localProxyConfig struct { // it's always true for Snowflake database. Value is copied here to not modify // cli arguments directly. localProxyTunnel bool + // onNewConnection is a callback triggered when the ALPN local proxy + // accepts a new connection. Note that this callback always provides the + // database certificate in addition to the parameters in the original + // alpnproxy.OnNewConnectionFunc, regardless of whether the database + // certificate is provided to the ALPN local proxy or not. + onNewConnection func(dbCert *x509.Certificate, lp *alpnproxy.LocalProxy, conn net.Conn) } // prepareLocalProxyOptions created localProxyOpts needed to create local proxy from localProxyConfig. @@ -647,6 +655,17 @@ func prepareLocalProxyOptions(arg *localProxyConfig) (localProxyOpts, error) { keyFile: keyFile, } + if arg.onNewConnection != nil { + dbCert, err := certFromPath(arg.profile.DatabaseCertPathForCluster(arg.cliConf.SiteName, arg.routeToDatabase.ServiceName)) + if err != nil { + return localProxyOpts{}, trace.Wrap(err) + } + + opts.onNewConnection = func(lp *alpnproxy.LocalProxy, conn net.Conn) { + arg.onNewConnection(dbCert, lp, conn) + } + } + // For SQL Server connections, local proxy must be configured with the // client certificate that will be used to route connections. if arg.routeToDatabase.Protocol == defaults.ProtocolSQLServer { @@ -845,11 +864,7 @@ func dbInfoHasChanged(cf *CLIConf, certPath string) (bool, error) { return false, nil } - buff, err := os.ReadFile(certPath) - if err != nil { - return false, trace.Wrap(err) - } - cert, err := tlsca.ParseCertificatePEM(buff) + cert, err := certFromPath(certPath) if err != nil { return false, trace.Wrap(err) } @@ -869,6 +884,20 @@ func dbInfoHasChanged(cf *CLIConf, certPath string) (bool, error) { return false, nil } +// certFromPath parses the PEM-encoded certificate from the provided path. Note +// that this function expects only one certificate in the file. +func certFromPath(path string) (*x509.Certificate, error) { + buff, err := os.ReadFile(path) + if err != nil { + return nil, trace.Wrap(err) + } + cert, err := tlsca.ParseCertificatePEM(buff) + if err != nil { + return nil, trace.Wrap(err) + } + return cert, nil +} + // isMFADatabaseAccessRequired calls the IsMFARequired endpoint in order to get from user roles if access to the database // requires MFA. func isMFADatabaseAccessRequired(cf *CLIConf, tc *client.TeleportClient, database *tlsca.RouteToDatabase) (bool, error) { diff --git a/tool/tsh/proxy.go b/tool/tsh/proxy.go index a1510f992b70d..2d04406eeca80 100644 --- a/tool/tsh/proxy.go +++ b/tool/tsh/proxy.go @@ -356,6 +356,15 @@ func onProxyCommandDB(cf *CLIConf) error { } }() + onNewConnection := func(dbCert *x509.Certificate, lp *alpnproxy.LocalProxy, conn net.Conn) { + if time.Now().After(dbCert.NotAfter) { + fmt.Fprintln(cf.Stdout()) + fmt.Fprintln(cf.Stdout(), "Your database session is expired. Please restart the local proxy.") + lp.Close() + return + } + } + proxyOpts, err := prepareLocalProxyOptions(&localProxyConfig{ cliConf: cf, teleportClient: client, @@ -363,6 +372,7 @@ func onProxyCommandDB(cf *CLIConf) error { routeToDatabase: routeToDatabase, listener: listener, localProxyTunnel: cf.LocalProxyTunnel, + onNewConnection: onNewConnection, }) if err != nil { return trace.Wrap(err) @@ -422,12 +432,13 @@ func onProxyCommandDB(cf *CLIConf) error { } type localProxyOpts struct { - proxyAddr string - listener net.Listener - protocols []alpncommon.Protocol - insecure bool - certFile string - keyFile string + proxyAddr string + listener net.Listener + protocols []alpncommon.Protocol + insecure bool + certFile string + keyFile string + onNewConnection alpnproxy.OnNewConnectionFunc } // protocol returns the first protocol or string if configuration doesn't contain any protocols. @@ -465,6 +476,7 @@ func mkLocalProxy(ctx context.Context, opts localProxyOpts) (*alpnproxy.LocalPro ParentContext: ctx, SNI: address.Host(), Certs: certs, + OnNewConnection: opts.onNewConnection, }) if err != nil { return nil, trace.Wrap(err)