diff --git a/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.go b/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.go index fdd32e99fb..66c9fc3320 100644 --- a/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.go +++ b/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.go @@ -2809,6 +2809,245 @@ func (x *CheckSqlQueryResponse) GetErorrMessage() string { return "" } +type CheckSSHConnectionRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The SSH tunnel configuration to use for the connection + Tunnel *SSHTunnel `protobuf:"bytes,1,opt,name=tunnel,proto3" json:"tunnel,omitempty"` +} + +func (x *CheckSSHConnectionRequest) Reset() { + *x = CheckSSHConnectionRequest{} + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[39] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckSSHConnectionRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckSSHConnectionRequest) ProtoMessage() {} + +func (x *CheckSSHConnectionRequest) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[39] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckSSHConnectionRequest.ProtoReflect.Descriptor instead. +func (*CheckSSHConnectionRequest) Descriptor() ([]byte, []int) { + return file_mgmt_v1alpha1_connection_proto_rawDescGZIP(), []int{39} +} + +func (x *CheckSSHConnectionRequest) GetTunnel() *SSHTunnel { + if x != nil { + return x.Tunnel + } + return nil +} + +type CheckSSHConnectionResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The result of the SSH connection check + Result *CheckSSHConnectionResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (x *CheckSSHConnectionResponse) Reset() { + *x = CheckSSHConnectionResponse{} + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckSSHConnectionResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckSSHConnectionResponse) ProtoMessage() {} + +func (x *CheckSSHConnectionResponse) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[40] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckSSHConnectionResponse.ProtoReflect.Descriptor instead. +func (*CheckSSHConnectionResponse) Descriptor() ([]byte, []int) { + return file_mgmt_v1alpha1_connection_proto_rawDescGZIP(), []int{40} +} + +func (x *CheckSSHConnectionResponse) GetResult() *CheckSSHConnectionResult { + if x != nil { + return x.Result + } + return nil +} + +type CheckSSHConnectionByIdRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The connection id that the SSH connection will be checked against + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *CheckSSHConnectionByIdRequest) Reset() { + *x = CheckSSHConnectionByIdRequest{} + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckSSHConnectionByIdRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckSSHConnectionByIdRequest) ProtoMessage() {} + +func (x *CheckSSHConnectionByIdRequest) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[41] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckSSHConnectionByIdRequest.ProtoReflect.Descriptor instead. +func (*CheckSSHConnectionByIdRequest) Descriptor() ([]byte, []int) { + return file_mgmt_v1alpha1_connection_proto_rawDescGZIP(), []int{41} +} + +func (x *CheckSSHConnectionByIdRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type CheckSSHConnectionByIdResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The result of the SSH connection check + Result *CheckSSHConnectionResult `protobuf:"bytes,1,opt,name=result,proto3" json:"result,omitempty"` +} + +func (x *CheckSSHConnectionByIdResponse) Reset() { + *x = CheckSSHConnectionByIdResponse{} + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckSSHConnectionByIdResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckSSHConnectionByIdResponse) ProtoMessage() {} + +func (x *CheckSSHConnectionByIdResponse) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[42] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckSSHConnectionByIdResponse.ProtoReflect.Descriptor instead. +func (*CheckSSHConnectionByIdResponse) Descriptor() ([]byte, []int) { + return file_mgmt_v1alpha1_connection_proto_rawDescGZIP(), []int{42} +} + +func (x *CheckSSHConnectionByIdResponse) GetResult() *CheckSSHConnectionResult { + if x != nil { + return x.Result + } + return nil +} + +type CheckSSHConnectionResult struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Whether or not the SSH connection is successful + IsSuccessful bool `protobuf:"varint,1,opt,name=is_successful,json=isSuccessful,proto3" json:"is_successful,omitempty"` + // The error message returned by the SSH client if the connection is not successful + ErrorMessage *string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3,oneof" json:"error_message,omitempty"` +} + +func (x *CheckSSHConnectionResult) Reset() { + *x = CheckSSHConnectionResult{} + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CheckSSHConnectionResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CheckSSHConnectionResult) ProtoMessage() {} + +func (x *CheckSSHConnectionResult) ProtoReflect() protoreflect.Message { + mi := &file_mgmt_v1alpha1_connection_proto_msgTypes[43] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CheckSSHConnectionResult.ProtoReflect.Descriptor instead. +func (*CheckSSHConnectionResult) Descriptor() ([]byte, []int) { + return file_mgmt_v1alpha1_connection_proto_rawDescGZIP(), []int{43} +} + +func (x *CheckSSHConnectionResult) GetIsSuccessful() bool { + if x != nil { + return x.IsSuccessful + } + return false +} + +func (x *CheckSSHConnectionResult) GetErrorMessage() string { + if x != nil && x.ErrorMessage != nil { + return *x.ErrorMessage + } + return "" +} + var File_mgmt_v1alpha1_connection_proto protoreflect.FileDescriptor var file_mgmt_v1alpha1_connection_proto_rawDesc = []byte{ @@ -3273,83 +3512,126 @@ var file_mgmt_v1alpha1_connection_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x65, 0x72, 0x6f, 0x72, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0c, 0x65, 0x72, 0x6f, 0x72, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x6f, - 0x72, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xe7, 0x07, 0x0a, 0x11, 0x43, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x12, 0x62, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x24, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x03, 0x90, 0x02, 0x01, 0x12, 0x5f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x65, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, + 0x72, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x19, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x74, 0x75, 0x6e, 0x6e, 0x65, + 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x53, 0x53, 0x48, 0x54, 0x75, 0x6e, 0x6e, 0x65, + 0x6c, 0x52, 0x06, 0x74, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x22, 0x5d, 0x0a, 0x1a, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x52, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x39, 0x0a, 0x1d, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, + 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x61, 0x0a, 0x1e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x06, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, + 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x06, + 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x22, 0x7b, 0x0a, 0x18, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, + 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, + 0x6c, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x69, 0x73, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x66, 0x75, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x73, 0x53, 0x75, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x66, 0x75, 0x6c, 0x12, 0x28, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, + 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, + 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x88, 0x01, + 0x01, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x32, 0xcd, 0x09, 0x0a, 0x11, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x0e, 0x47, 0x65, 0x74, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x24, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x25, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x5f, 0x0a, + 0x0d, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x23, + 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x90, 0x02, 0x01, 0x12, 0x65, + 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x67, 0x6d, 0x74, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x10, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x65, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, - 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x27, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x19, 0x49, - 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x41, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x2f, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6d, 0x67, 0x6d, 0x74, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, - 0x15, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x19, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x49, - 0x64, 0x12, 0x2f, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, 0x19, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x2f, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x2e, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, - 0x71, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x23, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x71, 0x6c, - 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, + 0x61, 0x31, 0x2e, 0x49, 0x73, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, + 0x61, 0x6d, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x74, 0x0a, 0x15, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x2b, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x53, 0x71, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x42, 0xcb, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x67, 0x6d, - 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, 0x75, 0x63, 0x6c, 0x65, 0x75, - 0x73, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6e, 0x65, 0x6f, 0x73, 0x79, 0x6e, 0x63, 0x2f, 0x62, - 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x73, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x3b, 0x6d, 0x67, 0x6d, 0x74, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, - 0x02, 0x03, 0x4d, 0x58, 0x58, 0xaa, 0x02, 0x0d, 0x4d, 0x67, 0x6d, 0x74, 0x2e, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x0d, 0x4d, 0x67, 0x6d, 0x74, 0x5c, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x19, 0x4d, 0x67, 0x6d, 0x74, 0x5c, 0x56, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x0e, 0x4d, 0x67, 0x6d, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x80, 0x01, 0x0a, + 0x19, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x79, 0x49, 0x64, 0x12, 0x2f, 0x2e, 0x6d, 0x67, 0x6d, + 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, + 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6d, 0x67, + 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x5c, 0x0a, 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x71, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x12, 0x23, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x71, 0x6c, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x71, 0x6c, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6b, 0x0a, + 0x12, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x28, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, + 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x77, 0x0a, 0x16, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x42, 0x79, 0x49, 0x64, 0x12, 0x2c, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x53, 0x53, 0x48, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x79, 0x49, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x42, 0xcb, 0x01, 0x0a, 0x11, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x67, 0x6d, 0x74, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x42, 0x0f, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x50, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6e, 0x75, 0x63, 0x6c, 0x65, 0x75, 0x73, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6e, 0x65, 0x6f, 0x73, 0x79, 0x6e, 0x63, 0x2f, 0x62, 0x61, + 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x2f, 0x6d, 0x67, 0x6d, 0x74, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x3b, 0x6d, 0x67, 0x6d, 0x74, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0xa2, 0x02, + 0x03, 0x4d, 0x58, 0x58, 0xaa, 0x02, 0x0d, 0x4d, 0x67, 0x6d, 0x74, 0x2e, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xca, 0x02, 0x0d, 0x4d, 0x67, 0x6d, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0xe2, 0x02, 0x19, 0x4d, 0x67, 0x6d, 0x74, 0x5c, 0x56, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0xea, 0x02, 0x0e, 0x4d, 0x67, 0x6d, 0x74, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3364,7 +3646,7 @@ func file_mgmt_v1alpha1_connection_proto_rawDescGZIP() []byte { return file_mgmt_v1alpha1_connection_proto_rawDescData } -var file_mgmt_v1alpha1_connection_proto_msgTypes = make([]protoimpl.MessageInfo, 39) +var file_mgmt_v1alpha1_connection_proto_msgTypes = make([]protoimpl.MessageInfo, 44) var file_mgmt_v1alpha1_connection_proto_goTypes = []any{ (*GetConnectionsRequest)(nil), // 0: mgmt.v1alpha1.GetConnectionsRequest (*GetConnectionsResponse)(nil), // 1: mgmt.v1alpha1.GetConnectionsResponse @@ -3405,7 +3687,12 @@ var file_mgmt_v1alpha1_connection_proto_goTypes = []any{ (*IsConnectionNameAvailableResponse)(nil), // 36: mgmt.v1alpha1.IsConnectionNameAvailableResponse (*CheckSqlQueryRequest)(nil), // 37: mgmt.v1alpha1.CheckSqlQueryRequest (*CheckSqlQueryResponse)(nil), // 38: mgmt.v1alpha1.CheckSqlQueryResponse - (*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp + (*CheckSSHConnectionRequest)(nil), // 39: mgmt.v1alpha1.CheckSSHConnectionRequest + (*CheckSSHConnectionResponse)(nil), // 40: mgmt.v1alpha1.CheckSSHConnectionResponse + (*CheckSSHConnectionByIdRequest)(nil), // 41: mgmt.v1alpha1.CheckSSHConnectionByIdRequest + (*CheckSSHConnectionByIdResponse)(nil), // 42: mgmt.v1alpha1.CheckSSHConnectionByIdResponse + (*CheckSSHConnectionResult)(nil), // 43: mgmt.v1alpha1.CheckSSHConnectionResult + (*timestamppb.Timestamp)(nil), // 44: google.protobuf.Timestamp } var file_mgmt_v1alpha1_connection_proto_depIdxs = []int32{ 15, // 0: mgmt.v1alpha1.GetConnectionsResponse.connections:type_name -> mgmt.v1alpha1.Connection @@ -3418,8 +3705,8 @@ var file_mgmt_v1alpha1_connection_proto_depIdxs = []int32{ 14, // 7: mgmt.v1alpha1.CheckConnectionConfigByIdResponse.privileges:type_name -> mgmt.v1alpha1.ConnectionRolePrivilege 14, // 8: mgmt.v1alpha1.CheckConnectionConfigResponse.privileges:type_name -> mgmt.v1alpha1.ConnectionRolePrivilege 16, // 9: mgmt.v1alpha1.Connection.connection_config:type_name -> mgmt.v1alpha1.ConnectionConfig - 39, // 10: mgmt.v1alpha1.Connection.created_at:type_name -> google.protobuf.Timestamp - 39, // 11: mgmt.v1alpha1.Connection.updated_at:type_name -> google.protobuf.Timestamp + 44, // 10: mgmt.v1alpha1.Connection.created_at:type_name -> google.protobuf.Timestamp + 44, // 11: mgmt.v1alpha1.Connection.updated_at:type_name -> google.protobuf.Timestamp 22, // 12: mgmt.v1alpha1.ConnectionConfig.pg_config:type_name -> mgmt.v1alpha1.PostgresConnectionConfig 32, // 13: mgmt.v1alpha1.ConnectionConfig.aws_s3_config:type_name -> mgmt.v1alpha1.AwsS3ConnectionConfig 31, // 14: mgmt.v1alpha1.ConnectionConfig.mysql_config:type_name -> mgmt.v1alpha1.MysqlConnectionConfig @@ -3447,29 +3734,36 @@ var file_mgmt_v1alpha1_connection_proto_depIdxs = []int32{ 24, // 36: mgmt.v1alpha1.MysqlConnectionConfig.connection_options:type_name -> mgmt.v1alpha1.SqlConnectionOptions 23, // 37: mgmt.v1alpha1.MysqlConnectionConfig.client_tls:type_name -> mgmt.v1alpha1.ClientTlsConfig 33, // 38: mgmt.v1alpha1.AwsS3ConnectionConfig.credentials:type_name -> mgmt.v1alpha1.AwsS3Credentials - 0, // 39: mgmt.v1alpha1.ConnectionService.GetConnections:input_type -> mgmt.v1alpha1.GetConnectionsRequest - 2, // 40: mgmt.v1alpha1.ConnectionService.GetConnection:input_type -> mgmt.v1alpha1.GetConnectionRequest - 4, // 41: mgmt.v1alpha1.ConnectionService.CreateConnection:input_type -> mgmt.v1alpha1.CreateConnectionRequest - 6, // 42: mgmt.v1alpha1.ConnectionService.UpdateConnection:input_type -> mgmt.v1alpha1.UpdateConnectionRequest - 8, // 43: mgmt.v1alpha1.ConnectionService.DeleteConnection:input_type -> mgmt.v1alpha1.DeleteConnectionRequest - 35, // 44: mgmt.v1alpha1.ConnectionService.IsConnectionNameAvailable:input_type -> mgmt.v1alpha1.IsConnectionNameAvailableRequest - 10, // 45: mgmt.v1alpha1.ConnectionService.CheckConnectionConfig:input_type -> mgmt.v1alpha1.CheckConnectionConfigRequest - 11, // 46: mgmt.v1alpha1.ConnectionService.CheckConnectionConfigById:input_type -> mgmt.v1alpha1.CheckConnectionConfigByIdRequest - 37, // 47: mgmt.v1alpha1.ConnectionService.CheckSqlQuery:input_type -> mgmt.v1alpha1.CheckSqlQueryRequest - 1, // 48: mgmt.v1alpha1.ConnectionService.GetConnections:output_type -> mgmt.v1alpha1.GetConnectionsResponse - 3, // 49: mgmt.v1alpha1.ConnectionService.GetConnection:output_type -> mgmt.v1alpha1.GetConnectionResponse - 5, // 50: mgmt.v1alpha1.ConnectionService.CreateConnection:output_type -> mgmt.v1alpha1.CreateConnectionResponse - 7, // 51: mgmt.v1alpha1.ConnectionService.UpdateConnection:output_type -> mgmt.v1alpha1.UpdateConnectionResponse - 9, // 52: mgmt.v1alpha1.ConnectionService.DeleteConnection:output_type -> mgmt.v1alpha1.DeleteConnectionResponse - 36, // 53: mgmt.v1alpha1.ConnectionService.IsConnectionNameAvailable:output_type -> mgmt.v1alpha1.IsConnectionNameAvailableResponse - 13, // 54: mgmt.v1alpha1.ConnectionService.CheckConnectionConfig:output_type -> mgmt.v1alpha1.CheckConnectionConfigResponse - 12, // 55: mgmt.v1alpha1.ConnectionService.CheckConnectionConfigById:output_type -> mgmt.v1alpha1.CheckConnectionConfigByIdResponse - 38, // 56: mgmt.v1alpha1.ConnectionService.CheckSqlQuery:output_type -> mgmt.v1alpha1.CheckSqlQueryResponse - 48, // [48:57] is the sub-list for method output_type - 39, // [39:48] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 25, // 39: mgmt.v1alpha1.CheckSSHConnectionRequest.tunnel:type_name -> mgmt.v1alpha1.SSHTunnel + 43, // 40: mgmt.v1alpha1.CheckSSHConnectionResponse.result:type_name -> mgmt.v1alpha1.CheckSSHConnectionResult + 43, // 41: mgmt.v1alpha1.CheckSSHConnectionByIdResponse.result:type_name -> mgmt.v1alpha1.CheckSSHConnectionResult + 0, // 42: mgmt.v1alpha1.ConnectionService.GetConnections:input_type -> mgmt.v1alpha1.GetConnectionsRequest + 2, // 43: mgmt.v1alpha1.ConnectionService.GetConnection:input_type -> mgmt.v1alpha1.GetConnectionRequest + 4, // 44: mgmt.v1alpha1.ConnectionService.CreateConnection:input_type -> mgmt.v1alpha1.CreateConnectionRequest + 6, // 45: mgmt.v1alpha1.ConnectionService.UpdateConnection:input_type -> mgmt.v1alpha1.UpdateConnectionRequest + 8, // 46: mgmt.v1alpha1.ConnectionService.DeleteConnection:input_type -> mgmt.v1alpha1.DeleteConnectionRequest + 35, // 47: mgmt.v1alpha1.ConnectionService.IsConnectionNameAvailable:input_type -> mgmt.v1alpha1.IsConnectionNameAvailableRequest + 10, // 48: mgmt.v1alpha1.ConnectionService.CheckConnectionConfig:input_type -> mgmt.v1alpha1.CheckConnectionConfigRequest + 11, // 49: mgmt.v1alpha1.ConnectionService.CheckConnectionConfigById:input_type -> mgmt.v1alpha1.CheckConnectionConfigByIdRequest + 37, // 50: mgmt.v1alpha1.ConnectionService.CheckSqlQuery:input_type -> mgmt.v1alpha1.CheckSqlQueryRequest + 39, // 51: mgmt.v1alpha1.ConnectionService.CheckSSHConnection:input_type -> mgmt.v1alpha1.CheckSSHConnectionRequest + 41, // 52: mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById:input_type -> mgmt.v1alpha1.CheckSSHConnectionByIdRequest + 1, // 53: mgmt.v1alpha1.ConnectionService.GetConnections:output_type -> mgmt.v1alpha1.GetConnectionsResponse + 3, // 54: mgmt.v1alpha1.ConnectionService.GetConnection:output_type -> mgmt.v1alpha1.GetConnectionResponse + 5, // 55: mgmt.v1alpha1.ConnectionService.CreateConnection:output_type -> mgmt.v1alpha1.CreateConnectionResponse + 7, // 56: mgmt.v1alpha1.ConnectionService.UpdateConnection:output_type -> mgmt.v1alpha1.UpdateConnectionResponse + 9, // 57: mgmt.v1alpha1.ConnectionService.DeleteConnection:output_type -> mgmt.v1alpha1.DeleteConnectionResponse + 36, // 58: mgmt.v1alpha1.ConnectionService.IsConnectionNameAvailable:output_type -> mgmt.v1alpha1.IsConnectionNameAvailableResponse + 13, // 59: mgmt.v1alpha1.ConnectionService.CheckConnectionConfig:output_type -> mgmt.v1alpha1.CheckConnectionConfigResponse + 12, // 60: mgmt.v1alpha1.ConnectionService.CheckConnectionConfigById:output_type -> mgmt.v1alpha1.CheckConnectionConfigByIdResponse + 38, // 61: mgmt.v1alpha1.ConnectionService.CheckSqlQuery:output_type -> mgmt.v1alpha1.CheckSqlQueryResponse + 40, // 62: mgmt.v1alpha1.ConnectionService.CheckSSHConnection:output_type -> mgmt.v1alpha1.CheckSSHConnectionResponse + 42, // 63: mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById:output_type -> mgmt.v1alpha1.CheckSSHConnectionByIdResponse + 53, // [53:64] is the sub-list for method output_type + 42, // [42:53] is the sub-list for method input_type + 42, // [42:42] is the sub-list for extension type_name + 42, // [42:42] is the sub-list for extension extendee + 0, // [0:42] is the sub-list for field type_name } func init() { file_mgmt_v1alpha1_connection_proto_init() } @@ -3521,13 +3815,14 @@ func file_mgmt_v1alpha1_connection_proto_init() { file_mgmt_v1alpha1_connection_proto_msgTypes[33].OneofWrappers = []any{} file_mgmt_v1alpha1_connection_proto_msgTypes[34].OneofWrappers = []any{} file_mgmt_v1alpha1_connection_proto_msgTypes[38].OneofWrappers = []any{} + file_mgmt_v1alpha1_connection_proto_msgTypes[43].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_mgmt_v1alpha1_connection_proto_rawDesc, NumEnums: 0, - NumMessages: 39, + NumMessages: 44, NumExtensions: 0, NumServices: 1, }, diff --git a/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.json.go b/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.json.go index d4628dfeb3..f3781aa508 100644 --- a/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.json.go +++ b/backend/gen/go/protos/mgmt/v1alpha1/connection.pb.json.go @@ -396,3 +396,53 @@ func (msg *CheckSqlQueryResponse) MarshalJSON() ([]byte, error) { func (msg *CheckSqlQueryResponse) UnmarshalJSON(b []byte) error { return protojson.UnmarshalOptions{}.Unmarshal(b, msg) } + +// MarshalJSON implements json.Marshaler +func (msg *CheckSSHConnectionRequest) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{}.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *CheckSSHConnectionRequest) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{}.Unmarshal(b, msg) +} + +// MarshalJSON implements json.Marshaler +func (msg *CheckSSHConnectionResponse) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{}.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *CheckSSHConnectionResponse) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{}.Unmarshal(b, msg) +} + +// MarshalJSON implements json.Marshaler +func (msg *CheckSSHConnectionByIdRequest) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{}.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *CheckSSHConnectionByIdRequest) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{}.Unmarshal(b, msg) +} + +// MarshalJSON implements json.Marshaler +func (msg *CheckSSHConnectionByIdResponse) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{}.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *CheckSSHConnectionByIdResponse) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{}.Unmarshal(b, msg) +} + +// MarshalJSON implements json.Marshaler +func (msg *CheckSSHConnectionResult) MarshalJSON() ([]byte, error) { + return protojson.MarshalOptions{}.Marshal(msg) +} + +// UnmarshalJSON implements json.Unmarshaler +func (msg *CheckSSHConnectionResult) UnmarshalJSON(b []byte) error { + return protojson.UnmarshalOptions{}.Unmarshal(b, msg) +} diff --git a/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/connection.connect.go b/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/connection.connect.go index 702ed96557..ff4ca872f1 100644 --- a/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/connection.connect.go +++ b/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/connection.connect.go @@ -60,6 +60,12 @@ const ( // ConnectionServiceCheckSqlQueryProcedure is the fully-qualified name of the ConnectionService's // CheckSqlQuery RPC. ConnectionServiceCheckSqlQueryProcedure = "/mgmt.v1alpha1.ConnectionService/CheckSqlQuery" + // ConnectionServiceCheckSSHConnectionProcedure is the fully-qualified name of the + // ConnectionService's CheckSSHConnection RPC. + ConnectionServiceCheckSSHConnectionProcedure = "/mgmt.v1alpha1.ConnectionService/CheckSSHConnection" + // ConnectionServiceCheckSSHConnectionByIdProcedure is the fully-qualified name of the + // ConnectionService's CheckSSHConnectionById RPC. + ConnectionServiceCheckSSHConnectionByIdProcedure = "/mgmt.v1alpha1.ConnectionService/CheckSSHConnectionById" ) // These variables are the protoreflect.Descriptor objects for the RPCs defined in this package. @@ -74,6 +80,8 @@ var ( connectionServiceCheckConnectionConfigMethodDescriptor = connectionServiceServiceDescriptor.Methods().ByName("CheckConnectionConfig") connectionServiceCheckConnectionConfigByIdMethodDescriptor = connectionServiceServiceDescriptor.Methods().ByName("CheckConnectionConfigById") connectionServiceCheckSqlQueryMethodDescriptor = connectionServiceServiceDescriptor.Methods().ByName("CheckSqlQuery") + connectionServiceCheckSSHConnectionMethodDescriptor = connectionServiceServiceDescriptor.Methods().ByName("CheckSSHConnection") + connectionServiceCheckSSHConnectionByIdMethodDescriptor = connectionServiceServiceDescriptor.Methods().ByName("CheckSSHConnectionById") ) // ConnectionServiceClient is a client for the mgmt.v1alpha1.ConnectionService service. @@ -99,6 +107,10 @@ type ConnectionServiceClient interface { // Checks a constructed SQL query against a sql-based connection to see if it's valid based on that connection's data schema // This is useful when constructing subsets to see if the WHERE clause is correct CheckSqlQuery(context.Context, *connect.Request[v1alpha1.CheckSqlQueryRequest]) (*connect.Response[v1alpha1.CheckSqlQueryResponse], error) + // Checks if the SSH server is reachable and accessible with the given credentials + CheckSSHConnection(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionResponse], error) + // Checks if the SSH server is reachable and accessible with the given credentials + CheckSSHConnectionById(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionByIdResponse], error) } // NewConnectionServiceClient constructs a client for the mgmt.v1alpha1.ConnectionService service. @@ -167,6 +179,18 @@ func NewConnectionServiceClient(httpClient connect.HTTPClient, baseURL string, o connect.WithSchema(connectionServiceCheckSqlQueryMethodDescriptor), connect.WithClientOptions(opts...), ), + checkSSHConnection: connect.NewClient[v1alpha1.CheckSSHConnectionRequest, v1alpha1.CheckSSHConnectionResponse]( + httpClient, + baseURL+ConnectionServiceCheckSSHConnectionProcedure, + connect.WithSchema(connectionServiceCheckSSHConnectionMethodDescriptor), + connect.WithClientOptions(opts...), + ), + checkSSHConnectionById: connect.NewClient[v1alpha1.CheckSSHConnectionByIdRequest, v1alpha1.CheckSSHConnectionByIdResponse]( + httpClient, + baseURL+ConnectionServiceCheckSSHConnectionByIdProcedure, + connect.WithSchema(connectionServiceCheckSSHConnectionByIdMethodDescriptor), + connect.WithClientOptions(opts...), + ), } } @@ -181,6 +205,8 @@ type connectionServiceClient struct { checkConnectionConfig *connect.Client[v1alpha1.CheckConnectionConfigRequest, v1alpha1.CheckConnectionConfigResponse] checkConnectionConfigById *connect.Client[v1alpha1.CheckConnectionConfigByIdRequest, v1alpha1.CheckConnectionConfigByIdResponse] checkSqlQuery *connect.Client[v1alpha1.CheckSqlQueryRequest, v1alpha1.CheckSqlQueryResponse] + checkSSHConnection *connect.Client[v1alpha1.CheckSSHConnectionRequest, v1alpha1.CheckSSHConnectionResponse] + checkSSHConnectionById *connect.Client[v1alpha1.CheckSSHConnectionByIdRequest, v1alpha1.CheckSSHConnectionByIdResponse] } // GetConnections calls mgmt.v1alpha1.ConnectionService.GetConnections. @@ -228,6 +254,16 @@ func (c *connectionServiceClient) CheckSqlQuery(ctx context.Context, req *connec return c.checkSqlQuery.CallUnary(ctx, req) } +// CheckSSHConnection calls mgmt.v1alpha1.ConnectionService.CheckSSHConnection. +func (c *connectionServiceClient) CheckSSHConnection(ctx context.Context, req *connect.Request[v1alpha1.CheckSSHConnectionRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionResponse], error) { + return c.checkSSHConnection.CallUnary(ctx, req) +} + +// CheckSSHConnectionById calls mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById. +func (c *connectionServiceClient) CheckSSHConnectionById(ctx context.Context, req *connect.Request[v1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionByIdResponse], error) { + return c.checkSSHConnectionById.CallUnary(ctx, req) +} + // ConnectionServiceHandler is an implementation of the mgmt.v1alpha1.ConnectionService service. type ConnectionServiceHandler interface { // Returns a list of connections associated with the account @@ -251,6 +287,10 @@ type ConnectionServiceHandler interface { // Checks a constructed SQL query against a sql-based connection to see if it's valid based on that connection's data schema // This is useful when constructing subsets to see if the WHERE clause is correct CheckSqlQuery(context.Context, *connect.Request[v1alpha1.CheckSqlQueryRequest]) (*connect.Response[v1alpha1.CheckSqlQueryResponse], error) + // Checks if the SSH server is reachable and accessible with the given credentials + CheckSSHConnection(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionResponse], error) + // Checks if the SSH server is reachable and accessible with the given credentials + CheckSSHConnectionById(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionByIdResponse], error) } // NewConnectionServiceHandler builds an HTTP handler from the service implementation. It returns @@ -315,6 +355,18 @@ func NewConnectionServiceHandler(svc ConnectionServiceHandler, opts ...connect.H connect.WithSchema(connectionServiceCheckSqlQueryMethodDescriptor), connect.WithHandlerOptions(opts...), ) + connectionServiceCheckSSHConnectionHandler := connect.NewUnaryHandler( + ConnectionServiceCheckSSHConnectionProcedure, + svc.CheckSSHConnection, + connect.WithSchema(connectionServiceCheckSSHConnectionMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) + connectionServiceCheckSSHConnectionByIdHandler := connect.NewUnaryHandler( + ConnectionServiceCheckSSHConnectionByIdProcedure, + svc.CheckSSHConnectionById, + connect.WithSchema(connectionServiceCheckSSHConnectionByIdMethodDescriptor), + connect.WithHandlerOptions(opts...), + ) return "/mgmt.v1alpha1.ConnectionService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case ConnectionServiceGetConnectionsProcedure: @@ -335,6 +387,10 @@ func NewConnectionServiceHandler(svc ConnectionServiceHandler, opts ...connect.H connectionServiceCheckConnectionConfigByIdHandler.ServeHTTP(w, r) case ConnectionServiceCheckSqlQueryProcedure: connectionServiceCheckSqlQueryHandler.ServeHTTP(w, r) + case ConnectionServiceCheckSSHConnectionProcedure: + connectionServiceCheckSSHConnectionHandler.ServeHTTP(w, r) + case ConnectionServiceCheckSSHConnectionByIdProcedure: + connectionServiceCheckSSHConnectionByIdHandler.ServeHTTP(w, r) default: http.NotFound(w, r) } @@ -379,3 +435,11 @@ func (UnimplementedConnectionServiceHandler) CheckConnectionConfigById(context.C func (UnimplementedConnectionServiceHandler) CheckSqlQuery(context.Context, *connect.Request[v1alpha1.CheckSqlQueryRequest]) (*connect.Response[v1alpha1.CheckSqlQueryResponse], error) { return nil, connect.NewError(connect.CodeUnimplemented, errors.New("mgmt.v1alpha1.ConnectionService.CheckSqlQuery is not implemented")) } + +func (UnimplementedConnectionServiceHandler) CheckSSHConnection(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("mgmt.v1alpha1.ConnectionService.CheckSSHConnection is not implemented")) +} + +func (UnimplementedConnectionServiceHandler) CheckSSHConnectionById(context.Context, *connect.Request[v1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[v1alpha1.CheckSSHConnectionByIdResponse], error) { + return nil, connect.NewError(connect.CodeUnimplemented, errors.New("mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById is not implemented")) +} diff --git a/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/mock_ConnectionServiceClient.go b/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/mock_ConnectionServiceClient.go index a5fc440cd9..d73319b976 100644 --- a/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/mock_ConnectionServiceClient.go +++ b/backend/gen/go/protos/mgmt/v1alpha1/mgmtv1alpha1connect/mock_ConnectionServiceClient.go @@ -142,6 +142,124 @@ func (_c *MockConnectionServiceClient_CheckConnectionConfigById_Call) RunAndRetu return _c } +// CheckSSHConnection provides a mock function with given fields: _a0, _a1 +func (_m *MockConnectionServiceClient) CheckSSHConnection(_a0 context.Context, _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse], error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for CheckSSHConnection") + } + + var r0 *connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse] + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse], error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest]) *connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse]); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse]) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest]) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockConnectionServiceClient_CheckSSHConnection_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckSSHConnection' +type MockConnectionServiceClient_CheckSSHConnection_Call struct { + *mock.Call +} + +// CheckSSHConnection is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest] +func (_e *MockConnectionServiceClient_Expecter) CheckSSHConnection(_a0 interface{}, _a1 interface{}) *MockConnectionServiceClient_CheckSSHConnection_Call { + return &MockConnectionServiceClient_CheckSSHConnection_Call{Call: _e.mock.On("CheckSSHConnection", _a0, _a1)} +} + +func (_c *MockConnectionServiceClient_CheckSSHConnection_Call) Run(run func(_a0 context.Context, _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest])) *MockConnectionServiceClient_CheckSSHConnection_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest])) + }) + return _c +} + +func (_c *MockConnectionServiceClient_CheckSSHConnection_Call) Return(_a0 *connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse], _a1 error) *MockConnectionServiceClient_CheckSSHConnection_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockConnectionServiceClient_CheckSSHConnection_Call) RunAndReturn(run func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse], error)) *MockConnectionServiceClient_CheckSSHConnection_Call { + _c.Call.Return(run) + return _c +} + +// CheckSSHConnectionById provides a mock function with given fields: _a0, _a1 +func (_m *MockConnectionServiceClient) CheckSSHConnectionById(_a0 context.Context, _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse], error) { + ret := _m.Called(_a0, _a1) + + if len(ret) == 0 { + panic("no return value specified for CheckSSHConnectionById") + } + + var r0 *connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse] + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse], error)); ok { + return rf(_a0, _a1) + } + if rf, ok := ret.Get(0).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest]) *connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse]); ok { + r0 = rf(_a0, _a1) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse]) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest]) error); ok { + r1 = rf(_a0, _a1) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockConnectionServiceClient_CheckSSHConnectionById_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CheckSSHConnectionById' +type MockConnectionServiceClient_CheckSSHConnectionById_Call struct { + *mock.Call +} + +// CheckSSHConnectionById is a helper method to define mock.On call +// - _a0 context.Context +// - _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest] +func (_e *MockConnectionServiceClient_Expecter) CheckSSHConnectionById(_a0 interface{}, _a1 interface{}) *MockConnectionServiceClient_CheckSSHConnectionById_Call { + return &MockConnectionServiceClient_CheckSSHConnectionById_Call{Call: _e.mock.On("CheckSSHConnectionById", _a0, _a1)} +} + +func (_c *MockConnectionServiceClient_CheckSSHConnectionById_Call) Run(run func(_a0 context.Context, _a1 *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest])) *MockConnectionServiceClient_CheckSSHConnectionById_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(*connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest])) + }) + return _c +} + +func (_c *MockConnectionServiceClient_CheckSSHConnectionById_Call) Return(_a0 *connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse], _a1 error) *MockConnectionServiceClient_CheckSSHConnectionById_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockConnectionServiceClient_CheckSSHConnectionById_Call) RunAndReturn(run func(context.Context, *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest]) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse], error)) *MockConnectionServiceClient_CheckSSHConnectionById_Call { + _c.Call.Return(run) + return _c +} + // CheckSqlQuery provides a mock function with given fields: _a0, _a1 func (_m *MockConnectionServiceClient) CheckSqlQuery(_a0 context.Context, _a1 *connect.Request[mgmtv1alpha1.CheckSqlQueryRequest]) (*connect.Response[mgmtv1alpha1.CheckSqlQueryResponse], error) { ret := _m.Called(_a0, _a1) diff --git a/backend/pkg/sqlconnect/sql-connector.go b/backend/pkg/sqlconnect/sql-connector.go index 8b0c152933..3a76e4d1f5 100644 --- a/backend/pkg/sqlconnect/sql-connector.go +++ b/backend/pkg/sqlconnect/sql-connector.go @@ -8,8 +8,6 @@ import ( "errors" "fmt" "log/slog" - "net" - "strconv" "sync" "time" @@ -21,7 +19,6 @@ import ( "github.com/nucleuscloud/neosync/internal/sshtunnel/connectors/mssqltunconnector" "github.com/nucleuscloud/neosync/internal/sshtunnel/connectors/mysqltunconnector" "github.com/nucleuscloud/neosync/internal/sshtunnel/connectors/postgrestunconnector" - "golang.org/x/crypto/ssh" ) // interface used by SqlConnector to abstract away the opening and closing of a sqldb that includes tunnelingff @@ -134,7 +131,7 @@ func getPgConnectorFn(dsn string, config *mgmtv1alpha1.PostgresConnectionConfig, connectorOpts = append(connectorOpts, postgrestunconnector.WithTLSConfig(tlsConfig)) } if config.GetTunnel() != nil { - cfg, err := getTunnelConfig(config.GetTunnel()) + cfg, err := tun.GetTunnelConfigFromSSHDto(config.GetTunnel()) if err != nil { return nil, nil, fmt.Errorf("unable to construct postgres client tunnel config: %w", err) } @@ -179,7 +176,7 @@ func getMysqlConnectorFn(dsn string, config *mgmtv1alpha1.MysqlConnectionConfig, connectorOpts = append(connectorOpts, mysqltunconnector.WithTLSConfig(tlsConfig)) } if config.GetTunnel() != nil { - cfg, err := getTunnelConfig(config.GetTunnel()) + cfg, err := tun.GetTunnelConfigFromSSHDto(config.GetTunnel()) if err != nil { return nil, nil, fmt.Errorf("unable to construct mysql client tunnel config: %w", err) } @@ -224,7 +221,7 @@ func getMssqlConnectorFn(dsn string, config *mgmtv1alpha1.MssqlConnectionConfig, connectorOpts = append(connectorOpts, mssqltunconnector.WithTLSConfig(tlsConfig)) } if config.GetTunnel() != nil { - cfg, err := getTunnelConfig(config.GetTunnel()) + cfg, err := tun.GetTunnelConfigFromSSHDto(config.GetTunnel()) if err != nil { return nil, nil, fmt.Errorf("unable to construct mssql tunnel config: %w", err) } @@ -304,52 +301,6 @@ func convertInt32PtrToIntPtr(input *int32) *int { return &value } -type tunnelConfig struct { - Addr string - ClientConfig *ssh.ClientConfig -} - -func getTunnelConfig(tunnel *mgmtv1alpha1.SSHTunnel) (*tunnelConfig, error) { - var hostcallback ssh.HostKeyCallback - if tunnel.GetKnownHostPublicKey() != "" { - publickey, err := tun.ParseSshKey(tunnel.GetKnownHostPublicKey()) - if err != nil { - return nil, fmt.Errorf("unable to parse ssh known host public key: %w", err) - } - hostcallback = ssh.FixedHostKey(publickey) - } else { - hostcallback = ssh.InsecureIgnoreHostKey() //nolint:gosec // the user has chosen to not provide a known host public key - } - authmethod, err := tun.GetTunnelAuthMethodFromSshConfig(tunnel.GetAuthentication()) - if err != nil { - return nil, fmt.Errorf("unable to parse ssh auth method: %w", err) - } - - authmethods := []ssh.AuthMethod{} - if authmethod != nil { - authmethods = append(authmethods, authmethod) - } - - return &tunnelConfig{ - Addr: getSshAddr(tunnel), - ClientConfig: &ssh.ClientConfig{ - User: tunnel.GetUser(), - Auth: authmethods, - HostKeyCallback: hostcallback, - Timeout: 15 * time.Second, // todo: make configurable - }, - }, nil -} - -func getSshAddr(tunnel *mgmtv1alpha1.SSHTunnel) string { - host := tunnel.GetHost() - port := tunnel.GetPort() - if port > 0 { - return net.JoinHostPort(host, strconv.FormatInt(int64(port), 10)) - } - return host -} - type stdlibConnectorGetter func() (driver.Connector, func(), error) func newStdlibConnectorContainer( diff --git a/backend/pkg/sqlconnect/sql-connector_test.go b/backend/pkg/sqlconnect/sql-connector_test.go index a0a40e4c3f..48041d29da 100644 --- a/backend/pkg/sqlconnect/sql-connector_test.go +++ b/backend/pkg/sqlconnect/sql-connector_test.go @@ -142,19 +142,3 @@ func Test_NewDbFromConnectionConfig(t *testing.T) { func ptr[T any](val T) *T { return &val } - -func Test_getSshAddr(t *testing.T) { - t.Run("with port", func(t *testing.T) { - actual := getSshAddr(&mgmtv1alpha1.SSHTunnel{ - Host: "localhost", - Port: 2222, - }) - assert.Equal(t, "localhost:2222", actual) - }) - t.Run("without port", func(t *testing.T) { - actual := getSshAddr(&mgmtv1alpha1.SSHTunnel{ - Host: "localhost", - }) - assert.Equal(t, "localhost", actual) - }) -} diff --git a/backend/protos/mgmt/v1alpha1/connection.proto b/backend/protos/mgmt/v1alpha1/connection.proto index 02075aa3d0..234a47618c 100644 --- a/backend/protos/mgmt/v1alpha1/connection.proto +++ b/backend/protos/mgmt/v1alpha1/connection.proto @@ -433,6 +433,33 @@ message CheckSqlQueryResponse { optional string erorr_message = 2; } +message CheckSSHConnectionRequest { + // The SSH tunnel configuration to use for the connection + SSHTunnel tunnel = 1; +} + +message CheckSSHConnectionResponse { + // The result of the SSH connection check + CheckSSHConnectionResult result = 1; +} + +message CheckSSHConnectionByIdRequest { + // The connection id that the SSH connection will be checked against + string id = 1 [(buf.validate.field).string.uuid = true]; +} + +message CheckSSHConnectionByIdResponse { + // The result of the SSH connection check + CheckSSHConnectionResult result = 1; +} + +message CheckSSHConnectionResult { + // Whether or not the SSH connection is successful + bool is_successful = 1; + // The error message returned by the SSH client if the connection is not successful + optional string error_message = 2; +} + // Service for managing datasource connections. // This is a primary data model in Neosync and is used in reference when hooking up Jobs to synchronize and generate data. service ConnectionService { @@ -462,4 +489,8 @@ service ConnectionService { // Checks a constructed SQL query against a sql-based connection to see if it's valid based on that connection's data schema // This is useful when constructing subsets to see if the WHERE clause is correct rpc CheckSqlQuery(CheckSqlQueryRequest) returns (CheckSqlQueryResponse) {} + // Checks if the SSH server is reachable and accessible with the given credentials + rpc CheckSSHConnection(CheckSSHConnectionRequest) returns (CheckSSHConnectionResponse) {} + // Checks if the SSH server is reachable and accessible with the given credentials + rpc CheckSSHConnectionById(CheckSSHConnectionByIdRequest) returns (CheckSSHConnectionByIdResponse) {} } diff --git a/backend/services/mgmt/v1alpha1/connection-service/connection.go b/backend/services/mgmt/v1alpha1/connection-service/connection.go index b069d89dc7..136bc401b6 100644 --- a/backend/services/mgmt/v1alpha1/connection-service/connection.go +++ b/backend/services/mgmt/v1alpha1/connection-service/connection.go @@ -24,6 +24,8 @@ import ( "github.com/nucleuscloud/neosync/internal/ee/rbac" nucleuserrors "github.com/nucleuscloud/neosync/internal/errors" "github.com/nucleuscloud/neosync/internal/neosyncdb" + "github.com/nucleuscloud/neosync/internal/sshtunnel" + "golang.org/x/crypto/ssh" "golang.org/x/sync/errgroup" "go.mongodb.org/mongo-driver/bson" @@ -552,6 +554,81 @@ func (s *Service) CheckSqlQuery( }), nil } +func (s *Service) CheckSSHConnection( + ctx context.Context, + req *connect.Request[mgmtv1alpha1.CheckSSHConnectionRequest], +) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionResponse], error) { + logger := logger_interceptor.GetLoggerFromContextOrDefault(ctx) + result, err := checkSSHConnection(req.Msg.GetTunnel(), logger) + if err != nil { + return nil, err + } + return connect.NewResponse(&mgmtv1alpha1.CheckSSHConnectionResponse{ + Result: result, + }), nil +} + +func (s *Service) CheckSSHConnectionById( + ctx context.Context, + req *connect.Request[mgmtv1alpha1.CheckSSHConnectionByIdRequest], +) (*connect.Response[mgmtv1alpha1.CheckSSHConnectionByIdResponse], error) { + logger := logger_interceptor.GetLoggerFromContextOrDefault(ctx) + logger = logger.With("connectionId", req.Msg.GetId()) + connection, err := s.GetConnection(ctx, connect.NewRequest(&mgmtv1alpha1.GetConnectionRequest{Id: req.Msg.GetId()})) + if err != nil { + return nil, err + } + + var sshTunnel *mgmtv1alpha1.SSHTunnel + + switch cfg := connection.Msg.GetConnection().GetConnectionConfig().GetConfig().(type) { + case *mgmtv1alpha1.ConnectionConfig_PgConfig: + sshTunnel = cfg.PgConfig.GetTunnel() + case *mgmtv1alpha1.ConnectionConfig_MssqlConfig: + sshTunnel = cfg.MssqlConfig.GetTunnel() + case *mgmtv1alpha1.ConnectionConfig_MysqlConfig: + sshTunnel = cfg.MysqlConfig.GetTunnel() + } + + result, err := checkSSHConnection(sshTunnel, logger) + if err != nil { + return nil, err + } + + return connect.NewResponse(&mgmtv1alpha1.CheckSSHConnectionByIdResponse{ + Result: result, + }), nil +} + +func checkSSHConnection(sshTunnel *mgmtv1alpha1.SSHTunnel, logger *slog.Logger) (*mgmtv1alpha1.CheckSSHConnectionResult, error) { + if sshTunnel == nil { + errorMsg := "no ssh tunnel config found" + return &mgmtv1alpha1.CheckSSHConnectionResult{ + IsSuccessful: false, + ErrorMessage: &errorMsg, + }, nil + } + + tunnelConfig, err := sshtunnel.GetTunnelConfigFromSSHDto(sshTunnel) + if err != nil { + return nil, fmt.Errorf("unable to build tunnel config from dto: %w", err) + } + client, err := ssh.Dial("tcp", tunnelConfig.Addr, tunnelConfig.ClientConfig) + if err != nil { + errorMsg := err.Error() + logger.Error(fmt.Sprintf("unable to dial ssh: %s", errorMsg)) + return &mgmtv1alpha1.CheckSSHConnectionResult{ + IsSuccessful: false, + ErrorMessage: &errorMsg, + }, nil + } + client.Close() + + return &mgmtv1alpha1.CheckSSHConnectionResult{ + IsSuccessful: true, + }, nil +} + type urlEnvVarConfig interface { GetUrlFromEnv() string } diff --git a/docs/openapi/mgmt/v1alpha1/connection.openapi.yaml b/docs/openapi/mgmt/v1alpha1/connection.openapi.yaml index de6f12227f..95d32865d2 100644 --- a/docs/openapi/mgmt/v1alpha1/connection.openapi.yaml +++ b/docs/openapi/mgmt/v1alpha1/connection.openapi.yaml @@ -346,6 +346,74 @@ components: title: privileges title: CheckConnectionConfigResponse additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionByIdRequest: + type: object + properties: + id: + type: string + title: id + format: uuid + description: The connection id that the SSH connection will be checked against + title: CheckSSHConnectionByIdRequest + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionByIdResponse: + type: object + properties: + result: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResult' + title: result + description: The result of the SSH connection check + title: CheckSSHConnectionByIdResponse + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionRequest: + type: object + properties: + tunnel: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.SSHTunnel' + title: tunnel + description: The SSH tunnel configuration to use for the connection + title: CheckSSHConnectionRequest + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionResponse: + type: object + properties: + result: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResult' + title: result + description: The result of the SSH connection check + title: CheckSSHConnectionResponse + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionResult: + type: object + allOf: + - anyOf: + - required: + - errorMessage + - not: + anyOf: + - required: + - errorMessage + anyOf: + - required: + - errorMessage + - not: + anyOf: + - required: + - errorMessage + properties: + isSuccessful: + type: boolean + title: is_successful + description: Whether or not the SSH connection is successful + errorMessage: + type: string + title: error_message + description: The error message returned by the SSH client if the connection is not successful + title: CheckSSHConnectionResult + additionalProperties: false mgmt.v1alpha1.CheckSqlQueryRequest: type: object properties: @@ -1771,6 +1839,78 @@ paths: application/json: schema: $ref: '#/components/schemas/mgmt.v1alpha1.CheckSqlQueryResponse' + /mgmt.v1alpha1.ConnectionService/CheckSSHConnection: + post: + tags: + - mgmt.v1alpha1.ConnectionService + summary: CheckSSHConnection + description: Checks if the SSH server is reachable and accessible with the given credentials + operationId: mgmt.v1alpha1.ConnectionService.CheckSSHConnection + parameters: + - name: Connect-Protocol-Version + in: header + required: true + schema: + $ref: '#/components/schemas/connect-protocol-version' + - name: Connect-Timeout-Ms + in: header + schema: + $ref: '#/components/schemas/connect-timeout-header' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionRequest' + required: true + responses: + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/connect.error' + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResponse' + /mgmt.v1alpha1.ConnectionService/CheckSSHConnectionById: + post: + tags: + - mgmt.v1alpha1.ConnectionService + summary: CheckSSHConnectionById + description: Checks if the SSH server is reachable and accessible with the given credentials + operationId: mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById + parameters: + - name: Connect-Protocol-Version + in: header + required: true + schema: + $ref: '#/components/schemas/connect-protocol-version' + - name: Connect-Timeout-Ms + in: header + schema: + $ref: '#/components/schemas/connect-timeout-header' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionByIdRequest' + required: true + responses: + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/connect.error' + "200": + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionByIdResponse' tags: - name: mgmt.v1alpha1.ConnectionService description: |- diff --git a/docs/openapi/neosync.mgmt.v1alpha1.yaml b/docs/openapi/neosync.mgmt.v1alpha1.yaml index efdc8c1a1d..809befe413 100644 --- a/docs/openapi/neosync.mgmt.v1alpha1.yaml +++ b/docs/openapi/neosync.mgmt.v1alpha1.yaml @@ -1358,6 +1358,87 @@ paths: $ref: '#/components/schemas/connect.error' security: - BearerAuth: [] + /mgmt.v1alpha1.ConnectionService/CheckSSHConnection: + post: + tags: + - mgmt.v1alpha1.ConnectionService + summary: CheckSSHConnection + description: >- + Checks if the SSH server is reachable and accessible with the given + credentials + operationId: mgmt.v1alpha1.ConnectionService.CheckSSHConnection + parameters: + - name: Connect-Protocol-Version + in: header + required: true + schema: + $ref: '#/components/schemas/connect-protocol-version' + - name: Connect-Timeout-Ms + in: header + schema: + $ref: '#/components/schemas/connect-timeout-header' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResponse' + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/connect.error' + security: + - BearerAuth: [] + /mgmt.v1alpha1.ConnectionService/CheckSSHConnectionById: + post: + tags: + - mgmt.v1alpha1.ConnectionService + summary: CheckSSHConnectionById + description: >- + Checks if the SSH server is reachable and accessible with the given + credentials + operationId: mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById + parameters: + - name: Connect-Protocol-Version + in: header + required: true + schema: + $ref: '#/components/schemas/connect-protocol-version' + - name: Connect-Timeout-Ms + in: header + schema: + $ref: '#/components/schemas/connect-timeout-header' + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionByIdRequest' + required: true + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: >- + #/components/schemas/mgmt.v1alpha1.CheckSSHConnectionByIdResponse + default: + description: Error + content: + application/json: + schema: + $ref: '#/components/schemas/connect.error' + security: + - BearerAuth: [] /mgmt.v1alpha1.ConnectionDataService/GetConnectionDataStream: {} /mgmt.v1alpha1.ConnectionDataService/GetConnectionSchema: post: @@ -7986,6 +8067,76 @@ components: title: privileges title: CheckConnectionConfigResponse additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionByIdRequest: + type: object + properties: + id: + type: string + title: id + format: uuid + description: The connection id that the SSH connection will be checked against + title: CheckSSHConnectionByIdRequest + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionByIdResponse: + type: object + properties: + result: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResult' + title: result + description: The result of the SSH connection check + title: CheckSSHConnectionByIdResponse + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionRequest: + type: object + properties: + tunnel: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.SSHTunnel' + title: tunnel + description: The SSH tunnel configuration to use for the connection + title: CheckSSHConnectionRequest + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionResponse: + type: object + properties: + result: + allOf: + - $ref: '#/components/schemas/mgmt.v1alpha1.CheckSSHConnectionResult' + title: result + description: The result of the SSH connection check + title: CheckSSHConnectionResponse + additionalProperties: false + mgmt.v1alpha1.CheckSSHConnectionResult: + type: object + allOf: + - anyOf: + - required: + - errorMessage + - not: + anyOf: + - required: + - errorMessage + anyOf: + - required: + - errorMessage + - not: + anyOf: + - required: + - errorMessage + properties: + isSuccessful: + type: boolean + title: is_successful + description: Whether or not the SSH connection is successful + errorMessage: + type: string + title: error_message + description: >- + The error message returned by the SSH client if the connection is + not successful + title: CheckSSHConnectionResult + additionalProperties: false mgmt.v1alpha1.CheckSqlQueryRequest: type: object properties: diff --git a/docs/protos/mgmt/v1alpha1/connection.proto.mdx b/docs/protos/mgmt/v1alpha1/connection.proto.mdx index c4b5b8c924..c9c2e037d5 100644 --- a/docs/protos/mgmt/v1alpha1/connection.proto.mdx +++ b/docs/protos/mgmt/v1alpha1/connection.proto.mdx @@ -41,136 +41,156 @@ _**package** mgmt.v1alpha1_ +### `CheckSSHConnectionByIdRequest` + + + +### `CheckSSHConnectionByIdResponse` + + + +### `CheckSSHConnectionRequest` + + + +### `CheckSSHConnectionResponse` + + + +### `CheckSSHConnectionResult` + + + ### `CheckSqlQueryRequest` - + ### `CheckSqlQueryResponse` - + ### `ClientTlsConfig` - + ### `Connection` - + ### `ConnectionConfig` - + ### `ConnectionRolePrivilege` - + ### `CreateConnectionRequest` - + ### `CreateConnectionResponse` - + ### `DeleteConnectionRequest` - + ### `DeleteConnectionResponse` - + ### `DynamoDBConnectionConfig` - + ### `GcpCloudStorageConnectionConfig` - + ### `GetConnectionRequest` - + ### `GetConnectionResponse` - + ### `GetConnectionsRequest` - + ### `GetConnectionsResponse` - + ### `IsConnectionNameAvailableRequest` - + ### `IsConnectionNameAvailableResponse` - + ### `LocalDirectoryConnectionConfig` - + ### `MongoConnectionConfig` - + ### `MssqlConnectionConfig` - + ### `MysqlConnection` - + ### `MysqlConnectionConfig` - + ### `OpenAiConnectionConfig` - + ### `PostgresConnection` - + ### `PostgresConnectionConfig` - + ### `SSHAuthentication` - + ### `SSHPassphrase` - + ### `SSHPrivateKey` - + ### `SSHTunnel` - + ### `SqlConnectionOptions` - + ### `UpdateConnectionRequest` - + ### `UpdateConnectionResponse` - + --- ## Services @@ -218,6 +238,14 @@ This is a primary data model in Neosync and is used in reference when hooking up +#### `CheckSSHConnection` + + + +#### `CheckSSHConnectionById` + + + --- diff --git a/docs/protos/proto_docs.json b/docs/protos/proto_docs.json index 4c58e2f816..729bbc90dc 100644 --- a/docs/protos/proto_docs.json +++ b/docs/protos/proto_docs.json @@ -6327,6 +6327,138 @@ } ] }, + { + "name": "CheckSSHConnectionByIdRequest", + "longName": "CheckSSHConnectionByIdRequest", + "fullName": "mgmt.v1alpha1.CheckSSHConnectionByIdRequest", + "description": "", + "hasExtensions": false, + "hasFields": true, + "hasOneofs": false, + "extensions": [], + "fields": [ + { + "name": "id", + "description": "The connection id that the SSH connection will be checked against", + "label": "", + "type": "string", + "longType": "string", + "fullType": "string", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "" + } + ] + }, + { + "name": "CheckSSHConnectionByIdResponse", + "longName": "CheckSSHConnectionByIdResponse", + "fullName": "mgmt.v1alpha1.CheckSSHConnectionByIdResponse", + "description": "", + "hasExtensions": false, + "hasFields": true, + "hasOneofs": false, + "extensions": [], + "fields": [ + { + "name": "result", + "description": "The result of the SSH connection check", + "label": "", + "type": "CheckSSHConnectionResult", + "longType": "CheckSSHConnectionResult", + "fullType": "mgmt.v1alpha1.CheckSSHConnectionResult", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "" + } + ] + }, + { + "name": "CheckSSHConnectionRequest", + "longName": "CheckSSHConnectionRequest", + "fullName": "mgmt.v1alpha1.CheckSSHConnectionRequest", + "description": "", + "hasExtensions": false, + "hasFields": true, + "hasOneofs": false, + "extensions": [], + "fields": [ + { + "name": "tunnel", + "description": "The SSH tunnel configuration to use for the connection", + "label": "", + "type": "SSHTunnel", + "longType": "SSHTunnel", + "fullType": "mgmt.v1alpha1.SSHTunnel", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "" + } + ] + }, + { + "name": "CheckSSHConnectionResponse", + "longName": "CheckSSHConnectionResponse", + "fullName": "mgmt.v1alpha1.CheckSSHConnectionResponse", + "description": "", + "hasExtensions": false, + "hasFields": true, + "hasOneofs": false, + "extensions": [], + "fields": [ + { + "name": "result", + "description": "The result of the SSH connection check", + "label": "", + "type": "CheckSSHConnectionResult", + "longType": "CheckSSHConnectionResult", + "fullType": "mgmt.v1alpha1.CheckSSHConnectionResult", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "" + } + ] + }, + { + "name": "CheckSSHConnectionResult", + "longName": "CheckSSHConnectionResult", + "fullName": "mgmt.v1alpha1.CheckSSHConnectionResult", + "description": "", + "hasExtensions": false, + "hasFields": true, + "hasOneofs": true, + "extensions": [], + "fields": [ + { + "name": "is_successful", + "description": "Whether or not the SSH connection is successful", + "label": "", + "type": "bool", + "longType": "bool", + "fullType": "bool", + "ismap": false, + "isoneof": false, + "oneofdecl": "", + "defaultValue": "" + }, + { + "name": "error_message", + "description": "The error message returned by the SSH client if the connection is not successful", + "label": "optional", + "type": "string", + "longType": "string", + "fullType": "string", + "ismap": false, + "isoneof": true, + "oneofdecl": "_error_message", + "defaultValue": "" + } + ] + }, { "name": "CheckSqlQueryRequest", "longName": "CheckSqlQueryRequest", @@ -8067,6 +8199,30 @@ "responseLongType": "CheckSqlQueryResponse", "responseFullType": "mgmt.v1alpha1.CheckSqlQueryResponse", "responseStreaming": false + }, + { + "name": "CheckSSHConnection", + "description": "Checks if the SSH server is reachable and accessible with the given credentials", + "requestType": "CheckSSHConnectionRequest", + "requestLongType": "CheckSSHConnectionRequest", + "requestFullType": "mgmt.v1alpha1.CheckSSHConnectionRequest", + "requestStreaming": false, + "responseType": "CheckSSHConnectionResponse", + "responseLongType": "CheckSSHConnectionResponse", + "responseFullType": "mgmt.v1alpha1.CheckSSHConnectionResponse", + "responseStreaming": false + }, + { + "name": "CheckSSHConnectionById", + "description": "Checks if the SSH server is reachable and accessible with the given credentials", + "requestType": "CheckSSHConnectionByIdRequest", + "requestLongType": "CheckSSHConnectionByIdRequest", + "requestFullType": "mgmt.v1alpha1.CheckSSHConnectionByIdRequest", + "requestStreaming": false, + "responseType": "CheckSSHConnectionByIdResponse", + "responseLongType": "CheckSSHConnectionByIdResponse", + "responseFullType": "mgmt.v1alpha1.CheckSSHConnectionByIdResponse", + "responseStreaming": false } ] } diff --git a/frontend/apps/web/app/(mgmt)/[account]/connections/util.ts b/frontend/apps/web/app/(mgmt)/[account]/connections/util.ts index 1b45a37a92..b03a683fa1 100644 --- a/frontend/apps/web/app/(mgmt)/[account]/connections/util.ts +++ b/frontend/apps/web/app/(mgmt)/[account]/connections/util.ts @@ -577,7 +577,9 @@ function getClientTlsConfig( }); } -function getTunnelConfig(values?: SshTunnelFormValues): SSHTunnel | undefined { +export function getTunnelConfig( + values?: SshTunnelFormValues +): SSHTunnel | undefined { if (!values || !values.host) { return undefined; } diff --git a/frontend/apps/web/components/connections/forms/SharedFormInputs.tsx b/frontend/apps/web/components/connections/forms/SharedFormInputs.tsx index 29625e7d6b..0909fefe63 100644 --- a/frontend/apps/web/components/connections/forms/SharedFormInputs.tsx +++ b/frontend/apps/web/components/connections/forms/SharedFormInputs.tsx @@ -17,6 +17,7 @@ import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; +import { getErrorMessage } from '@/util/util'; import { AwsAdvancedFormValues, AwsCredentialsFormValues, @@ -32,10 +33,17 @@ import { CheckConnectionConfigRequest, CheckConnectionConfigResponse, CheckConnectionConfigResponseSchema, + CheckSSHConnectionByIdRequest, + CheckSSHConnectionRequest, + CheckSSHConnectionResult, ConnectionService, } from '@neosync/sdk'; -import { ExclamationTriangleIcon } from '@radix-ui/react-icons'; +import { + CheckCircledIcon, + ExclamationTriangleIcon, +} from '@radix-ui/react-icons'; import { ReactElement, useState } from 'react'; +import { toast } from 'sonner'; export interface SecretRevealProps { isViewMode: boolean; @@ -301,6 +309,8 @@ interface SshTunnelAccordionProps value: SshTunnelFormValues; onChange(value: SshTunnelFormValues): void; errors: Record; + onCheckRequest(): CheckSSHConnectionRequest; + onCheckIdRequest(): CheckSSHConnectionByIdRequest; } export function SshTunnelAccordion( @@ -326,11 +336,21 @@ interface SSHTunnelProps extends SecretRevealProps { value: SshTunnelFormValues; onChange(value: SshTunnelFormValues): void; errors: Record; + onCheckRequest(): CheckSSHConnectionRequest; + onCheckIdRequest(): CheckSSHConnectionByIdRequest; } function SSHTunnel(props: SSHTunnelProps): ReactElement { - const { value, onChange, errors, isViewMode, canViewSecrets, onRevealClick } = - props; + const { + value, + onChange, + errors, + isViewMode, + canViewSecrets, + onRevealClick, + onCheckRequest, + onCheckIdRequest, + } = props; return ( <> @@ -458,11 +478,94 @@ function SSHTunnel(props: SSHTunnelProps): ReactElement { placeholder="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAlkjd9s7aJkfdLk3jSLkfj2lk3j2lkfj2l3kjf2lkfj2l" /> +
+ +
); } +interface CheckSSHConnectionButtonProps { + onCheckRequest(): CheckSSHConnectionRequest; + onCheckIdRequest(): CheckSSHConnectionByIdRequest; + isViewMode: boolean; +} + +function CheckSSHConnectionButton( + props: CheckSSHConnectionButtonProps +): ReactElement { + const { onCheckRequest, onCheckIdRequest, isViewMode } = props; + const { mutateAsync: checkSSHConnection } = useMutation( + ConnectionService.method.checkSSHConnection + ); + const { mutateAsync: checkSSHConnectionById } = useMutation( + ConnectionService.method.checkSSHConnectionById + ); + const [isChecking, setIsChecking] = useState(false); + const [checkResponse, setCheckResponse] = useState< + CheckSSHConnectionResult | undefined + >(); + + async function onClick(): Promise { + if (isChecking) { + return; + } + try { + setCheckResponse(undefined); + setIsChecking(true); + if (isViewMode) { + const res = await checkSSHConnectionById(onCheckIdRequest()); + setCheckResponse(res.result); + } else { + const res = await checkSSHConnection(onCheckRequest()); + setCheckResponse(res.result); + } + } catch (err) { + console.error(err); + toast.error('Unable to connect to SSH tunnel', { + description: getErrorMessage(err), + }); + } finally { + setIsChecking(false); + } + } + + return ( +
+
+ {checkResponse?.isSuccessful && ( + + )} + {checkResponse && !checkResponse.isSuccessful && ( + + )} + + +
+ {checkResponse && ( +
+ {checkResponse.errorMessage && ( + + )} +
+ )} +
+ ); +} + interface CheckConnectionButtonProps { isValid: boolean; connectionName: string; diff --git a/frontend/apps/web/components/connections/forms/mysql/MysqlForm.tsx b/frontend/apps/web/components/connections/forms/mysql/MysqlForm.tsx index 7f655b02d8..17de65a9e8 100644 --- a/frontend/apps/web/components/connections/forms/mysql/MysqlForm.tsx +++ b/frontend/apps/web/components/connections/forms/mysql/MysqlForm.tsx @@ -1,4 +1,7 @@ -import { buildConnectionConfigMysql } from '@/app/(mgmt)/[account]/connections/util'; +import { + buildConnectionConfigMysql, + getTunnelConfig, +} from '@/app/(mgmt)/[account]/connections/util'; import Submit from '@/components/forms/Submit'; import { useAccount } from '@/components/providers/account-provider'; import { BaseStore } from '@/util/zustand.stores.util'; @@ -8,6 +11,8 @@ import { useMutation } from '@connectrpc/connect-query'; import { CheckConnectionConfigByIdRequestSchema, CheckConnectionConfigRequestSchema, + CheckSSHConnectionByIdRequestSchema, + CheckSSHConnectionRequestSchema, ConnectionService, } from '@neosync/sdk'; import { ReactElement, useEffect } from 'react'; @@ -193,6 +198,16 @@ export default function MysqlForm(props: Props): ReactElement { const values = await getValueWithSecrets?.(); return values?.tunnel; }} + onCheckRequest={() => { + return createMessage(CheckSSHConnectionRequestSchema, { + tunnel: getTunnelConfig(formData.tunnel), + }); + }} + onCheckIdRequest={() => { + return createMessage(CheckSSHConnectionByIdRequestSchema, { + id: connectionId ?? '', + }); + }} />
diff --git a/frontend/apps/web/components/connections/forms/postgres/PostgresForm.tsx b/frontend/apps/web/components/connections/forms/postgres/PostgresForm.tsx index fb4d8af05a..90b6f54435 100644 --- a/frontend/apps/web/components/connections/forms/postgres/PostgresForm.tsx +++ b/frontend/apps/web/components/connections/forms/postgres/PostgresForm.tsx @@ -1,4 +1,7 @@ -import { buildConnectionConfigPostgres } from '@/app/(mgmt)/[account]/connections/util'; +import { + buildConnectionConfigPostgres, + getTunnelConfig, +} from '@/app/(mgmt)/[account]/connections/util'; import Submit from '@/components/forms/Submit'; import { useAccount } from '@/components/providers/account-provider'; import { BaseStore } from '@/util/zustand.stores.util'; @@ -8,6 +11,8 @@ import { useMutation } from '@connectrpc/connect-query'; import { CheckConnectionConfigByIdRequestSchema, CheckConnectionConfigRequestSchema, + CheckSSHConnectionByIdRequestSchema, + CheckSSHConnectionRequestSchema, ConnectionService, } from '@neosync/sdk'; import { ReactElement, useEffect } from 'react'; @@ -196,6 +201,16 @@ export default function PostgresForm(props: Props): ReactElement { const values = await getValueWithSecrets?.(); return values?.tunnel; }} + onCheckRequest={() => { + return createMessage(CheckSSHConnectionRequestSchema, { + tunnel: getTunnelConfig(formData.tunnel), + }); + }} + onCheckIdRequest={() => { + return createMessage(CheckSSHConnectionByIdRequestSchema, { + id: connectionId ?? '', + }); + }} />
diff --git a/frontend/apps/web/components/connections/forms/sql-server/SqlServerForm.tsx b/frontend/apps/web/components/connections/forms/sql-server/SqlServerForm.tsx index 862dde531c..1ca5688f4b 100644 --- a/frontend/apps/web/components/connections/forms/sql-server/SqlServerForm.tsx +++ b/frontend/apps/web/components/connections/forms/sql-server/SqlServerForm.tsx @@ -1,4 +1,7 @@ -import { buildConnectionConfigMssql } from '@/app/(mgmt)/[account]/connections/util'; +import { + buildConnectionConfigMssql, + getTunnelConfig, +} from '@/app/(mgmt)/[account]/connections/util'; import Submit from '@/components/forms/Submit'; import { useAccount } from '@/components/providers/account-provider'; import { BaseStore } from '@/util/zustand.stores.util'; @@ -8,6 +11,8 @@ import { useMutation } from '@connectrpc/connect-query'; import { CheckConnectionConfigByIdRequestSchema, CheckConnectionConfigRequestSchema, + CheckSSHConnectionByIdRequestSchema, + CheckSSHConnectionRequestSchema, ConnectionService, } from '@neosync/sdk'; import { ReactElement, useEffect } from 'react'; @@ -184,6 +189,16 @@ export default function SqlServerForm(props: Props): ReactElement { const values = await getValueWithSecrets?.(); return values?.tunnel; }} + onCheckRequest={() => { + return createMessage(CheckSSHConnectionRequestSchema, { + tunnel: getTunnelConfig(formData.tunnel), + }); + }} + onCheckIdRequest={() => { + return createMessage(CheckSSHConnectionByIdRequestSchema, { + id: connectionId ?? '', + }); + }} />
diff --git a/frontend/packages/sdk/src/client/mgmt/v1alpha1/connection_pb.ts b/frontend/packages/sdk/src/client/mgmt/v1alpha1/connection_pb.ts index dc639947c7..3e6914cb1a 100644 --- a/frontend/packages/sdk/src/client/mgmt/v1alpha1/connection_pb.ts +++ b/frontend/packages/sdk/src/client/mgmt/v1alpha1/connection_pb.ts @@ -13,7 +13,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file mgmt/v1alpha1/connection.proto. */ export const file_mgmt_v1alpha1_connection: GenFile = /*@__PURE__*/ - fileDesc("Ch5tZ210L3YxYWxwaGExL2Nvbm5lY3Rpb24ucHJvdG8SDW1nbXQudjFhbHBoYTEiUAoVR2V0Q29ubmVjdGlvbnNSZXF1ZXN0EhwKCmFjY291bnRfaWQYASABKAlCCLpIBXIDsAEBEhkKEWV4Y2x1ZGVfc2Vuc2l0aXZlGAIgASgIIkgKFkdldENvbm5lY3Rpb25zUmVzcG9uc2USLgoLY29ubmVjdGlvbnMYASADKAsyGS5tZ210LnYxYWxwaGExLkNvbm5lY3Rpb24iRwoUR2V0Q29ubmVjdGlvblJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEhkKEWV4Y2x1ZGVfc2Vuc2l0aXZlGAIgASgIIkYKFUdldENvbm5lY3Rpb25SZXNwb25zZRItCgpjb25uZWN0aW9uGAEgASgLMhkubWdtdC52MWFscGhhMS5Db25uZWN0aW9uIpwBChdDcmVhdGVDb25uZWN0aW9uUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABARInCgRuYW1lGAIgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kEjoKEWNvbm5lY3Rpb25fY29uZmlnGAMgASgLMh8ubWdtdC52MWFscGhhMS5Db25uZWN0aW9uQ29uZmlnIkkKGENyZWF0ZUNvbm5lY3Rpb25SZXNwb25zZRItCgpjb25uZWN0aW9uGAEgASgLMhkubWdtdC52MWFscGhhMS5Db25uZWN0aW9uIpQBChdVcGRhdGVDb25uZWN0aW9uUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESJwoEbmFtZRgCIAEoCUIZukgWchQyEl5bYS16MC05LV17MywxMDB9JBI6ChFjb25uZWN0aW9uX2NvbmZpZxgDIAEoCzIfLm1nbXQudjFhbHBoYTEuQ29ubmVjdGlvbkNvbmZpZyJJChhVcGRhdGVDb25uZWN0aW9uUmVzcG9uc2USLQoKY29ubmVjdGlvbhgBIAEoCzIZLm1nbXQudjFhbHBoYTEuQ29ubmVjdGlvbiIvChdEZWxldGVDb25uZWN0aW9uUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiGgoYRGVsZXRlQ29ubmVjdGlvblJlc3BvbnNlIloKHENoZWNrQ29ubmVjdGlvbkNvbmZpZ1JlcXVlc3QSOgoRY29ubmVjdGlvbl9jb25maWcYASABKAsyHy5tZ210LnYxYWxwaGExLkNvbm5lY3Rpb25Db25maWciOAogQ2hlY2tDb25uZWN0aW9uQ29uZmlnQnlJZFJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIqkBCiFDaGVja0Nvbm5lY3Rpb25Db25maWdCeUlkUmVzcG9uc2USFAoMaXNfY29ubmVjdGVkGAEgASgIEh0KEGNvbm5lY3Rpb25fZXJyb3IYAiABKAlIAIgBARI6Cgpwcml2aWxlZ2VzGAMgAygLMiYubWdtdC52MWFscGhhMS5Db25uZWN0aW9uUm9sZVByaXZpbGVnZUITChFfY29ubmVjdGlvbl9lcnJvciKlAQodQ2hlY2tDb25uZWN0aW9uQ29uZmlnUmVzcG9uc2USFAoMaXNfY29ubmVjdGVkGAEgASgIEh0KEGNvbm5lY3Rpb25fZXJyb3IYAiABKAlIAIgBARI6Cgpwcml2aWxlZ2VzGAMgAygLMiYubWdtdC52MWFscGhhMS5Db25uZWN0aW9uUm9sZVByaXZpbGVnZUITChFfY29ubmVjdGlvbl9lcnJvciJhChdDb25uZWN0aW9uUm9sZVByaXZpbGVnZRIPCgdncmFudGVlGAEgASgJEg4KBnNjaGVtYRgCIAEoCRINCgV0YWJsZRgDIAEoCRIWCg5wcml2aWxlZ2VfdHlwZRgEIAMoCSKOAgoKQ29ubmVjdGlvbhIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEjoKEWNvbm5lY3Rpb25fY29uZmlnGAMgASgLMh8ubWdtdC52MWFscGhhMS5Db25uZWN0aW9uQ29uZmlnEhoKEmNyZWF0ZWRfYnlfdXNlcl9pZBgEIAEoCRIuCgpjcmVhdGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJ1cGRhdGVkX2J5X3VzZXJfaWQYBiABKAkSLgoKdXBkYXRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASEgoKYWNjb3VudF9pZBgIIAEoCSL8BAoQQ29ubmVjdGlvbkNvbmZpZxI8CglwZ19jb25maWcYASABKAsyJy5tZ210LnYxYWxwaGExLlBvc3RncmVzQ29ubmVjdGlvbkNvbmZpZ0gAEj0KDWF3c19zM19jb25maWcYAiABKAsyJC5tZ210LnYxYWxwaGExLkF3c1MzQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG15c3FsX2NvbmZpZxgDIAEoCzIkLm1nbXQudjFhbHBoYTEuTXlzcWxDb25uZWN0aW9uQ29uZmlnSAASSQoQbG9jYWxfZGlyX2NvbmZpZxgEIAEoCzItLm1nbXQudjFhbHBoYTEuTG9jYWxEaXJlY3RvcnlDb25uZWN0aW9uQ29uZmlnSAASPgoNb3BlbmFpX2NvbmZpZxgFIAEoCzIlLm1nbXQudjFhbHBoYTEuT3BlbkFpQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG1vbmdvX2NvbmZpZxgGIAEoCzIkLm1nbXQudjFhbHBoYTEuTW9uZ29Db25uZWN0aW9uQ29uZmlnSAASUQoXZ2NwX2Nsb3Vkc3RvcmFnZV9jb25maWcYByABKAsyLi5tZ210LnYxYWxwaGExLkdjcENsb3VkU3RvcmFnZUNvbm5lY3Rpb25Db25maWdIABJCCg9keW5hbW9kYl9jb25maWcYCCABKAsyJy5tZ210LnYxYWxwaGExLkR5bmFtb0RCQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG1zc3FsX2NvbmZpZxgJIAEoCzIkLm1nbXQudjFhbHBoYTEuTXNzcWxDb25uZWN0aW9uQ29uZmlnSABCDwoGY29uZmlnEgW6SAIIASL5AQoVTXNzcWxDb25uZWN0aW9uQ29uZmlnEg0KA3VybBgBIAEoCUgAEhYKDHVybF9mcm9tX2VudhgFIAEoCUgAEj8KEmNvbm5lY3Rpb25fb3B0aW9ucxgCIAEoCzIjLm1nbXQudjFhbHBoYTEuU3FsQ29ubmVjdGlvbk9wdGlvbnMSKAoGdHVubmVsGAMgASgLMhgubWdtdC52MWFscGhhMS5TU0hUdW5uZWwSMgoKY2xpZW50X3RscxgEIAEoCzIeLm1nbXQudjFhbHBoYTEuQ2xpZW50VGxzQ29uZmlnQhoKEWNvbm5lY3Rpb25fY29uZmlnEgW6SAIIASKpAQoYRHluYW1vREJDb25uZWN0aW9uQ29uZmlnEjkKC2NyZWRlbnRpYWxzGAEgASgLMh8ubWdtdC52MWFscGhhMS5Bd3NTM0NyZWRlbnRpYWxzSACIAQESEwoGcmVnaW9uGAIgASgJSAGIAQESFQoIZW5kcG9pbnQYAyABKAlIAogBAUIOCgxfY3JlZGVudGlhbHNCCQoHX3JlZ2lvbkILCglfZW5kcG9pbnQioAEKFU1vbmdvQ29ubmVjdGlvbkNvbmZpZxINCgN1cmwYASABKAlIABIoCgZ0dW5uZWwYAiABKAsyGC5tZ210LnYxYWxwaGExLlNTSFR1bm5lbBIyCgpjbGllbnRfdGxzGAMgASgLMh4ubWdtdC52MWFscGhhMS5DbGllbnRUbHNDb25maWdCGgoRY29ubmVjdGlvbl9jb25maWcSBbpIAggBIjoKFk9wZW5BaUNvbm5lY3Rpb25Db25maWcSDwoHYXBpX2tleRgBIAEoCRIPCgdhcGlfdXJsGAIgASgJIjcKHkxvY2FsRGlyZWN0b3J5Q29ubmVjdGlvbkNvbmZpZxIVCgRwYXRoGAEgASgJQge6SARyAhABIrUCChhQb3N0Z3Jlc0Nvbm5lY3Rpb25Db25maWcSDQoDdXJsGAEgASgJSAASNwoKY29ubmVjdGlvbhgCIAEoCzIhLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNDb25uZWN0aW9uSAASFgoMdXJsX2Zyb21fZW52GAYgASgJSAASKAoGdHVubmVsGAMgASgLMhgubWdtdC52MWFscGhhMS5TU0hUdW5uZWwSPwoSY29ubmVjdGlvbl9vcHRpb25zGAQgASgLMiMubWdtdC52MWFscGhhMS5TcWxDb25uZWN0aW9uT3B0aW9ucxIyCgpjbGllbnRfdGxzGAUgASgLMh4ubWdtdC52MWFscGhhMS5DbGllbnRUbHNDb25maWdCGgoRY29ubmVjdGlvbl9jb25maWcSBbpIAggBIrMBCg9DbGllbnRUbHNDb25maWcSFgoJcm9vdF9jZXJ0GAEgASgJSACIAQESGAoLY2xpZW50X2NlcnQYAiABKAlIAYgBARIXCgpjbGllbnRfa2V5GAMgASgJSAKIAQESGAoLc2VydmVyX25hbWUYBCABKAlIA4gBAUIMCgpfcm9vdF9jZXJ0Qg4KDF9jbGllbnRfY2VydEINCgtfY2xpZW50X2tleUIOCgxfc2VydmVyX25hbWUi+gEKFFNxbENvbm5lY3Rpb25PcHRpb25zEiEKFG1heF9jb25uZWN0aW9uX2xpbWl0GAEgASgFSACIAQESIQoUbWF4X2lkbGVfY29ubmVjdGlvbnMYAiABKAVIAYgBARIeChFtYXhfaWRsZV9kdXJhdGlvbhgDIAEoCUgCiAEBEh4KEW1heF9vcGVuX2R1cmF0aW9uGAQgASgJSAOIAQFCFwoVX21heF9jb25uZWN0aW9uX2xpbWl0QhcKFV9tYXhfaWRsZV9jb25uZWN0aW9uc0IUChJfbWF4X2lkbGVfZHVyYXRpb25CFAoSX21heF9vcGVuX2R1cmF0aW9uItEBCglTU0hUdW5uZWwSFQoEaG9zdBgBIAEoCUIHukgEcgIQARIVCgRwb3J0GAIgASgFQge6SAQaAigAEhUKBHVzZXIYAyABKAlCB7pIBHICEAESKwoVa25vd25faG9zdF9wdWJsaWNfa2V5GAQgASgJQge6SARyAhABSACIAQESOAoOYXV0aGVudGljYXRpb24YBSABKAsyIC5tZ210LnYxYWxwaGExLlNTSEF1dGhlbnRpY2F0aW9uQhgKFl9rbm93bl9ob3N0X3B1YmxpY19rZXkikgEKEVNTSEF1dGhlbnRpY2F0aW9uEjIKCnBhc3NwaHJhc2UYASABKAsyHC5tZ210LnYxYWxwaGExLlNTSFBhc3NwaHJhc2VIABIzCgtwcml2YXRlX2tleRgCIAEoCzIcLm1nbXQudjFhbHBoYTEuU1NIUHJpdmF0ZUtleUgAQhQKC2F1dGhfY29uZmlnEgW6SAIIASInCg1TU0hQYXNzcGhyYXNlEhYKBXZhbHVlGAEgASgJQge6SARyAhABIk8KDVNTSFByaXZhdGVLZXkSFgoFdmFsdWUYASABKAlCB7pIBHICEAESFwoKcGFzc3BocmFzZRgCIAEoCUgAiAEBQg0KC19wYXNzcGhyYXNlIn4KElBvc3RncmVzQ29ubmVjdGlvbhIMCgRob3N0GAEgASgJEgwKBHBvcnQYAiABKAUSDAoEbmFtZRgDIAEoCRIMCgR1c2VyGAQgASgJEgwKBHBhc3MYBSABKAkSFQoIc3NsX21vZGUYBiABKAlIAIgBAUILCglfc3NsX21vZGUiaQoPTXlzcWxDb25uZWN0aW9uEgwKBHVzZXIYASABKAkSDAoEcGFzcxgCIAEoCRIQCghwcm90b2NvbBgDIAEoCRIMCgRob3N0GAQgASgJEgwKBHBvcnQYBSABKAUSDAoEbmFtZRgGIAEoCSKvAgoVTXlzcWxDb25uZWN0aW9uQ29uZmlnEg0KA3VybBgBIAEoCUgAEjQKCmNvbm5lY3Rpb24YAiABKAsyHi5tZ210LnYxYWxwaGExLk15c3FsQ29ubmVjdGlvbkgAEhYKDHVybF9mcm9tX2VudhgGIAEoCUgAEigKBnR1bm5lbBgDIAEoCzIYLm1nbXQudjFhbHBoYTEuU1NIVHVubmVsEj8KEmNvbm5lY3Rpb25fb3B0aW9ucxgEIAEoCzIjLm1nbXQudjFhbHBoYTEuU3FsQ29ubmVjdGlvbk9wdGlvbnMSMgoKY2xpZW50X3RscxgFIAEoCzIeLm1nbXQudjFhbHBoYTEuQ2xpZW50VGxzQ29uZmlnQhoKEWNvbm5lY3Rpb25fY29uZmlnEgW6SAIIASLvAQoVQXdzUzNDb25uZWN0aW9uQ29uZmlnEhgKC3BhdGhfcHJlZml4GAIgASgJSACIAQESOQoLY3JlZGVudGlhbHMYAyABKAsyHy5tZ210LnYxYWxwaGExLkF3c1MzQ3JlZGVudGlhbHNIAYgBARITCgZyZWdpb24YBCABKAlIAogBARIVCghlbmRwb2ludBgFIAEoCUgDiAEBEhcKBmJ1Y2tldBgGIAEoCUIHukgEcgIQAUIOCgxfcGF0aF9wcmVmaXhCDgoMX2NyZWRlbnRpYWxzQgkKB19yZWdpb25CCwoJX2VuZHBvaW50SgQIARACIswCChBBd3NTM0NyZWRlbnRpYWxzEhQKB3Byb2ZpbGUYASABKAlIAIgBARIaCg1hY2Nlc3Nfa2V5X2lkGAIgASgJSAGIAQESHgoRc2VjcmV0X2FjY2Vzc19rZXkYAyABKAlIAogBARIaCg1zZXNzaW9uX3Rva2VuGAQgASgJSAOIAQESGgoNZnJvbV9lYzJfcm9sZRgFIAEoCEgEiAEBEhUKCHJvbGVfYXJuGAYgASgJSAWIAQESHQoQcm9sZV9leHRlcm5hbF9pZBgHIAEoCUgGiAEBQgoKCF9wcm9maWxlQhAKDl9hY2Nlc3Nfa2V5X2lkQhQKEl9zZWNyZXRfYWNjZXNzX2tleUIQCg5fc2Vzc2lvbl90b2tlbkIQCg5fZnJvbV9lYzJfcm9sZUILCglfcm9sZV9hcm5CEwoRX3JvbGVfZXh0ZXJuYWxfaWQirgEKH0djcENsb3VkU3RvcmFnZUNvbm5lY3Rpb25Db25maWcSFwoGYnVja2V0GAEgASgJQge6SARyAhABEhgKC3BhdGhfcHJlZml4GAIgASgJSACIAQESKAobc2VydmljZV9hY2NvdW50X2NyZWRlbnRpYWxzGAMgASgJSAGIAQFCDgoMX3BhdGhfcHJlZml4Qh4KHF9zZXJ2aWNlX2FjY291bnRfY3JlZGVudGlhbHMidAogSXNDb25uZWN0aW9uTmFtZUF2YWlsYWJsZVJlcXVlc3QSHAoKYWNjb3VudF9pZBgBIAEoCUIIukgFcgOwAQESMgoPY29ubmVjdGlvbl9uYW1lGAIgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kIjkKIUlzQ29ubmVjdGlvbk5hbWVBdmFpbGFibGVSZXNwb25zZRIUCgxpc19hdmFpbGFibGUYASABKAgiRAoUQ2hlY2tTcWxRdWVyeVJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEhYKBXF1ZXJ5GAIgASgJQge6SARyAhABIlcKFUNoZWNrU3FsUXVlcnlSZXNwb25zZRIQCghpc192YWxpZBgBIAEoCBIaCg1lcm9ycl9tZXNzYWdlGAIgASgJSACIAQFCEAoOX2Vyb3JyX21lc3NhZ2Uy5wcKEUNvbm5lY3Rpb25TZXJ2aWNlEmIKDkdldENvbm5lY3Rpb25zEiQubWdtdC52MWFscGhhMS5HZXRDb25uZWN0aW9uc1JlcXVlc3QaJS5tZ210LnYxYWxwaGExLkdldENvbm5lY3Rpb25zUmVzcG9uc2UiA5ACARJfCg1HZXRDb25uZWN0aW9uEiMubWdtdC52MWFscGhhMS5HZXRDb25uZWN0aW9uUmVxdWVzdBokLm1nbXQudjFhbHBoYTEuR2V0Q29ubmVjdGlvblJlc3BvbnNlIgOQAgESZQoQQ3JlYXRlQ29ubmVjdGlvbhImLm1nbXQudjFhbHBoYTEuQ3JlYXRlQ29ubmVjdGlvblJlcXVlc3QaJy5tZ210LnYxYWxwaGExLkNyZWF0ZUNvbm5lY3Rpb25SZXNwb25zZSIAEmUKEFVwZGF0ZUNvbm5lY3Rpb24SJi5tZ210LnYxYWxwaGExLlVwZGF0ZUNvbm5lY3Rpb25SZXF1ZXN0GicubWdtdC52MWFscGhhMS5VcGRhdGVDb25uZWN0aW9uUmVzcG9uc2UiABJlChBEZWxldGVDb25uZWN0aW9uEiYubWdtdC52MWFscGhhMS5EZWxldGVDb25uZWN0aW9uUmVxdWVzdBonLm1nbXQudjFhbHBoYTEuRGVsZXRlQ29ubmVjdGlvblJlc3BvbnNlIgASgAEKGUlzQ29ubmVjdGlvbk5hbWVBdmFpbGFibGUSLy5tZ210LnYxYWxwaGExLklzQ29ubmVjdGlvbk5hbWVBdmFpbGFibGVSZXF1ZXN0GjAubWdtdC52MWFscGhhMS5Jc0Nvbm5lY3Rpb25OYW1lQXZhaWxhYmxlUmVzcG9uc2UiABJ0ChVDaGVja0Nvbm5lY3Rpb25Db25maWcSKy5tZ210LnYxYWxwaGExLkNoZWNrQ29ubmVjdGlvbkNvbmZpZ1JlcXVlc3QaLC5tZ210LnYxYWxwaGExLkNoZWNrQ29ubmVjdGlvbkNvbmZpZ1Jlc3BvbnNlIgASgAEKGUNoZWNrQ29ubmVjdGlvbkNvbmZpZ0J5SWQSLy5tZ210LnYxYWxwaGExLkNoZWNrQ29ubmVjdGlvbkNvbmZpZ0J5SWRSZXF1ZXN0GjAubWdtdC52MWFscGhhMS5DaGVja0Nvbm5lY3Rpb25Db25maWdCeUlkUmVzcG9uc2UiABJcCg1DaGVja1NxbFF1ZXJ5EiMubWdtdC52MWFscGhhMS5DaGVja1NxbFF1ZXJ5UmVxdWVzdBokLm1nbXQudjFhbHBoYTEuQ2hlY2tTcWxRdWVyeVJlc3BvbnNlIgBCywEKEWNvbS5tZ210LnYxYWxwaGExQg9Db25uZWN0aW9uUHJvdG9QAVpQZ2l0aHViLmNvbS9udWNsZXVzY2xvdWQvbmVvc3luYy9iYWNrZW5kL2dlbi9nby9wcm90b3MvbWdtdC92MWFscGhhMTttZ210djFhbHBoYTGiAgNNWFiqAg1NZ210LlYxYWxwaGExygINTWdtdFxWMWFscGhhMeICGU1nbXRcVjFhbHBoYTFcR1BCTWV0YWRhdGHqAg5NZ210OjpWMWFscGhhMWIGcHJvdG8z", [file_buf_validate_validate, file_google_protobuf_timestamp]); + fileDesc("Ch5tZ210L3YxYWxwaGExL2Nvbm5lY3Rpb24ucHJvdG8SDW1nbXQudjFhbHBoYTEiUAoVR2V0Q29ubmVjdGlvbnNSZXF1ZXN0EhwKCmFjY291bnRfaWQYASABKAlCCLpIBXIDsAEBEhkKEWV4Y2x1ZGVfc2Vuc2l0aXZlGAIgASgIIkgKFkdldENvbm5lY3Rpb25zUmVzcG9uc2USLgoLY29ubmVjdGlvbnMYASADKAsyGS5tZ210LnYxYWxwaGExLkNvbm5lY3Rpb24iRwoUR2V0Q29ubmVjdGlvblJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEhkKEWV4Y2x1ZGVfc2Vuc2l0aXZlGAIgASgIIkYKFUdldENvbm5lY3Rpb25SZXNwb25zZRItCgpjb25uZWN0aW9uGAEgASgLMhkubWdtdC52MWFscGhhMS5Db25uZWN0aW9uIpwBChdDcmVhdGVDb25uZWN0aW9uUmVxdWVzdBIcCgphY2NvdW50X2lkGAEgASgJQgi6SAVyA7ABARInCgRuYW1lGAIgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kEjoKEWNvbm5lY3Rpb25fY29uZmlnGAMgASgLMh8ubWdtdC52MWFscGhhMS5Db25uZWN0aW9uQ29uZmlnIkkKGENyZWF0ZUNvbm5lY3Rpb25SZXNwb25zZRItCgpjb25uZWN0aW9uGAEgASgLMhkubWdtdC52MWFscGhhMS5Db25uZWN0aW9uIpQBChdVcGRhdGVDb25uZWN0aW9uUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQESJwoEbmFtZRgCIAEoCUIZukgWchQyEl5bYS16MC05LV17MywxMDB9JBI6ChFjb25uZWN0aW9uX2NvbmZpZxgDIAEoCzIfLm1nbXQudjFhbHBoYTEuQ29ubmVjdGlvbkNvbmZpZyJJChhVcGRhdGVDb25uZWN0aW9uUmVzcG9uc2USLQoKY29ubmVjdGlvbhgBIAEoCzIZLm1nbXQudjFhbHBoYTEuQ29ubmVjdGlvbiIvChdEZWxldGVDb25uZWN0aW9uUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiGgoYRGVsZXRlQ29ubmVjdGlvblJlc3BvbnNlIloKHENoZWNrQ29ubmVjdGlvbkNvbmZpZ1JlcXVlc3QSOgoRY29ubmVjdGlvbl9jb25maWcYASABKAsyHy5tZ210LnYxYWxwaGExLkNvbm5lY3Rpb25Db25maWciOAogQ2hlY2tDb25uZWN0aW9uQ29uZmlnQnlJZFJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBIqkBCiFDaGVja0Nvbm5lY3Rpb25Db25maWdCeUlkUmVzcG9uc2USFAoMaXNfY29ubmVjdGVkGAEgASgIEh0KEGNvbm5lY3Rpb25fZXJyb3IYAiABKAlIAIgBARI6Cgpwcml2aWxlZ2VzGAMgAygLMiYubWdtdC52MWFscGhhMS5Db25uZWN0aW9uUm9sZVByaXZpbGVnZUITChFfY29ubmVjdGlvbl9lcnJvciKlAQodQ2hlY2tDb25uZWN0aW9uQ29uZmlnUmVzcG9uc2USFAoMaXNfY29ubmVjdGVkGAEgASgIEh0KEGNvbm5lY3Rpb25fZXJyb3IYAiABKAlIAIgBARI6Cgpwcml2aWxlZ2VzGAMgAygLMiYubWdtdC52MWFscGhhMS5Db25uZWN0aW9uUm9sZVByaXZpbGVnZUITChFfY29ubmVjdGlvbl9lcnJvciJhChdDb25uZWN0aW9uUm9sZVByaXZpbGVnZRIPCgdncmFudGVlGAEgASgJEg4KBnNjaGVtYRgCIAEoCRINCgV0YWJsZRgDIAEoCRIWCg5wcml2aWxlZ2VfdHlwZRgEIAMoCSKOAgoKQ29ubmVjdGlvbhIKCgJpZBgBIAEoCRIMCgRuYW1lGAIgASgJEjoKEWNvbm5lY3Rpb25fY29uZmlnGAMgASgLMh8ubWdtdC52MWFscGhhMS5Db25uZWN0aW9uQ29uZmlnEhoKEmNyZWF0ZWRfYnlfdXNlcl9pZBgEIAEoCRIuCgpjcmVhdGVkX2F0GAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIaChJ1cGRhdGVkX2J5X3VzZXJfaWQYBiABKAkSLgoKdXBkYXRlZF9hdBgHIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASEgoKYWNjb3VudF9pZBgIIAEoCSL8BAoQQ29ubmVjdGlvbkNvbmZpZxI8CglwZ19jb25maWcYASABKAsyJy5tZ210LnYxYWxwaGExLlBvc3RncmVzQ29ubmVjdGlvbkNvbmZpZ0gAEj0KDWF3c19zM19jb25maWcYAiABKAsyJC5tZ210LnYxYWxwaGExLkF3c1MzQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG15c3FsX2NvbmZpZxgDIAEoCzIkLm1nbXQudjFhbHBoYTEuTXlzcWxDb25uZWN0aW9uQ29uZmlnSAASSQoQbG9jYWxfZGlyX2NvbmZpZxgEIAEoCzItLm1nbXQudjFhbHBoYTEuTG9jYWxEaXJlY3RvcnlDb25uZWN0aW9uQ29uZmlnSAASPgoNb3BlbmFpX2NvbmZpZxgFIAEoCzIlLm1nbXQudjFhbHBoYTEuT3BlbkFpQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG1vbmdvX2NvbmZpZxgGIAEoCzIkLm1nbXQudjFhbHBoYTEuTW9uZ29Db25uZWN0aW9uQ29uZmlnSAASUQoXZ2NwX2Nsb3Vkc3RvcmFnZV9jb25maWcYByABKAsyLi5tZ210LnYxYWxwaGExLkdjcENsb3VkU3RvcmFnZUNvbm5lY3Rpb25Db25maWdIABJCCg9keW5hbW9kYl9jb25maWcYCCABKAsyJy5tZ210LnYxYWxwaGExLkR5bmFtb0RCQ29ubmVjdGlvbkNvbmZpZ0gAEjwKDG1zc3FsX2NvbmZpZxgJIAEoCzIkLm1nbXQudjFhbHBoYTEuTXNzcWxDb25uZWN0aW9uQ29uZmlnSABCDwoGY29uZmlnEgW6SAIIASL5AQoVTXNzcWxDb25uZWN0aW9uQ29uZmlnEg0KA3VybBgBIAEoCUgAEhYKDHVybF9mcm9tX2VudhgFIAEoCUgAEj8KEmNvbm5lY3Rpb25fb3B0aW9ucxgCIAEoCzIjLm1nbXQudjFhbHBoYTEuU3FsQ29ubmVjdGlvbk9wdGlvbnMSKAoGdHVubmVsGAMgASgLMhgubWdtdC52MWFscGhhMS5TU0hUdW5uZWwSMgoKY2xpZW50X3RscxgEIAEoCzIeLm1nbXQudjFhbHBoYTEuQ2xpZW50VGxzQ29uZmlnQhoKEWNvbm5lY3Rpb25fY29uZmlnEgW6SAIIASKpAQoYRHluYW1vREJDb25uZWN0aW9uQ29uZmlnEjkKC2NyZWRlbnRpYWxzGAEgASgLMh8ubWdtdC52MWFscGhhMS5Bd3NTM0NyZWRlbnRpYWxzSACIAQESEwoGcmVnaW9uGAIgASgJSAGIAQESFQoIZW5kcG9pbnQYAyABKAlIAogBAUIOCgxfY3JlZGVudGlhbHNCCQoHX3JlZ2lvbkILCglfZW5kcG9pbnQioAEKFU1vbmdvQ29ubmVjdGlvbkNvbmZpZxINCgN1cmwYASABKAlIABIoCgZ0dW5uZWwYAiABKAsyGC5tZ210LnYxYWxwaGExLlNTSFR1bm5lbBIyCgpjbGllbnRfdGxzGAMgASgLMh4ubWdtdC52MWFscGhhMS5DbGllbnRUbHNDb25maWdCGgoRY29ubmVjdGlvbl9jb25maWcSBbpIAggBIjoKFk9wZW5BaUNvbm5lY3Rpb25Db25maWcSDwoHYXBpX2tleRgBIAEoCRIPCgdhcGlfdXJsGAIgASgJIjcKHkxvY2FsRGlyZWN0b3J5Q29ubmVjdGlvbkNvbmZpZxIVCgRwYXRoGAEgASgJQge6SARyAhABIrUCChhQb3N0Z3Jlc0Nvbm5lY3Rpb25Db25maWcSDQoDdXJsGAEgASgJSAASNwoKY29ubmVjdGlvbhgCIAEoCzIhLm1nbXQudjFhbHBoYTEuUG9zdGdyZXNDb25uZWN0aW9uSAASFgoMdXJsX2Zyb21fZW52GAYgASgJSAASKAoGdHVubmVsGAMgASgLMhgubWdtdC52MWFscGhhMS5TU0hUdW5uZWwSPwoSY29ubmVjdGlvbl9vcHRpb25zGAQgASgLMiMubWdtdC52MWFscGhhMS5TcWxDb25uZWN0aW9uT3B0aW9ucxIyCgpjbGllbnRfdGxzGAUgASgLMh4ubWdtdC52MWFscGhhMS5DbGllbnRUbHNDb25maWdCGgoRY29ubmVjdGlvbl9jb25maWcSBbpIAggBIrMBCg9DbGllbnRUbHNDb25maWcSFgoJcm9vdF9jZXJ0GAEgASgJSACIAQESGAoLY2xpZW50X2NlcnQYAiABKAlIAYgBARIXCgpjbGllbnRfa2V5GAMgASgJSAKIAQESGAoLc2VydmVyX25hbWUYBCABKAlIA4gBAUIMCgpfcm9vdF9jZXJ0Qg4KDF9jbGllbnRfY2VydEINCgtfY2xpZW50X2tleUIOCgxfc2VydmVyX25hbWUi+gEKFFNxbENvbm5lY3Rpb25PcHRpb25zEiEKFG1heF9jb25uZWN0aW9uX2xpbWl0GAEgASgFSACIAQESIQoUbWF4X2lkbGVfY29ubmVjdGlvbnMYAiABKAVIAYgBARIeChFtYXhfaWRsZV9kdXJhdGlvbhgDIAEoCUgCiAEBEh4KEW1heF9vcGVuX2R1cmF0aW9uGAQgASgJSAOIAQFCFwoVX21heF9jb25uZWN0aW9uX2xpbWl0QhcKFV9tYXhfaWRsZV9jb25uZWN0aW9uc0IUChJfbWF4X2lkbGVfZHVyYXRpb25CFAoSX21heF9vcGVuX2R1cmF0aW9uItEBCglTU0hUdW5uZWwSFQoEaG9zdBgBIAEoCUIHukgEcgIQARIVCgRwb3J0GAIgASgFQge6SAQaAigAEhUKBHVzZXIYAyABKAlCB7pIBHICEAESKwoVa25vd25faG9zdF9wdWJsaWNfa2V5GAQgASgJQge6SARyAhABSACIAQESOAoOYXV0aGVudGljYXRpb24YBSABKAsyIC5tZ210LnYxYWxwaGExLlNTSEF1dGhlbnRpY2F0aW9uQhgKFl9rbm93bl9ob3N0X3B1YmxpY19rZXkikgEKEVNTSEF1dGhlbnRpY2F0aW9uEjIKCnBhc3NwaHJhc2UYASABKAsyHC5tZ210LnYxYWxwaGExLlNTSFBhc3NwaHJhc2VIABIzCgtwcml2YXRlX2tleRgCIAEoCzIcLm1nbXQudjFhbHBoYTEuU1NIUHJpdmF0ZUtleUgAQhQKC2F1dGhfY29uZmlnEgW6SAIIASInCg1TU0hQYXNzcGhyYXNlEhYKBXZhbHVlGAEgASgJQge6SARyAhABIk8KDVNTSFByaXZhdGVLZXkSFgoFdmFsdWUYASABKAlCB7pIBHICEAESFwoKcGFzc3BocmFzZRgCIAEoCUgAiAEBQg0KC19wYXNzcGhyYXNlIn4KElBvc3RncmVzQ29ubmVjdGlvbhIMCgRob3N0GAEgASgJEgwKBHBvcnQYAiABKAUSDAoEbmFtZRgDIAEoCRIMCgR1c2VyGAQgASgJEgwKBHBhc3MYBSABKAkSFQoIc3NsX21vZGUYBiABKAlIAIgBAUILCglfc3NsX21vZGUiaQoPTXlzcWxDb25uZWN0aW9uEgwKBHVzZXIYASABKAkSDAoEcGFzcxgCIAEoCRIQCghwcm90b2NvbBgDIAEoCRIMCgRob3N0GAQgASgJEgwKBHBvcnQYBSABKAUSDAoEbmFtZRgGIAEoCSKvAgoVTXlzcWxDb25uZWN0aW9uQ29uZmlnEg0KA3VybBgBIAEoCUgAEjQKCmNvbm5lY3Rpb24YAiABKAsyHi5tZ210LnYxYWxwaGExLk15c3FsQ29ubmVjdGlvbkgAEhYKDHVybF9mcm9tX2VudhgGIAEoCUgAEigKBnR1bm5lbBgDIAEoCzIYLm1nbXQudjFhbHBoYTEuU1NIVHVubmVsEj8KEmNvbm5lY3Rpb25fb3B0aW9ucxgEIAEoCzIjLm1nbXQudjFhbHBoYTEuU3FsQ29ubmVjdGlvbk9wdGlvbnMSMgoKY2xpZW50X3RscxgFIAEoCzIeLm1nbXQudjFhbHBoYTEuQ2xpZW50VGxzQ29uZmlnQhoKEWNvbm5lY3Rpb25fY29uZmlnEgW6SAIIASLvAQoVQXdzUzNDb25uZWN0aW9uQ29uZmlnEhgKC3BhdGhfcHJlZml4GAIgASgJSACIAQESOQoLY3JlZGVudGlhbHMYAyABKAsyHy5tZ210LnYxYWxwaGExLkF3c1MzQ3JlZGVudGlhbHNIAYgBARITCgZyZWdpb24YBCABKAlIAogBARIVCghlbmRwb2ludBgFIAEoCUgDiAEBEhcKBmJ1Y2tldBgGIAEoCUIHukgEcgIQAUIOCgxfcGF0aF9wcmVmaXhCDgoMX2NyZWRlbnRpYWxzQgkKB19yZWdpb25CCwoJX2VuZHBvaW50SgQIARACIswCChBBd3NTM0NyZWRlbnRpYWxzEhQKB3Byb2ZpbGUYASABKAlIAIgBARIaCg1hY2Nlc3Nfa2V5X2lkGAIgASgJSAGIAQESHgoRc2VjcmV0X2FjY2Vzc19rZXkYAyABKAlIAogBARIaCg1zZXNzaW9uX3Rva2VuGAQgASgJSAOIAQESGgoNZnJvbV9lYzJfcm9sZRgFIAEoCEgEiAEBEhUKCHJvbGVfYXJuGAYgASgJSAWIAQESHQoQcm9sZV9leHRlcm5hbF9pZBgHIAEoCUgGiAEBQgoKCF9wcm9maWxlQhAKDl9hY2Nlc3Nfa2V5X2lkQhQKEl9zZWNyZXRfYWNjZXNzX2tleUIQCg5fc2Vzc2lvbl90b2tlbkIQCg5fZnJvbV9lYzJfcm9sZUILCglfcm9sZV9hcm5CEwoRX3JvbGVfZXh0ZXJuYWxfaWQirgEKH0djcENsb3VkU3RvcmFnZUNvbm5lY3Rpb25Db25maWcSFwoGYnVja2V0GAEgASgJQge6SARyAhABEhgKC3BhdGhfcHJlZml4GAIgASgJSACIAQESKAobc2VydmljZV9hY2NvdW50X2NyZWRlbnRpYWxzGAMgASgJSAGIAQFCDgoMX3BhdGhfcHJlZml4Qh4KHF9zZXJ2aWNlX2FjY291bnRfY3JlZGVudGlhbHMidAogSXNDb25uZWN0aW9uTmFtZUF2YWlsYWJsZVJlcXVlc3QSHAoKYWNjb3VudF9pZBgBIAEoCUIIukgFcgOwAQESMgoPY29ubmVjdGlvbl9uYW1lGAIgASgJQhm6SBZyFDISXlthLXowLTktXXszLDEwMH0kIjkKIUlzQ29ubmVjdGlvbk5hbWVBdmFpbGFibGVSZXNwb25zZRIUCgxpc19hdmFpbGFibGUYASABKAgiRAoUQ2hlY2tTcWxRdWVyeVJlcXVlc3QSFAoCaWQYASABKAlCCLpIBXIDsAEBEhYKBXF1ZXJ5GAIgASgJQge6SARyAhABIlcKFUNoZWNrU3FsUXVlcnlSZXNwb25zZRIQCghpc192YWxpZBgBIAEoCBIaCg1lcm9ycl9tZXNzYWdlGAIgASgJSACIAQFCEAoOX2Vyb3JyX21lc3NhZ2UiRQoZQ2hlY2tTU0hDb25uZWN0aW9uUmVxdWVzdBIoCgZ0dW5uZWwYASABKAsyGC5tZ210LnYxYWxwaGExLlNTSFR1bm5lbCJVChpDaGVja1NTSENvbm5lY3Rpb25SZXNwb25zZRI3CgZyZXN1bHQYASABKAsyJy5tZ210LnYxYWxwaGExLkNoZWNrU1NIQ29ubmVjdGlvblJlc3VsdCI1Ch1DaGVja1NTSENvbm5lY3Rpb25CeUlkUmVxdWVzdBIUCgJpZBgBIAEoCUIIukgFcgOwAQEiWQoeQ2hlY2tTU0hDb25uZWN0aW9uQnlJZFJlc3BvbnNlEjcKBnJlc3VsdBgBIAEoCzInLm1nbXQudjFhbHBoYTEuQ2hlY2tTU0hDb25uZWN0aW9uUmVzdWx0Il8KGENoZWNrU1NIQ29ubmVjdGlvblJlc3VsdBIVCg1pc19zdWNjZXNzZnVsGAEgASgIEhoKDWVycm9yX21lc3NhZ2UYAiABKAlIAIgBAUIQCg5fZXJyb3JfbWVzc2FnZTLNCQoRQ29ubmVjdGlvblNlcnZpY2USYgoOR2V0Q29ubmVjdGlvbnMSJC5tZ210LnYxYWxwaGExLkdldENvbm5lY3Rpb25zUmVxdWVzdBolLm1nbXQudjFhbHBoYTEuR2V0Q29ubmVjdGlvbnNSZXNwb25zZSIDkAIBEl8KDUdldENvbm5lY3Rpb24SIy5tZ210LnYxYWxwaGExLkdldENvbm5lY3Rpb25SZXF1ZXN0GiQubWdtdC52MWFscGhhMS5HZXRDb25uZWN0aW9uUmVzcG9uc2UiA5ACARJlChBDcmVhdGVDb25uZWN0aW9uEiYubWdtdC52MWFscGhhMS5DcmVhdGVDb25uZWN0aW9uUmVxdWVzdBonLm1nbXQudjFhbHBoYTEuQ3JlYXRlQ29ubmVjdGlvblJlc3BvbnNlIgASZQoQVXBkYXRlQ29ubmVjdGlvbhImLm1nbXQudjFhbHBoYTEuVXBkYXRlQ29ubmVjdGlvblJlcXVlc3QaJy5tZ210LnYxYWxwaGExLlVwZGF0ZUNvbm5lY3Rpb25SZXNwb25zZSIAEmUKEERlbGV0ZUNvbm5lY3Rpb24SJi5tZ210LnYxYWxwaGExLkRlbGV0ZUNvbm5lY3Rpb25SZXF1ZXN0GicubWdtdC52MWFscGhhMS5EZWxldGVDb25uZWN0aW9uUmVzcG9uc2UiABKAAQoZSXNDb25uZWN0aW9uTmFtZUF2YWlsYWJsZRIvLm1nbXQudjFhbHBoYTEuSXNDb25uZWN0aW9uTmFtZUF2YWlsYWJsZVJlcXVlc3QaMC5tZ210LnYxYWxwaGExLklzQ29ubmVjdGlvbk5hbWVBdmFpbGFibGVSZXNwb25zZSIAEnQKFUNoZWNrQ29ubmVjdGlvbkNvbmZpZxIrLm1nbXQudjFhbHBoYTEuQ2hlY2tDb25uZWN0aW9uQ29uZmlnUmVxdWVzdBosLm1nbXQudjFhbHBoYTEuQ2hlY2tDb25uZWN0aW9uQ29uZmlnUmVzcG9uc2UiABKAAQoZQ2hlY2tDb25uZWN0aW9uQ29uZmlnQnlJZBIvLm1nbXQudjFhbHBoYTEuQ2hlY2tDb25uZWN0aW9uQ29uZmlnQnlJZFJlcXVlc3QaMC5tZ210LnYxYWxwaGExLkNoZWNrQ29ubmVjdGlvbkNvbmZpZ0J5SWRSZXNwb25zZSIAElwKDUNoZWNrU3FsUXVlcnkSIy5tZ210LnYxYWxwaGExLkNoZWNrU3FsUXVlcnlSZXF1ZXN0GiQubWdtdC52MWFscGhhMS5DaGVja1NxbFF1ZXJ5UmVzcG9uc2UiABJrChJDaGVja1NTSENvbm5lY3Rpb24SKC5tZ210LnYxYWxwaGExLkNoZWNrU1NIQ29ubmVjdGlvblJlcXVlc3QaKS5tZ210LnYxYWxwaGExLkNoZWNrU1NIQ29ubmVjdGlvblJlc3BvbnNlIgASdwoWQ2hlY2tTU0hDb25uZWN0aW9uQnlJZBIsLm1nbXQudjFhbHBoYTEuQ2hlY2tTU0hDb25uZWN0aW9uQnlJZFJlcXVlc3QaLS5tZ210LnYxYWxwaGExLkNoZWNrU1NIQ29ubmVjdGlvbkJ5SWRSZXNwb25zZSIAQssBChFjb20ubWdtdC52MWFscGhhMUIPQ29ubmVjdGlvblByb3RvUAFaUGdpdGh1Yi5jb20vbnVjbGV1c2Nsb3VkL25lb3N5bmMvYmFja2VuZC9nZW4vZ28vcHJvdG9zL21nbXQvdjFhbHBoYTE7bWdtdHYxYWxwaGExogIDTVhYqgINTWdtdC5WMWFscGhhMcoCDU1nbXRcVjFhbHBoYTHiAhlNZ210XFYxYWxwaGExXEdQQk1ldGFkYXRh6gIOTWdtdDo6VjFhbHBoYTFiBnByb3RvMw", [file_buf_validate_validate, file_google_protobuf_timestamp]); /** * @generated from message mgmt.v1alpha1.GetConnectionsRequest @@ -1443,6 +1443,108 @@ export type CheckSqlQueryResponse = Message<"mgmt.v1alpha1.CheckSqlQueryResponse export const CheckSqlQueryResponseSchema: GenMessage = /*@__PURE__*/ messageDesc(file_mgmt_v1alpha1_connection, 38); +/** + * @generated from message mgmt.v1alpha1.CheckSSHConnectionRequest + */ +export type CheckSSHConnectionRequest = Message<"mgmt.v1alpha1.CheckSSHConnectionRequest"> & { + /** + * The SSH tunnel configuration to use for the connection + * + * @generated from field: mgmt.v1alpha1.SSHTunnel tunnel = 1; + */ + tunnel?: SSHTunnel; +}; + +/** + * Describes the message mgmt.v1alpha1.CheckSSHConnectionRequest. + * Use `create(CheckSSHConnectionRequestSchema)` to create a new message. + */ +export const CheckSSHConnectionRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mgmt_v1alpha1_connection, 39); + +/** + * @generated from message mgmt.v1alpha1.CheckSSHConnectionResponse + */ +export type CheckSSHConnectionResponse = Message<"mgmt.v1alpha1.CheckSSHConnectionResponse"> & { + /** + * The result of the SSH connection check + * + * @generated from field: mgmt.v1alpha1.CheckSSHConnectionResult result = 1; + */ + result?: CheckSSHConnectionResult; +}; + +/** + * Describes the message mgmt.v1alpha1.CheckSSHConnectionResponse. + * Use `create(CheckSSHConnectionResponseSchema)` to create a new message. + */ +export const CheckSSHConnectionResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mgmt_v1alpha1_connection, 40); + +/** + * @generated from message mgmt.v1alpha1.CheckSSHConnectionByIdRequest + */ +export type CheckSSHConnectionByIdRequest = Message<"mgmt.v1alpha1.CheckSSHConnectionByIdRequest"> & { + /** + * The connection id that the SSH connection will be checked against + * + * @generated from field: string id = 1; + */ + id: string; +}; + +/** + * Describes the message mgmt.v1alpha1.CheckSSHConnectionByIdRequest. + * Use `create(CheckSSHConnectionByIdRequestSchema)` to create a new message. + */ +export const CheckSSHConnectionByIdRequestSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mgmt_v1alpha1_connection, 41); + +/** + * @generated from message mgmt.v1alpha1.CheckSSHConnectionByIdResponse + */ +export type CheckSSHConnectionByIdResponse = Message<"mgmt.v1alpha1.CheckSSHConnectionByIdResponse"> & { + /** + * The result of the SSH connection check + * + * @generated from field: mgmt.v1alpha1.CheckSSHConnectionResult result = 1; + */ + result?: CheckSSHConnectionResult; +}; + +/** + * Describes the message mgmt.v1alpha1.CheckSSHConnectionByIdResponse. + * Use `create(CheckSSHConnectionByIdResponseSchema)` to create a new message. + */ +export const CheckSSHConnectionByIdResponseSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mgmt_v1alpha1_connection, 42); + +/** + * @generated from message mgmt.v1alpha1.CheckSSHConnectionResult + */ +export type CheckSSHConnectionResult = Message<"mgmt.v1alpha1.CheckSSHConnectionResult"> & { + /** + * Whether or not the SSH connection is successful + * + * @generated from field: bool is_successful = 1; + */ + isSuccessful: boolean; + + /** + * The error message returned by the SSH client if the connection is not successful + * + * @generated from field: optional string error_message = 2; + */ + errorMessage?: string; +}; + +/** + * Describes the message mgmt.v1alpha1.CheckSSHConnectionResult. + * Use `create(CheckSSHConnectionResultSchema)` to create a new message. + */ +export const CheckSSHConnectionResultSchema: GenMessage = /*@__PURE__*/ + messageDesc(file_mgmt_v1alpha1_connection, 43); + /** * Service for managing datasource connections. * This is a primary data model in Neosync and is used in reference when hooking up Jobs to synchronize and generate data. @@ -1543,6 +1645,26 @@ export const ConnectionService: GenService<{ input: typeof CheckSqlQueryRequestSchema; output: typeof CheckSqlQueryResponseSchema; }, + /** + * Checks if the SSH server is reachable and accessible with the given credentials + * + * @generated from rpc mgmt.v1alpha1.ConnectionService.CheckSSHConnection + */ + checkSSHConnection: { + methodKind: "unary"; + input: typeof CheckSSHConnectionRequestSchema; + output: typeof CheckSSHConnectionResponseSchema; + }, + /** + * Checks if the SSH server is reachable and accessible with the given credentials + * + * @generated from rpc mgmt.v1alpha1.ConnectionService.CheckSSHConnectionById + */ + checkSSHConnectionById: { + methodKind: "unary"; + input: typeof CheckSSHConnectionByIdRequestSchema; + output: typeof CheckSSHConnectionByIdResponseSchema; + }, }> = /*@__PURE__*/ serviceDesc(file_mgmt_v1alpha1_connection, 0); diff --git a/internal/sshtunnel/connectors/postgrestunconnector/connector.go b/internal/sshtunnel/connectors/postgrestunconnector/connector.go index 590d6e6f93..f990619b54 100644 --- a/internal/sshtunnel/connectors/postgrestunconnector/connector.go +++ b/internal/sshtunnel/connectors/postgrestunconnector/connector.go @@ -74,6 +74,20 @@ func New( pgxConfig.DialFunc = func(ctx context.Context, network, addr string) (net.Conn, error) { return cfg.dialer.DialContext(ctx, network, addr) } + + // This solves an issue with AWS Multi-AZ connections that seems to plague the PGX driver. + // Related: https://github.com/jackc/pgx/issues/1724 + pgxConfig.LookupFunc = func(ctx context.Context, name string) ([]string, error) { + addrs := []string{name} + resp, err := net.DefaultResolver.LookupHost(ctx, name) + if err != nil { + cfg.logger.Error("unable to lookup addrs for hostname during postgres tunnel dial", "name", name, "err", err) + } else { + addrs = append(addrs, resp...) + } + cfg.logger.Debug("looked up", "name", name, "addrs", addrs) + return addrs, nil + } } if cfg.tlsConfig != nil { pgxConfig.TLSConfig = cfg.tlsConfig diff --git a/internal/sshtunnel/dialer.go b/internal/sshtunnel/dialer.go index d2ea3dcd44..8a01c1c833 100644 --- a/internal/sshtunnel/dialer.go +++ b/internal/sshtunnel/dialer.go @@ -83,7 +83,8 @@ func (s *SSHDialer) DialContext(ctx context.Context, network, addr string) (net. if err != nil { return nil, fmt.Errorf("unable to get or create ssh client during DialContext: %w", err) } - conn, err := client.DialContext(ctx, network, addr) + s.logger.Debug("dialing", "network", network, "addr", addr) + conn, err := client.Dial(network, addr) if err != nil { return nil, fmt.Errorf("unable to dial address: %w", err) } @@ -207,6 +208,8 @@ func (s *SSHDialer) startKeepAlive(client *ssh.Client) { s.logger.Error("keepalive failed", "error", err) s.client = nil client.Close() + } else { + s.logger.Debug("keepalive successful") } case <-ctx.Done(): s.logger.Error("keepalive timed out") diff --git a/internal/sshtunnel/utils.go b/internal/sshtunnel/utils.go index 94ccca6583..6129157c58 100644 --- a/internal/sshtunnel/utils.go +++ b/internal/sshtunnel/utils.go @@ -1,13 +1,17 @@ package sshtunnel import ( + "errors" "fmt" + "net" + "strconv" + "time" mgmtv1alpha1 "github.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1" "golang.org/x/crypto/ssh" ) -func GetPrivateKeyAuthMethod(keyBytes []byte, passphrase *string) (ssh.AuthMethod, error) { +func getPrivateKeyAuthMethod(keyBytes []byte, passphrase *string) (ssh.AuthMethod, error) { if passphrase != nil && *passphrase != "" { return getEncryptedPrivateKeyAuthMethod(keyBytes, []byte(*passphrase)) } @@ -30,7 +34,7 @@ func getPlaintextPrivateKeyAuthMethod(keyBytes []byte) (ssh.AuthMethod, error) { return ssh.PublicKeys(key), nil } -func ParseSshKey(keyString string) (ssh.PublicKey, error) { +func parseSshKey(keyString string) (ssh.PublicKey, error) { // Parse the key publicKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(keyString)) //nolint if err != nil { @@ -42,7 +46,7 @@ func ParseSshKey(keyString string) (ssh.PublicKey, error) { // Auth Method is optional and will return nil if there is no valid method. // Will only return error if unable to parse the private key into an auth method -func GetTunnelAuthMethodFromSshConfig(auth *mgmtv1alpha1.SSHAuthentication) (ssh.AuthMethod, error) { +func getTunnelAuthMethodFromSshConfig(auth *mgmtv1alpha1.SSHAuthentication) (ssh.AuthMethod, error) { if auth == nil { return nil, nil } @@ -50,7 +54,7 @@ func GetTunnelAuthMethodFromSshConfig(auth *mgmtv1alpha1.SSHAuthentication) (ssh case *mgmtv1alpha1.SSHAuthentication_Passphrase: return ssh.Password(config.Passphrase.Value), nil case *mgmtv1alpha1.SSHAuthentication_PrivateKey: - authMethod, err := GetPrivateKeyAuthMethod([]byte(config.PrivateKey.Value), config.PrivateKey.Passphrase) + authMethod, err := getPrivateKeyAuthMethod([]byte(config.PrivateKey.Value), config.PrivateKey.Passphrase) if err != nil { return nil, err } @@ -59,3 +63,60 @@ func GetTunnelAuthMethodFromSshConfig(auth *mgmtv1alpha1.SSHAuthentication) (ssh return nil, nil } } + +type DtoTunnelConfig struct { + Addr string + ClientConfig *ssh.ClientConfig +} + +// Converts the proto SSHTunnel into a config that can be plugged in to ssh.Dial +func GetTunnelConfigFromSSHDto(tunnel *mgmtv1alpha1.SSHTunnel) (*DtoTunnelConfig, error) { + if tunnel == nil { + return nil, errors.New("tunnel config is nil") + } + + hostcallback, err := buildHostKeyCallback(tunnel) + if err != nil { + return nil, fmt.Errorf("unable to build host key callback: %w", err) + } + + authmethod, err := getTunnelAuthMethodFromSshConfig(tunnel.GetAuthentication()) + if err != nil { + return nil, fmt.Errorf("unable to parse ssh auth method: %w", err) + } + + authmethods := []ssh.AuthMethod{} + if authmethod != nil { + authmethods = append(authmethods, authmethod) + } + return &DtoTunnelConfig{ + Addr: getSshAddr(tunnel), + ClientConfig: &ssh.ClientConfig{ + User: tunnel.GetUser(), + Auth: authmethods, + HostKeyCallback: hostcallback, + Timeout: 15 * time.Second, // todo: make configurable + }, + }, nil +} + +func getSshAddr(tunnel *mgmtv1alpha1.SSHTunnel) string { + host := tunnel.GetHost() + port := tunnel.GetPort() + if port > 0 { + return net.JoinHostPort(host, strconv.FormatInt(int64(port), 10)) + } + return host +} + +func buildHostKeyCallback(tunnel *mgmtv1alpha1.SSHTunnel) (ssh.HostKeyCallback, error) { + if tunnel.GetKnownHostPublicKey() != "" { + publickey, err := parseSshKey(tunnel.GetKnownHostPublicKey()) + if err != nil { + return nil, fmt.Errorf("unable to parse ssh known host public key: %w", err) + } + return ssh.FixedHostKey(publickey), nil + } else { + return ssh.InsecureIgnoreHostKey(), nil //nolint:gosec // the user has chosen to not provide a known host public key + } +} diff --git a/internal/sshtunnel/utils_test.go b/internal/sshtunnel/utils_test.go index efae1ed135..68c8346612 100644 --- a/internal/sshtunnel/utils_test.go +++ b/internal/sshtunnel/utils_test.go @@ -28,24 +28,24 @@ UmTDjHp2ZBeXOtnQniimAAAAEHRlc3RAZXhhbXBsZS5jb20BAgMEBQ== unencryptedPublicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJVer1BVE7oIuxR6Z5uP/yBwUmTDjHp2ZBeXOtnQniim test@example.com" ) -func Test_GetPrivateKeyAuthMethod(t *testing.T) { - out, err := GetPrivateKeyAuthMethod([]byte(encryptedPrivateKey), ptr(encryptedPrivateKeyPass)) +func Test_getPrivateKeyAuthMethod(t *testing.T) { + out, err := getPrivateKeyAuthMethod([]byte(encryptedPrivateKey), ptr(encryptedPrivateKeyPass)) assert.NoError(t, err) assert.NotNil(t, out) - out, err = GetPrivateKeyAuthMethod([]byte(encryptedPrivateKey), ptr("badpassword")) + out, err = getPrivateKeyAuthMethod([]byte(encryptedPrivateKey), ptr("badpassword")) assert.Error(t, err) assert.Nil(t, out) - out, err = GetPrivateKeyAuthMethod([]byte("bad key"), ptr(encryptedPrivateKeyPass)) + out, err = getPrivateKeyAuthMethod([]byte("bad key"), ptr(encryptedPrivateKeyPass)) assert.Error(t, err) assert.Nil(t, out) - out, err = GetPrivateKeyAuthMethod([]byte(unencryptedPrivateKey), nil) + out, err = getPrivateKeyAuthMethod([]byte(unencryptedPrivateKey), nil) assert.NoError(t, err) assert.NotNil(t, out) - out, err = GetPrivateKeyAuthMethod([]byte("bad key"), nil) + out, err = getPrivateKeyAuthMethod([]byte("bad key"), nil) assert.Error(t, err) assert.Nil(t, out) } @@ -54,26 +54,26 @@ func ptr[T any](val T) *T { return &val } -func Test_ParseSshKey(t *testing.T) { - pk, err := ParseSshKey(unencryptedPublicKey) +func Test_parseSshKey(t *testing.T) { + pk, err := parseSshKey(unencryptedPublicKey) assert.NoError(t, err) assert.NotNil(t, pk) - pk, err = ParseSshKey("bad key") + pk, err = parseSshKey("bad key") assert.Error(t, err) assert.Nil(t, pk) } -func Test_GetTunnelAuthMethodFromSshConfig(t *testing.T) { - out, err := GetTunnelAuthMethodFromSshConfig(nil) +func Test_getTunnelAuthMethodFromSshConfig(t *testing.T) { + out, err := getTunnelAuthMethodFromSshConfig(nil) assert.NoError(t, err) assert.Nil(t, out) - out, err = GetTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{}) + out, err = getTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{}) assert.NoError(t, err) assert.Nil(t, out) - out, err = GetTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ + out, err = getTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ AuthConfig: &mgmtv1alpha1.SSHAuthentication_Passphrase{ Passphrase: &mgmtv1alpha1.SSHPassphrase{ Value: "foo", @@ -83,7 +83,7 @@ func Test_GetTunnelAuthMethodFromSshConfig(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, out) - out, err = GetTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ + out, err = getTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ AuthConfig: &mgmtv1alpha1.SSHAuthentication_PrivateKey{ PrivateKey: &mgmtv1alpha1.SSHPrivateKey{ Value: encryptedPrivateKey, @@ -94,7 +94,7 @@ func Test_GetTunnelAuthMethodFromSshConfig(t *testing.T) { assert.NoError(t, err) assert.NotNil(t, out) - out, err = GetTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ + out, err = getTunnelAuthMethodFromSshConfig(&mgmtv1alpha1.SSHAuthentication{ AuthConfig: &mgmtv1alpha1.SSHAuthentication_PrivateKey{ PrivateKey: &mgmtv1alpha1.SSHPrivateKey{ Value: encryptedPrivateKey, @@ -105,3 +105,19 @@ func Test_GetTunnelAuthMethodFromSshConfig(t *testing.T) { assert.Error(t, err) assert.Nil(t, out) } + +func Test_getSshAddr(t *testing.T) { + t.Run("with port", func(t *testing.T) { + actual := getSshAddr(&mgmtv1alpha1.SSHTunnel{ + Host: "localhost", + Port: 2222, + }) + assert.Equal(t, "localhost:2222", actual) + }) + t.Run("without port", func(t *testing.T) { + actual := getSshAddr(&mgmtv1alpha1.SSHTunnel{ + Host: "localhost", + }) + assert.Equal(t, "localhost", actual) + }) +} diff --git a/python/src/neosync/mgmt/v1alpha1/connection_pb2.py b/python/src/neosync/mgmt/v1alpha1/connection_pb2.py index 150556ff9e..c5057a0a53 100644 --- a/python/src/neosync/mgmt/v1alpha1/connection_pb2.py +++ b/python/src/neosync/mgmt/v1alpha1/connection_pb2.py @@ -26,7 +26,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__pb2 -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emgmt/v1alpha1/connection.proto\x12\rmgmt.v1alpha1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"m\n\x15GetConnectionsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12+\n\x11\x65xclude_sensitive\x18\x02 \x01(\x08R\x10\x65xcludeSensitive\"U\n\x16GetConnectionsResponse\x12;\n\x0b\x63onnections\x18\x01 \x03(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\x0b\x63onnections\"]\n\x14GetConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12+\n\x11\x65xclude_sensitive\x18\x02 \x01(\x08R\x10\x65xcludeSensitive\"R\n\x15GetConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"\xbf\x01\n\x17\x43reateConnectionRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"U\n\x18\x43reateConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"\xb0\x01\n\x17UpdateConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"U\n\x18UpdateConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"3\n\x17\x44\x65leteConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x1a\n\x18\x44\x65leteConnectionResponse\"l\n\x1c\x43heckConnectionConfigRequest\x12L\n\x11\x63onnection_config\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"<\n CheckConnectionConfigByIdRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\xd3\x01\n!CheckConnectionConfigByIdResponse\x12!\n\x0cis_connected\x18\x01 \x01(\x08R\x0bisConnected\x12.\n\x10\x63onnection_error\x18\x02 \x01(\tH\x00R\x0f\x63onnectionError\x88\x01\x01\x12\x46\n\nprivileges\x18\x03 \x03(\x0b\x32&.mgmt.v1alpha1.ConnectionRolePrivilegeR\nprivilegesB\x13\n\x11_connection_error\"\xcf\x01\n\x1d\x43heckConnectionConfigResponse\x12!\n\x0cis_connected\x18\x01 \x01(\x08R\x0bisConnected\x12.\n\x10\x63onnection_error\x18\x02 \x01(\tH\x00R\x0f\x63onnectionError\x88\x01\x01\x12\x46\n\nprivileges\x18\x03 \x03(\x0b\x32&.mgmt.v1alpha1.ConnectionRolePrivilegeR\nprivilegesB\x13\n\x11_connection_error\"\x88\x01\n\x17\x43onnectionRolePrivilege\x12\x18\n\x07grantee\x18\x01 \x01(\tR\x07grantee\x12\x16\n\x06schema\x18\x02 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x03 \x01(\tR\x05table\x12%\n\x0eprivilege_type\x18\x04 \x03(\tR\rprivilegeType\"\xed\x02\n\nConnection\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\x12+\n\x12\x63reated_by_user_id\x18\x04 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x06 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x1d\n\naccount_id\x18\x08 \x01(\tR\taccountId\"\xff\x05\n\x10\x43onnectionConfig\x12\x46\n\tpg_config\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.PostgresConnectionConfigH\x00R\x08pgConfig\x12J\n\raws_s3_config\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.AwsS3ConnectionConfigH\x00R\x0b\x61wsS3Config\x12I\n\x0cmysql_config\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MysqlConnectionConfigH\x00R\x0bmysqlConfig\x12Y\n\x10local_dir_config\x18\x04 \x01(\x0b\x32-.mgmt.v1alpha1.LocalDirectoryConnectionConfigH\x00R\x0elocalDirConfig\x12L\n\ropenai_config\x18\x05 \x01(\x0b\x32%.mgmt.v1alpha1.OpenAiConnectionConfigH\x00R\x0copenaiConfig\x12I\n\x0cmongo_config\x18\x06 \x01(\x0b\x32$.mgmt.v1alpha1.MongoConnectionConfigH\x00R\x0bmongoConfig\x12h\n\x17gcp_cloudstorage_config\x18\x07 \x01(\x0b\x32..mgmt.v1alpha1.GcpCloudStorageConnectionConfigH\x00R\x15gcpCloudstorageConfig\x12R\n\x0f\x64ynamodb_config\x18\x08 \x01(\x0b\x32\'.mgmt.v1alpha1.DynamoDBConnectionConfigH\x00R\x0e\x64ynamodbConfig\x12I\n\x0cmssql_config\x18\t \x01(\x0b\x32$.mgmt.v1alpha1.MssqlConnectionConfigH\x00R\x0bmssqlConfigB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"\xb0\x02\n\x15MssqlConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\"\n\x0curl_from_env\x18\x05 \x01(\tH\x00R\nurlFromEnv\x12R\n\x12\x63onnection_options\x18\x02 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12=\n\nclient_tls\x18\x04 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xc8\x01\n\x18\x44ynamoDBConnectionConfig\x12\x46\n\x0b\x63redentials\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.AwsS3CredentialsH\x00R\x0b\x63redentials\x88\x01\x01\x12\x1b\n\x06region\x18\x02 \x01(\tH\x01R\x06region\x88\x01\x01\x12\x1f\n\x08\x65ndpoint\x18\x03 \x01(\tH\x02R\x08\x65ndpoint\x88\x01\x01\x42\x0e\n\x0c_credentialsB\t\n\x07_regionB\x0b\n\t_endpoint\"\xb8\x01\n\x15MongoConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\x30\n\x06tunnel\x18\x02 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12=\n\nclient_tls\x18\x03 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"J\n\x16OpenAiConnectionConfig\x12\x17\n\x07\x61pi_key\x18\x01 \x01(\tR\x06\x61piKey\x12\x17\n\x07\x61pi_url\x18\x02 \x01(\tR\x06\x61piUrl\"=\n\x1eLocalDirectoryConnectionConfig\x12\x1b\n\x04path\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04path\"\xf8\x02\n\x18PostgresConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\x43\n\nconnection\x18\x02 \x01(\x0b\x32!.mgmt.v1alpha1.PostgresConnectionH\x00R\nconnection\x12\"\n\x0curl_from_env\x18\x06 \x01(\tH\x00R\nurlFromEnv\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12R\n\x12\x63onnection_options\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12=\n\nclient_tls\x18\x05 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xe0\x01\n\x0f\x43lientTlsConfig\x12 \n\troot_cert\x18\x01 \x01(\tH\x00R\x08rootCert\x88\x01\x01\x12$\n\x0b\x63lient_cert\x18\x02 \x01(\tH\x01R\nclientCert\x88\x01\x01\x12\"\n\nclient_key\x18\x03 \x01(\tH\x02R\tclientKey\x88\x01\x01\x12$\n\x0bserver_name\x18\x04 \x01(\tH\x03R\nserverName\x88\x01\x01\x42\x0c\n\n_root_certB\x0e\n\x0c_client_certB\r\n\x0b_client_keyB\x0e\n\x0c_server_name\"\xc4\x02\n\x14SqlConnectionOptions\x12\x35\n\x14max_connection_limit\x18\x01 \x01(\x05H\x00R\x12maxConnectionLimit\x88\x01\x01\x12\x35\n\x14max_idle_connections\x18\x02 \x01(\x05H\x01R\x12maxIdleConnections\x88\x01\x01\x12/\n\x11max_idle_duration\x18\x03 \x01(\tH\x02R\x0fmaxIdleDuration\x88\x01\x01\x12/\n\x11max_open_duration\x18\x04 \x01(\tH\x03R\x0fmaxOpenDuration\x88\x01\x01\x42\x17\n\x15_max_connection_limitB\x17\n\x15_max_idle_connectionsB\x14\n\x12_max_idle_durationB\x14\n\x12_max_open_duration\"\x87\x02\n\tSSHTunnel\x12\x1b\n\x04host\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04host\x12\x1b\n\x04port\x18\x02 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04port\x12\x1b\n\x04user\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04user\x12?\n\x15known_host_public_key\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x12knownHostPublicKey\x88\x01\x01\x12H\n\x0e\x61uthentication\x18\x05 \x01(\x0b\x32 .mgmt.v1alpha1.SSHAuthenticationR\x0e\x61uthenticationB\x18\n\x16_known_host_public_key\"\xaa\x01\n\x11SSHAuthentication\x12>\n\npassphrase\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.SSHPassphraseH\x00R\npassphrase\x12?\n\x0bprivate_key\x18\x02 \x01(\x0b\x32\x1c.mgmt.v1alpha1.SSHPrivateKeyH\x00R\nprivateKeyB\x14\n\x0b\x61uth_config\x12\x05\xbaH\x02\x08\x01\".\n\rSSHPassphrase\x12\x1d\n\x05value\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05value\"b\n\rSSHPrivateKey\x12\x1d\n\x05value\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05value\x12#\n\npassphrase\x18\x02 \x01(\tH\x00R\npassphrase\x88\x01\x01\x42\r\n\x0b_passphrase\"\xa5\x01\n\x12PostgresConnection\x12\x12\n\x04host\x18\x01 \x01(\tR\x04host\x12\x12\n\x04port\x18\x02 \x01(\x05R\x04port\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n\x04user\x18\x04 \x01(\tR\x04user\x12\x12\n\x04pass\x18\x05 \x01(\tR\x04pass\x12\x1e\n\x08ssl_mode\x18\x06 \x01(\tH\x00R\x07sslMode\x88\x01\x01\x42\x0b\n\t_ssl_mode\"\x91\x01\n\x0fMysqlConnection\x12\x12\n\x04user\x18\x01 \x01(\tR\x04user\x12\x12\n\x04pass\x18\x02 \x01(\tR\x04pass\x12\x1a\n\x08protocol\x18\x03 \x01(\tR\x08protocol\x12\x12\n\x04host\x18\x04 \x01(\tR\x04host\x12\x12\n\x04port\x18\x05 \x01(\x05R\x04port\x12\x12\n\x04name\x18\x06 \x01(\tR\x04name\"\xf2\x02\n\x15MysqlConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12@\n\nconnection\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.MysqlConnectionH\x00R\nconnection\x12\"\n\x0curl_from_env\x18\x06 \x01(\tH\x00R\nurlFromEnv\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12R\n\x12\x63onnection_options\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12=\n\nclient_tls\x18\x05 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xa2\x02\n\x15\x41wsS3ConnectionConfig\x12$\n\x0bpath_prefix\x18\x02 \x01(\tH\x00R\npathPrefix\x88\x01\x01\x12\x46\n\x0b\x63redentials\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.AwsS3CredentialsH\x01R\x0b\x63redentials\x88\x01\x01\x12\x1b\n\x06region\x18\x04 \x01(\tH\x02R\x06region\x88\x01\x01\x12\x1f\n\x08\x65ndpoint\x18\x05 \x01(\tH\x03R\x08\x65ndpoint\x88\x01\x01\x12\x1f\n\x06\x62ucket\x18\x06 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x62ucketB\x0e\n\x0c_path_prefixB\x0e\n\x0c_credentialsB\t\n\x07_regionB\x0b\n\t_endpointJ\x04\x08\x01\x10\x02\"\xa7\x03\n\x10\x41wsS3Credentials\x12\x1d\n\x07profile\x18\x01 \x01(\tH\x00R\x07profile\x88\x01\x01\x12\'\n\raccess_key_id\x18\x02 \x01(\tH\x01R\x0b\x61\x63\x63\x65ssKeyId\x88\x01\x01\x12/\n\x11secret_access_key\x18\x03 \x01(\tH\x02R\x0fsecretAccessKey\x88\x01\x01\x12(\n\rsession_token\x18\x04 \x01(\tH\x03R\x0csessionToken\x88\x01\x01\x12\'\n\rfrom_ec2_role\x18\x05 \x01(\x08H\x04R\x0b\x66romEc2Role\x88\x01\x01\x12\x1e\n\x08role_arn\x18\x06 \x01(\tH\x05R\x07roleArn\x88\x01\x01\x12-\n\x10role_external_id\x18\x07 \x01(\tH\x06R\x0eroleExternalId\x88\x01\x01\x42\n\n\x08_profileB\x10\n\x0e_access_key_idB\x14\n\x12_secret_access_keyB\x10\n\x0e_session_tokenB\x10\n\x0e_from_ec2_roleB\x0b\n\t_role_arnB\x13\n\x11_role_external_id\"\xdd\x01\n\x1fGcpCloudStorageConnectionConfig\x12\x1f\n\x06\x62ucket\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x62ucket\x12$\n\x0bpath_prefix\x18\x02 \x01(\tH\x00R\npathPrefix\x88\x01\x01\x12\x43\n\x1bservice_account_credentials\x18\x03 \x01(\tH\x01R\x19serviceAccountCredentials\x88\x01\x01\x42\x0e\n\x0c_path_prefixB\x1e\n\x1c_service_account_credentials\"\x8f\x01\n IsConnectionNameAvailableRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x42\n\x0f\x63onnection_name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x0e\x63onnectionName\"F\n!IsConnectionNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"O\n\x14\x43heckSqlQueryRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x1d\n\x05query\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05query\"n\n\x15\x43heckSqlQueryResponse\x12\x19\n\x08is_valid\x18\x01 \x01(\x08R\x07isValid\x12(\n\rerorr_message\x18\x02 \x01(\tH\x00R\x0c\x65rorrMessage\x88\x01\x01\x42\x10\n\x0e_erorr_message2\xe7\x07\n\x11\x43onnectionService\x12\x62\n\x0eGetConnections\x12$.mgmt.v1alpha1.GetConnectionsRequest\x1a%.mgmt.v1alpha1.GetConnectionsResponse\"\x03\x90\x02\x01\x12_\n\rGetConnection\x12#.mgmt.v1alpha1.GetConnectionRequest\x1a$.mgmt.v1alpha1.GetConnectionResponse\"\x03\x90\x02\x01\x12\x65\n\x10\x43reateConnection\x12&.mgmt.v1alpha1.CreateConnectionRequest\x1a\'.mgmt.v1alpha1.CreateConnectionResponse\"\x00\x12\x65\n\x10UpdateConnection\x12&.mgmt.v1alpha1.UpdateConnectionRequest\x1a\'.mgmt.v1alpha1.UpdateConnectionResponse\"\x00\x12\x65\n\x10\x44\x65leteConnection\x12&.mgmt.v1alpha1.DeleteConnectionRequest\x1a\'.mgmt.v1alpha1.DeleteConnectionResponse\"\x00\x12\x80\x01\n\x19IsConnectionNameAvailable\x12/.mgmt.v1alpha1.IsConnectionNameAvailableRequest\x1a\x30.mgmt.v1alpha1.IsConnectionNameAvailableResponse\"\x00\x12t\n\x15\x43heckConnectionConfig\x12+.mgmt.v1alpha1.CheckConnectionConfigRequest\x1a,.mgmt.v1alpha1.CheckConnectionConfigResponse\"\x00\x12\x80\x01\n\x19\x43heckConnectionConfigById\x12/.mgmt.v1alpha1.CheckConnectionConfigByIdRequest\x1a\x30.mgmt.v1alpha1.CheckConnectionConfigByIdResponse\"\x00\x12\\\n\rCheckSqlQuery\x12#.mgmt.v1alpha1.CheckSqlQueryRequest\x1a$.mgmt.v1alpha1.CheckSqlQueryResponse\"\x00\x42\xcb\x01\n\x11\x63om.mgmt.v1alpha1B\x0f\x43onnectionProtoP\x01ZPgithub.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1;mgmtv1alpha1\xa2\x02\x03MXX\xaa\x02\rMgmt.V1alpha1\xca\x02\rMgmt\\V1alpha1\xe2\x02\x19Mgmt\\V1alpha1\\GPBMetadata\xea\x02\x0eMgmt::V1alpha1b\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x1emgmt/v1alpha1/connection.proto\x12\rmgmt.v1alpha1\x1a\x1b\x62uf/validate/validate.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"m\n\x15GetConnectionsRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12+\n\x11\x65xclude_sensitive\x18\x02 \x01(\x08R\x10\x65xcludeSensitive\"U\n\x16GetConnectionsResponse\x12;\n\x0b\x63onnections\x18\x01 \x03(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\x0b\x63onnections\"]\n\x14GetConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12+\n\x11\x65xclude_sensitive\x18\x02 \x01(\x08R\x10\x65xcludeSensitive\"R\n\x15GetConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"\xbf\x01\n\x17\x43reateConnectionRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"U\n\x18\x43reateConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"\xb0\x01\n\x17UpdateConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12-\n\x04name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"U\n\x18UpdateConnectionResponse\x12\x39\n\nconnection\x18\x01 \x01(\x0b\x32\x19.mgmt.v1alpha1.ConnectionR\nconnection\"3\n\x17\x44\x65leteConnectionRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\x1a\n\x18\x44\x65leteConnectionResponse\"l\n\x1c\x43heckConnectionConfigRequest\x12L\n\x11\x63onnection_config\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\"<\n CheckConnectionConfigByIdRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"\xd3\x01\n!CheckConnectionConfigByIdResponse\x12!\n\x0cis_connected\x18\x01 \x01(\x08R\x0bisConnected\x12.\n\x10\x63onnection_error\x18\x02 \x01(\tH\x00R\x0f\x63onnectionError\x88\x01\x01\x12\x46\n\nprivileges\x18\x03 \x03(\x0b\x32&.mgmt.v1alpha1.ConnectionRolePrivilegeR\nprivilegesB\x13\n\x11_connection_error\"\xcf\x01\n\x1d\x43heckConnectionConfigResponse\x12!\n\x0cis_connected\x18\x01 \x01(\x08R\x0bisConnected\x12.\n\x10\x63onnection_error\x18\x02 \x01(\tH\x00R\x0f\x63onnectionError\x88\x01\x01\x12\x46\n\nprivileges\x18\x03 \x03(\x0b\x32&.mgmt.v1alpha1.ConnectionRolePrivilegeR\nprivilegesB\x13\n\x11_connection_error\"\x88\x01\n\x17\x43onnectionRolePrivilege\x12\x18\n\x07grantee\x18\x01 \x01(\tR\x07grantee\x12\x16\n\x06schema\x18\x02 \x01(\tR\x06schema\x12\x14\n\x05table\x18\x03 \x01(\tR\x05table\x12%\n\x0eprivilege_type\x18\x04 \x03(\tR\rprivilegeType\"\xed\x02\n\nConnection\x12\x0e\n\x02id\x18\x01 \x01(\tR\x02id\x12\x12\n\x04name\x18\x02 \x01(\tR\x04name\x12L\n\x11\x63onnection_config\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.ConnectionConfigR\x10\x63onnectionConfig\x12+\n\x12\x63reated_by_user_id\x18\x04 \x01(\tR\x0f\x63reatedByUserId\x12\x39\n\ncreated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tcreatedAt\x12+\n\x12updated_by_user_id\x18\x06 \x01(\tR\x0fupdatedByUserId\x12\x39\n\nupdated_at\x18\x07 \x01(\x0b\x32\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x1d\n\naccount_id\x18\x08 \x01(\tR\taccountId\"\xff\x05\n\x10\x43onnectionConfig\x12\x46\n\tpg_config\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.PostgresConnectionConfigH\x00R\x08pgConfig\x12J\n\raws_s3_config\x18\x02 \x01(\x0b\x32$.mgmt.v1alpha1.AwsS3ConnectionConfigH\x00R\x0b\x61wsS3Config\x12I\n\x0cmysql_config\x18\x03 \x01(\x0b\x32$.mgmt.v1alpha1.MysqlConnectionConfigH\x00R\x0bmysqlConfig\x12Y\n\x10local_dir_config\x18\x04 \x01(\x0b\x32-.mgmt.v1alpha1.LocalDirectoryConnectionConfigH\x00R\x0elocalDirConfig\x12L\n\ropenai_config\x18\x05 \x01(\x0b\x32%.mgmt.v1alpha1.OpenAiConnectionConfigH\x00R\x0copenaiConfig\x12I\n\x0cmongo_config\x18\x06 \x01(\x0b\x32$.mgmt.v1alpha1.MongoConnectionConfigH\x00R\x0bmongoConfig\x12h\n\x17gcp_cloudstorage_config\x18\x07 \x01(\x0b\x32..mgmt.v1alpha1.GcpCloudStorageConnectionConfigH\x00R\x15gcpCloudstorageConfig\x12R\n\x0f\x64ynamodb_config\x18\x08 \x01(\x0b\x32\'.mgmt.v1alpha1.DynamoDBConnectionConfigH\x00R\x0e\x64ynamodbConfig\x12I\n\x0cmssql_config\x18\t \x01(\x0b\x32$.mgmt.v1alpha1.MssqlConnectionConfigH\x00R\x0bmssqlConfigB\x0f\n\x06\x63onfig\x12\x05\xbaH\x02\x08\x01\"\xb0\x02\n\x15MssqlConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\"\n\x0curl_from_env\x18\x05 \x01(\tH\x00R\nurlFromEnv\x12R\n\x12\x63onnection_options\x18\x02 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12=\n\nclient_tls\x18\x04 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xc8\x01\n\x18\x44ynamoDBConnectionConfig\x12\x46\n\x0b\x63redentials\x18\x01 \x01(\x0b\x32\x1f.mgmt.v1alpha1.AwsS3CredentialsH\x00R\x0b\x63redentials\x88\x01\x01\x12\x1b\n\x06region\x18\x02 \x01(\tH\x01R\x06region\x88\x01\x01\x12\x1f\n\x08\x65ndpoint\x18\x03 \x01(\tH\x02R\x08\x65ndpoint\x88\x01\x01\x42\x0e\n\x0c_credentialsB\t\n\x07_regionB\x0b\n\t_endpoint\"\xb8\x01\n\x15MongoConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\x30\n\x06tunnel\x18\x02 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12=\n\nclient_tls\x18\x03 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"J\n\x16OpenAiConnectionConfig\x12\x17\n\x07\x61pi_key\x18\x01 \x01(\tR\x06\x61piKey\x12\x17\n\x07\x61pi_url\x18\x02 \x01(\tR\x06\x61piUrl\"=\n\x1eLocalDirectoryConnectionConfig\x12\x1b\n\x04path\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04path\"\xf8\x02\n\x18PostgresConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12\x43\n\nconnection\x18\x02 \x01(\x0b\x32!.mgmt.v1alpha1.PostgresConnectionH\x00R\nconnection\x12\"\n\x0curl_from_env\x18\x06 \x01(\tH\x00R\nurlFromEnv\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12R\n\x12\x63onnection_options\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12=\n\nclient_tls\x18\x05 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xe0\x01\n\x0f\x43lientTlsConfig\x12 \n\troot_cert\x18\x01 \x01(\tH\x00R\x08rootCert\x88\x01\x01\x12$\n\x0b\x63lient_cert\x18\x02 \x01(\tH\x01R\nclientCert\x88\x01\x01\x12\"\n\nclient_key\x18\x03 \x01(\tH\x02R\tclientKey\x88\x01\x01\x12$\n\x0bserver_name\x18\x04 \x01(\tH\x03R\nserverName\x88\x01\x01\x42\x0c\n\n_root_certB\x0e\n\x0c_client_certB\r\n\x0b_client_keyB\x0e\n\x0c_server_name\"\xc4\x02\n\x14SqlConnectionOptions\x12\x35\n\x14max_connection_limit\x18\x01 \x01(\x05H\x00R\x12maxConnectionLimit\x88\x01\x01\x12\x35\n\x14max_idle_connections\x18\x02 \x01(\x05H\x01R\x12maxIdleConnections\x88\x01\x01\x12/\n\x11max_idle_duration\x18\x03 \x01(\tH\x02R\x0fmaxIdleDuration\x88\x01\x01\x12/\n\x11max_open_duration\x18\x04 \x01(\tH\x03R\x0fmaxOpenDuration\x88\x01\x01\x42\x17\n\x15_max_connection_limitB\x17\n\x15_max_idle_connectionsB\x14\n\x12_max_idle_durationB\x14\n\x12_max_open_duration\"\x87\x02\n\tSSHTunnel\x12\x1b\n\x04host\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04host\x12\x1b\n\x04port\x18\x02 \x01(\x05\x42\x07\xbaH\x04\x1a\x02(\x00R\x04port\x12\x1b\n\x04user\x18\x03 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x04user\x12?\n\x15known_host_public_key\x18\x04 \x01(\tB\x07\xbaH\x04r\x02\x10\x01H\x00R\x12knownHostPublicKey\x88\x01\x01\x12H\n\x0e\x61uthentication\x18\x05 \x01(\x0b\x32 .mgmt.v1alpha1.SSHAuthenticationR\x0e\x61uthenticationB\x18\n\x16_known_host_public_key\"\xaa\x01\n\x11SSHAuthentication\x12>\n\npassphrase\x18\x01 \x01(\x0b\x32\x1c.mgmt.v1alpha1.SSHPassphraseH\x00R\npassphrase\x12?\n\x0bprivate_key\x18\x02 \x01(\x0b\x32\x1c.mgmt.v1alpha1.SSHPrivateKeyH\x00R\nprivateKeyB\x14\n\x0b\x61uth_config\x12\x05\xbaH\x02\x08\x01\".\n\rSSHPassphrase\x12\x1d\n\x05value\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05value\"b\n\rSSHPrivateKey\x12\x1d\n\x05value\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05value\x12#\n\npassphrase\x18\x02 \x01(\tH\x00R\npassphrase\x88\x01\x01\x42\r\n\x0b_passphrase\"\xa5\x01\n\x12PostgresConnection\x12\x12\n\x04host\x18\x01 \x01(\tR\x04host\x12\x12\n\x04port\x18\x02 \x01(\x05R\x04port\x12\x12\n\x04name\x18\x03 \x01(\tR\x04name\x12\x12\n\x04user\x18\x04 \x01(\tR\x04user\x12\x12\n\x04pass\x18\x05 \x01(\tR\x04pass\x12\x1e\n\x08ssl_mode\x18\x06 \x01(\tH\x00R\x07sslMode\x88\x01\x01\x42\x0b\n\t_ssl_mode\"\x91\x01\n\x0fMysqlConnection\x12\x12\n\x04user\x18\x01 \x01(\tR\x04user\x12\x12\n\x04pass\x18\x02 \x01(\tR\x04pass\x12\x1a\n\x08protocol\x18\x03 \x01(\tR\x08protocol\x12\x12\n\x04host\x18\x04 \x01(\tR\x04host\x12\x12\n\x04port\x18\x05 \x01(\x05R\x04port\x12\x12\n\x04name\x18\x06 \x01(\tR\x04name\"\xf2\x02\n\x15MysqlConnectionConfig\x12\x12\n\x03url\x18\x01 \x01(\tH\x00R\x03url\x12@\n\nconnection\x18\x02 \x01(\x0b\x32\x1e.mgmt.v1alpha1.MysqlConnectionH\x00R\nconnection\x12\"\n\x0curl_from_env\x18\x06 \x01(\tH\x00R\nurlFromEnv\x12\x30\n\x06tunnel\x18\x03 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\x12R\n\x12\x63onnection_options\x18\x04 \x01(\x0b\x32#.mgmt.v1alpha1.SqlConnectionOptionsR\x11\x63onnectionOptions\x12=\n\nclient_tls\x18\x05 \x01(\x0b\x32\x1e.mgmt.v1alpha1.ClientTlsConfigR\tclientTlsB\x1a\n\x11\x63onnection_config\x12\x05\xbaH\x02\x08\x01\"\xa2\x02\n\x15\x41wsS3ConnectionConfig\x12$\n\x0bpath_prefix\x18\x02 \x01(\tH\x00R\npathPrefix\x88\x01\x01\x12\x46\n\x0b\x63redentials\x18\x03 \x01(\x0b\x32\x1f.mgmt.v1alpha1.AwsS3CredentialsH\x01R\x0b\x63redentials\x88\x01\x01\x12\x1b\n\x06region\x18\x04 \x01(\tH\x02R\x06region\x88\x01\x01\x12\x1f\n\x08\x65ndpoint\x18\x05 \x01(\tH\x03R\x08\x65ndpoint\x88\x01\x01\x12\x1f\n\x06\x62ucket\x18\x06 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x62ucketB\x0e\n\x0c_path_prefixB\x0e\n\x0c_credentialsB\t\n\x07_regionB\x0b\n\t_endpointJ\x04\x08\x01\x10\x02\"\xa7\x03\n\x10\x41wsS3Credentials\x12\x1d\n\x07profile\x18\x01 \x01(\tH\x00R\x07profile\x88\x01\x01\x12\'\n\raccess_key_id\x18\x02 \x01(\tH\x01R\x0b\x61\x63\x63\x65ssKeyId\x88\x01\x01\x12/\n\x11secret_access_key\x18\x03 \x01(\tH\x02R\x0fsecretAccessKey\x88\x01\x01\x12(\n\rsession_token\x18\x04 \x01(\tH\x03R\x0csessionToken\x88\x01\x01\x12\'\n\rfrom_ec2_role\x18\x05 \x01(\x08H\x04R\x0b\x66romEc2Role\x88\x01\x01\x12\x1e\n\x08role_arn\x18\x06 \x01(\tH\x05R\x07roleArn\x88\x01\x01\x12-\n\x10role_external_id\x18\x07 \x01(\tH\x06R\x0eroleExternalId\x88\x01\x01\x42\n\n\x08_profileB\x10\n\x0e_access_key_idB\x14\n\x12_secret_access_keyB\x10\n\x0e_session_tokenB\x10\n\x0e_from_ec2_roleB\x0b\n\t_role_arnB\x13\n\x11_role_external_id\"\xdd\x01\n\x1fGcpCloudStorageConnectionConfig\x12\x1f\n\x06\x62ucket\x18\x01 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x06\x62ucket\x12$\n\x0bpath_prefix\x18\x02 \x01(\tH\x00R\npathPrefix\x88\x01\x01\x12\x43\n\x1bservice_account_credentials\x18\x03 \x01(\tH\x01R\x19serviceAccountCredentials\x88\x01\x01\x42\x0e\n\x0c_path_prefixB\x1e\n\x1c_service_account_credentials\"\x8f\x01\n IsConnectionNameAvailableRequest\x12\'\n\naccount_id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\taccountId\x12\x42\n\x0f\x63onnection_name\x18\x02 \x01(\tB\x19\xbaH\x16r\x14\x32\x12^[a-z0-9-]{3,100}$R\x0e\x63onnectionName\"F\n!IsConnectionNameAvailableResponse\x12!\n\x0cis_available\x18\x01 \x01(\x08R\x0bisAvailable\"O\n\x14\x43heckSqlQueryRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\x12\x1d\n\x05query\x18\x02 \x01(\tB\x07\xbaH\x04r\x02\x10\x01R\x05query\"n\n\x15\x43heckSqlQueryResponse\x12\x19\n\x08is_valid\x18\x01 \x01(\x08R\x07isValid\x12(\n\rerorr_message\x18\x02 \x01(\tH\x00R\x0c\x65rorrMessage\x88\x01\x01\x42\x10\n\x0e_erorr_message\"M\n\x19\x43heckSSHConnectionRequest\x12\x30\n\x06tunnel\x18\x01 \x01(\x0b\x32\x18.mgmt.v1alpha1.SSHTunnelR\x06tunnel\"]\n\x1a\x43heckSSHConnectionResponse\x12?\n\x06result\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.CheckSSHConnectionResultR\x06result\"9\n\x1d\x43heckSSHConnectionByIdRequest\x12\x18\n\x02id\x18\x01 \x01(\tB\x08\xbaH\x05r\x03\xb0\x01\x01R\x02id\"a\n\x1e\x43heckSSHConnectionByIdResponse\x12?\n\x06result\x18\x01 \x01(\x0b\x32\'.mgmt.v1alpha1.CheckSSHConnectionResultR\x06result\"{\n\x18\x43heckSSHConnectionResult\x12#\n\ris_successful\x18\x01 \x01(\x08R\x0cisSuccessful\x12(\n\rerror_message\x18\x02 \x01(\tH\x00R\x0c\x65rrorMessage\x88\x01\x01\x42\x10\n\x0e_error_message2\xcd\t\n\x11\x43onnectionService\x12\x62\n\x0eGetConnections\x12$.mgmt.v1alpha1.GetConnectionsRequest\x1a%.mgmt.v1alpha1.GetConnectionsResponse\"\x03\x90\x02\x01\x12_\n\rGetConnection\x12#.mgmt.v1alpha1.GetConnectionRequest\x1a$.mgmt.v1alpha1.GetConnectionResponse\"\x03\x90\x02\x01\x12\x65\n\x10\x43reateConnection\x12&.mgmt.v1alpha1.CreateConnectionRequest\x1a\'.mgmt.v1alpha1.CreateConnectionResponse\"\x00\x12\x65\n\x10UpdateConnection\x12&.mgmt.v1alpha1.UpdateConnectionRequest\x1a\'.mgmt.v1alpha1.UpdateConnectionResponse\"\x00\x12\x65\n\x10\x44\x65leteConnection\x12&.mgmt.v1alpha1.DeleteConnectionRequest\x1a\'.mgmt.v1alpha1.DeleteConnectionResponse\"\x00\x12\x80\x01\n\x19IsConnectionNameAvailable\x12/.mgmt.v1alpha1.IsConnectionNameAvailableRequest\x1a\x30.mgmt.v1alpha1.IsConnectionNameAvailableResponse\"\x00\x12t\n\x15\x43heckConnectionConfig\x12+.mgmt.v1alpha1.CheckConnectionConfigRequest\x1a,.mgmt.v1alpha1.CheckConnectionConfigResponse\"\x00\x12\x80\x01\n\x19\x43heckConnectionConfigById\x12/.mgmt.v1alpha1.CheckConnectionConfigByIdRequest\x1a\x30.mgmt.v1alpha1.CheckConnectionConfigByIdResponse\"\x00\x12\\\n\rCheckSqlQuery\x12#.mgmt.v1alpha1.CheckSqlQueryRequest\x1a$.mgmt.v1alpha1.CheckSqlQueryResponse\"\x00\x12k\n\x12\x43heckSSHConnection\x12(.mgmt.v1alpha1.CheckSSHConnectionRequest\x1a).mgmt.v1alpha1.CheckSSHConnectionResponse\"\x00\x12w\n\x16\x43heckSSHConnectionById\x12,.mgmt.v1alpha1.CheckSSHConnectionByIdRequest\x1a-.mgmt.v1alpha1.CheckSSHConnectionByIdResponse\"\x00\x42\xcb\x01\n\x11\x63om.mgmt.v1alpha1B\x0f\x43onnectionProtoP\x01ZPgithub.com/nucleuscloud/neosync/backend/gen/go/protos/mgmt/v1alpha1;mgmtv1alpha1\xa2\x02\x03MXX\xaa\x02\rMgmt.V1alpha1\xca\x02\rMgmt\\V1alpha1\xe2\x02\x19Mgmt\\V1alpha1\\GPBMetadata\xea\x02\x0eMgmt::V1alpha1b\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -88,6 +88,8 @@ _globals['_CHECKSQLQUERYREQUEST'].fields_by_name['id']._serialized_options = b'\272H\005r\003\260\001\001' _globals['_CHECKSQLQUERYREQUEST'].fields_by_name['query']._loaded_options = None _globals['_CHECKSQLQUERYREQUEST'].fields_by_name['query']._serialized_options = b'\272H\004r\002\020\001' + _globals['_CHECKSSHCONNECTIONBYIDREQUEST'].fields_by_name['id']._loaded_options = None + _globals['_CHECKSSHCONNECTIONBYIDREQUEST'].fields_by_name['id']._serialized_options = b'\272H\005r\003\260\001\001' _globals['_CONNECTIONSERVICE'].methods_by_name['GetConnections']._loaded_options = None _globals['_CONNECTIONSERVICE'].methods_by_name['GetConnections']._serialized_options = b'\220\002\001' _globals['_CONNECTIONSERVICE'].methods_by_name['GetConnection']._loaded_options = None @@ -170,6 +172,16 @@ _globals['_CHECKSQLQUERYREQUEST']._serialized_end=7274 _globals['_CHECKSQLQUERYRESPONSE']._serialized_start=7276 _globals['_CHECKSQLQUERYRESPONSE']._serialized_end=7386 - _globals['_CONNECTIONSERVICE']._serialized_start=7389 - _globals['_CONNECTIONSERVICE']._serialized_end=8388 + _globals['_CHECKSSHCONNECTIONREQUEST']._serialized_start=7388 + _globals['_CHECKSSHCONNECTIONREQUEST']._serialized_end=7465 + _globals['_CHECKSSHCONNECTIONRESPONSE']._serialized_start=7467 + _globals['_CHECKSSHCONNECTIONRESPONSE']._serialized_end=7560 + _globals['_CHECKSSHCONNECTIONBYIDREQUEST']._serialized_start=7562 + _globals['_CHECKSSHCONNECTIONBYIDREQUEST']._serialized_end=7619 + _globals['_CHECKSSHCONNECTIONBYIDRESPONSE']._serialized_start=7621 + _globals['_CHECKSSHCONNECTIONBYIDRESPONSE']._serialized_end=7718 + _globals['_CHECKSSHCONNECTIONRESULT']._serialized_start=7720 + _globals['_CHECKSSHCONNECTIONRESULT']._serialized_end=7843 + _globals['_CONNECTIONSERVICE']._serialized_start=7846 + _globals['_CONNECTIONSERVICE']._serialized_end=9075 # @@protoc_insertion_point(module_scope) diff --git a/python/src/neosync/mgmt/v1alpha1/connection_pb2.pyi b/python/src/neosync/mgmt/v1alpha1/connection_pb2.pyi index e2abeb77f4..84123e331d 100644 --- a/python/src/neosync/mgmt/v1alpha1/connection_pb2.pyi +++ b/python/src/neosync/mgmt/v1alpha1/connection_pb2.pyi @@ -404,3 +404,35 @@ class CheckSqlQueryResponse(_message.Message): is_valid: bool erorr_message: str def __init__(self, is_valid: bool = ..., erorr_message: _Optional[str] = ...) -> None: ... + +class CheckSSHConnectionRequest(_message.Message): + __slots__ = ("tunnel",) + TUNNEL_FIELD_NUMBER: _ClassVar[int] + tunnel: SSHTunnel + def __init__(self, tunnel: _Optional[_Union[SSHTunnel, _Mapping]] = ...) -> None: ... + +class CheckSSHConnectionResponse(_message.Message): + __slots__ = ("result",) + RESULT_FIELD_NUMBER: _ClassVar[int] + result: CheckSSHConnectionResult + def __init__(self, result: _Optional[_Union[CheckSSHConnectionResult, _Mapping]] = ...) -> None: ... + +class CheckSSHConnectionByIdRequest(_message.Message): + __slots__ = ("id",) + ID_FIELD_NUMBER: _ClassVar[int] + id: str + def __init__(self, id: _Optional[str] = ...) -> None: ... + +class CheckSSHConnectionByIdResponse(_message.Message): + __slots__ = ("result",) + RESULT_FIELD_NUMBER: _ClassVar[int] + result: CheckSSHConnectionResult + def __init__(self, result: _Optional[_Union[CheckSSHConnectionResult, _Mapping]] = ...) -> None: ... + +class CheckSSHConnectionResult(_message.Message): + __slots__ = ("is_successful", "error_message") + IS_SUCCESSFUL_FIELD_NUMBER: _ClassVar[int] + ERROR_MESSAGE_FIELD_NUMBER: _ClassVar[int] + is_successful: bool + error_message: str + def __init__(self, is_successful: bool = ..., error_message: _Optional[str] = ...) -> None: ... diff --git a/python/src/neosync/mgmt/v1alpha1/connection_pb2_grpc.py b/python/src/neosync/mgmt/v1alpha1/connection_pb2_grpc.py index f3577956cf..a71f7a5127 100644 --- a/python/src/neosync/mgmt/v1alpha1/connection_pb2_grpc.py +++ b/python/src/neosync/mgmt/v1alpha1/connection_pb2_grpc.py @@ -61,6 +61,16 @@ def __init__(self, channel): request_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSqlQueryRequest.SerializeToString, response_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSqlQueryResponse.FromString, _registered_method=True) + self.CheckSSHConnection = channel.unary_unary( + '/mgmt.v1alpha1.ConnectionService/CheckSSHConnection', + request_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionRequest.SerializeToString, + response_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionResponse.FromString, + _registered_method=True) + self.CheckSSHConnectionById = channel.unary_unary( + '/mgmt.v1alpha1.ConnectionService/CheckSSHConnectionById', + request_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdRequest.SerializeToString, + response_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdResponse.FromString, + _registered_method=True) class ConnectionServiceServicer(object): @@ -134,6 +144,20 @@ def CheckSqlQuery(self, request, context): context.set_details('Method not implemented!') raise NotImplementedError('Method not implemented!') + def CheckSSHConnection(self, request, context): + """Checks if the SSH server is reachable and accessible with the given credentials + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + + def CheckSSHConnectionById(self, request, context): + """Checks if the SSH server is reachable and accessible with the given credentials + """ + context.set_code(grpc.StatusCode.UNIMPLEMENTED) + context.set_details('Method not implemented!') + raise NotImplementedError('Method not implemented!') + def add_ConnectionServiceServicer_to_server(servicer, server): rpc_method_handlers = { @@ -182,6 +206,16 @@ def add_ConnectionServiceServicer_to_server(servicer, server): request_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSqlQueryRequest.FromString, response_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSqlQueryResponse.SerializeToString, ), + 'CheckSSHConnection': grpc.unary_unary_rpc_method_handler( + servicer.CheckSSHConnection, + request_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionRequest.FromString, + response_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionResponse.SerializeToString, + ), + 'CheckSSHConnectionById': grpc.unary_unary_rpc_method_handler( + servicer.CheckSSHConnectionById, + request_deserializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdRequest.FromString, + response_serializer=mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdResponse.SerializeToString, + ), } generic_handler = grpc.method_handlers_generic_handler( 'mgmt.v1alpha1.ConnectionService', rpc_method_handlers) @@ -437,3 +471,57 @@ def CheckSqlQuery(request, timeout, metadata, _registered_method=True) + + @staticmethod + def CheckSSHConnection(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/mgmt.v1alpha1.ConnectionService/CheckSSHConnection', + mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionRequest.SerializeToString, + mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True) + + @staticmethod + def CheckSSHConnectionById(request, + target, + options=(), + channel_credentials=None, + call_credentials=None, + insecure=False, + compression=None, + wait_for_ready=None, + timeout=None, + metadata=None): + return grpc.experimental.unary_unary( + request, + target, + '/mgmt.v1alpha1.ConnectionService/CheckSSHConnectionById', + mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdRequest.SerializeToString, + mgmt_dot_v1alpha1_dot_connection__pb2.CheckSSHConnectionByIdResponse.FromString, + options, + channel_credentials, + insecure, + call_credentials, + compression, + wait_for_ready, + timeout, + metadata, + _registered_method=True)