1
0
Fork 0

Merge pull request #1057 from ngharrington/nharrington-forward-creds

WIP TCP service auth
master
Philip O'Toole 2 years ago committed by GitHub
commit 7211e4d93b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -227,10 +227,19 @@ func Test_AuthPermsAA(t *testing.T) {
if store.AA("nonexistent", "password1", "foo") { if store.AA("nonexistent", "password1", "foo") {
t.Fatalf("nonexistent authenticated and authorized for foo") t.Fatalf("nonexistent authenticated and authorized for foo")
} }
if !store.AA("nonexistent", "password1", "qux") { if !store.AA("nonexistent", "password1", "qux") {
t.Fatalf("nonexistent not authenticated and authorized for qux") t.Fatalf("nonexistent not authenticated and authorized for qux")
} }
// explicit check of anonymous user
if !store.AA("", "", "qux") {
t.Fatalf("anonymous incorrectly not authorized")
}
if store.AA("", "", "foo") {
t.Fatalf("anonymous incorrectly authorized")
}
if !store.AA("username1", "password1", "foo") { if !store.AA("username1", "password1", "foo") {
t.Fatalf("username1 not authenticated and authorized for foo") t.Fatalf("username1 not authenticated and authorized for foo")
} }

@ -132,8 +132,10 @@ func (c *Client) GetNodeAPIAddr(nodeAddr string, timeout time.Duration) (string,
return a.Url, nil return a.Url, nil
} }
// Execute performs an Execute on a remote node. // Execute performs an Execute on a remote node. If username is an empty string
func (c *Client) Execute(er *command.ExecuteRequest, nodeAddr string, timeout time.Duration) ([]*command.ExecuteResult, error) { // no credential information will be included in the Execute request to the
// remote node.
func (c *Client) Execute(er *command.ExecuteRequest, nodeAddr string, username string, password string, timeout time.Duration) ([]*command.ExecuteResult, error) {
conn, err := c.dial(nodeAddr, c.timeout) conn, err := c.dial(nodeAddr, c.timeout)
if err != nil { if err != nil {
return nil, err return nil, err
@ -147,6 +149,14 @@ func (c *Client) Execute(er *command.ExecuteRequest, nodeAddr string, timeout ti
ExecuteRequest: er, ExecuteRequest: er,
}, },
} }
if username != "" {
command.Credentials = &Credentials{
Username: username,
Password: password,
}
}
p, err := proto.Marshal(command) p, err := proto.Marshal(command)
if err != nil { if err != nil {
return nil, fmt.Errorf("command marshal: %s", err) return nil, fmt.Errorf("command marshal: %s", err)
@ -205,14 +215,14 @@ func (c *Client) Execute(er *command.ExecuteRequest, nodeAddr string, timeout ti
return nil, err return nil, err
} }
if a.Error != "" { if a.Error != nil {
return nil, errors.New(a.Error) return nil, errors.New(a.Error.GetError())
} }
return a.Results, nil return a.Results, nil
} }
// Query performs a Query on a remote node. // Query performs a Query on a remote node.
func (c *Client) Query(qr *command.QueryRequest, nodeAddr string, timeout time.Duration) ([]*command.QueryRows, error) { func (c *Client) Query(qr *command.QueryRequest, nodeAddr string, username string, password string, timeout time.Duration) ([]*command.QueryRows, error) {
conn, err := c.dial(nodeAddr, c.timeout) conn, err := c.dial(nodeAddr, c.timeout)
if err != nil { if err != nil {
return nil, err return nil, err
@ -226,6 +236,13 @@ func (c *Client) Query(qr *command.QueryRequest, nodeAddr string, timeout time.D
QueryRequest: qr, QueryRequest: qr,
}, },
} }
if username != "" {
command.Credentials = &Credentials{
Username: username,
Password: password,
}
}
p, err := proto.Marshal(command) p, err := proto.Marshal(command)
if err != nil { if err != nil {
return nil, fmt.Errorf("command marshal: %s", err) return nil, fmt.Errorf("command marshal: %s", err)
@ -281,8 +298,8 @@ func (c *Client) Query(qr *command.QueryRequest, nodeAddr string, timeout time.D
return nil, err return nil, err
} }
if a.Error != "" { if a.Error != nil {
return nil, errors.New(a.Error) return nil, errors.New(a.Error.GetError())
} }
return a.Rows, nil return a.Rows, nil
} }

@ -1,8 +1,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT. // Code generated by protoc-gen-go. DO NOT EDIT.
// versions: // versions:
// protoc-gen-go v1.27.1 // protoc-gen-go v1.28.0
// protoc v3.13.0 // protoc v3.21.2
// source: message.proto // source: cluster/message.proto
package cluster package cluster
@ -57,11 +57,11 @@ func (x Command_Type) String() string {
} }
func (Command_Type) Descriptor() protoreflect.EnumDescriptor { func (Command_Type) Descriptor() protoreflect.EnumDescriptor {
return file_message_proto_enumTypes[0].Descriptor() return file_cluster_message_proto_enumTypes[0].Descriptor()
} }
func (Command_Type) Type() protoreflect.EnumType { func (Command_Type) Type() protoreflect.EnumType {
return &file_message_proto_enumTypes[0] return &file_cluster_message_proto_enumTypes[0]
} }
func (x Command_Type) Number() protoreflect.EnumNumber { func (x Command_Type) Number() protoreflect.EnumNumber {
@ -70,7 +70,111 @@ func (x Command_Type) Number() protoreflect.EnumNumber {
// Deprecated: Use Command_Type.Descriptor instead. // Deprecated: Use Command_Type.Descriptor instead.
func (Command_Type) EnumDescriptor() ([]byte, []int) { func (Command_Type) EnumDescriptor() ([]byte, []int) {
return file_message_proto_rawDescGZIP(), []int{1, 0} return file_cluster_message_proto_rawDescGZIP(), []int{2, 0}
}
type ResultsError_Type int32
const (
ResultsError_RESULTS_ERROR_UNSPECIFIED ResultsError_Type = 0
ResultsError_RESULTS_ERROR_UNAUTHORIZED ResultsError_Type = 1
ResultsError_RESULTS_ERROR_NIL_QUERY_REQUEST ResultsError_Type = 2
)
// Enum value maps for ResultsError_Type.
var (
ResultsError_Type_name = map[int32]string{
0: "RESULTS_ERROR_UNSPECIFIED",
1: "RESULTS_ERROR_UNAUTHORIZED",
2: "RESULTS_ERROR_NIL_QUERY_REQUEST",
}
ResultsError_Type_value = map[string]int32{
"RESULTS_ERROR_UNSPECIFIED": 0,
"RESULTS_ERROR_UNAUTHORIZED": 1,
"RESULTS_ERROR_NIL_QUERY_REQUEST": 2,
}
)
func (x ResultsError_Type) Enum() *ResultsError_Type {
p := new(ResultsError_Type)
*p = x
return p
}
func (x ResultsError_Type) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (ResultsError_Type) Descriptor() protoreflect.EnumDescriptor {
return file_cluster_message_proto_enumTypes[1].Descriptor()
}
func (ResultsError_Type) Type() protoreflect.EnumType {
return &file_cluster_message_proto_enumTypes[1]
}
func (x ResultsError_Type) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use ResultsError_Type.Descriptor instead.
func (ResultsError_Type) EnumDescriptor() ([]byte, []int) {
return file_cluster_message_proto_rawDescGZIP(), []int{3, 0}
}
type Credentials struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *Credentials) Reset() {
*x = Credentials{}
if protoimpl.UnsafeEnabled {
mi := &file_cluster_message_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Credentials) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Credentials) ProtoMessage() {}
func (x *Credentials) ProtoReflect() protoreflect.Message {
mi := &file_cluster_message_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Credentials.ProtoReflect.Descriptor instead.
func (*Credentials) Descriptor() ([]byte, []int) {
return file_cluster_message_proto_rawDescGZIP(), []int{0}
}
func (x *Credentials) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *Credentials) GetPassword() string {
if x != nil {
return x.Password
}
return ""
} }
type Address struct { type Address struct {
@ -84,7 +188,7 @@ type Address struct {
func (x *Address) Reset() { func (x *Address) Reset() {
*x = Address{} *x = Address{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_message_proto_msgTypes[0] mi := &file_cluster_message_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -97,7 +201,7 @@ func (x *Address) String() string {
func (*Address) ProtoMessage() {} func (*Address) ProtoMessage() {}
func (x *Address) ProtoReflect() protoreflect.Message { func (x *Address) ProtoReflect() protoreflect.Message {
mi := &file_message_proto_msgTypes[0] mi := &file_cluster_message_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -110,7 +214,7 @@ func (x *Address) ProtoReflect() protoreflect.Message {
// Deprecated: Use Address.ProtoReflect.Descriptor instead. // Deprecated: Use Address.ProtoReflect.Descriptor instead.
func (*Address) Descriptor() ([]byte, []int) { func (*Address) Descriptor() ([]byte, []int) {
return file_message_proto_rawDescGZIP(), []int{0} return file_cluster_message_proto_rawDescGZIP(), []int{1}
} }
func (x *Address) GetUrl() string { func (x *Address) GetUrl() string {
@ -129,13 +233,14 @@ type Command struct {
// Types that are assignable to Request: // Types that are assignable to Request:
// *Command_ExecuteRequest // *Command_ExecuteRequest
// *Command_QueryRequest // *Command_QueryRequest
Request isCommand_Request `protobuf_oneof:"request"` Request isCommand_Request `protobuf_oneof:"request"`
Credentials *Credentials `protobuf:"bytes,4,opt,name=credentials,proto3" json:"credentials,omitempty"`
} }
func (x *Command) Reset() { func (x *Command) Reset() {
*x = Command{} *x = Command{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_message_proto_msgTypes[1] mi := &file_cluster_message_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -148,7 +253,7 @@ func (x *Command) String() string {
func (*Command) ProtoMessage() {} func (*Command) ProtoMessage() {}
func (x *Command) ProtoReflect() protoreflect.Message { func (x *Command) ProtoReflect() protoreflect.Message {
mi := &file_message_proto_msgTypes[1] mi := &file_cluster_message_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -161,7 +266,7 @@ func (x *Command) ProtoReflect() protoreflect.Message {
// Deprecated: Use Command.ProtoReflect.Descriptor instead. // Deprecated: Use Command.ProtoReflect.Descriptor instead.
func (*Command) Descriptor() ([]byte, []int) { func (*Command) Descriptor() ([]byte, []int) {
return file_message_proto_rawDescGZIP(), []int{1} return file_cluster_message_proto_rawDescGZIP(), []int{2}
} }
func (x *Command) GetType() Command_Type { func (x *Command) GetType() Command_Type {
@ -192,6 +297,13 @@ func (x *Command) GetQueryRequest() *command.QueryRequest {
return nil return nil
} }
func (x *Command) GetCredentials() *Credentials {
if x != nil {
return x.Credentials
}
return nil
}
type isCommand_Request interface { type isCommand_Request interface {
isCommand_Request() isCommand_Request()
} }
@ -208,19 +320,74 @@ func (*Command_ExecuteRequest) isCommand_Request() {}
func (*Command_QueryRequest) isCommand_Request() {} func (*Command_QueryRequest) isCommand_Request() {}
type ResultsError struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Type ResultsError_Type `protobuf:"varint,1,opt,name=type,proto3,enum=cluster.ResultsError_Type" json:"type,omitempty"`
Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"`
}
func (x *ResultsError) Reset() {
*x = ResultsError{}
if protoimpl.UnsafeEnabled {
mi := &file_cluster_message_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *ResultsError) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ResultsError) ProtoMessage() {}
func (x *ResultsError) ProtoReflect() protoreflect.Message {
mi := &file_cluster_message_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ResultsError.ProtoReflect.Descriptor instead.
func (*ResultsError) Descriptor() ([]byte, []int) {
return file_cluster_message_proto_rawDescGZIP(), []int{3}
}
func (x *ResultsError) GetType() ResultsError_Type {
if x != nil {
return x.Type
}
return ResultsError_RESULTS_ERROR_UNSPECIFIED
}
func (x *ResultsError) GetError() string {
if x != nil {
return x.Error
}
return ""
}
type CommandExecuteResponse struct { type CommandExecuteResponse struct {
state protoimpl.MessageState state protoimpl.MessageState
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` Error *ResultsError `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
Results []*command.ExecuteResult `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"` Results []*command.ExecuteResult `protobuf:"bytes,2,rep,name=results,proto3" json:"results,omitempty"`
} }
func (x *CommandExecuteResponse) Reset() { func (x *CommandExecuteResponse) Reset() {
*x = CommandExecuteResponse{} *x = CommandExecuteResponse{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_message_proto_msgTypes[2] mi := &file_cluster_message_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -233,7 +400,7 @@ func (x *CommandExecuteResponse) String() string {
func (*CommandExecuteResponse) ProtoMessage() {} func (*CommandExecuteResponse) ProtoMessage() {}
func (x *CommandExecuteResponse) ProtoReflect() protoreflect.Message { func (x *CommandExecuteResponse) ProtoReflect() protoreflect.Message {
mi := &file_message_proto_msgTypes[2] mi := &file_cluster_message_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -246,14 +413,14 @@ func (x *CommandExecuteResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use CommandExecuteResponse.ProtoReflect.Descriptor instead. // Deprecated: Use CommandExecuteResponse.ProtoReflect.Descriptor instead.
func (*CommandExecuteResponse) Descriptor() ([]byte, []int) { func (*CommandExecuteResponse) Descriptor() ([]byte, []int) {
return file_message_proto_rawDescGZIP(), []int{2} return file_cluster_message_proto_rawDescGZIP(), []int{4}
} }
func (x *CommandExecuteResponse) GetError() string { func (x *CommandExecuteResponse) GetError() *ResultsError {
if x != nil { if x != nil {
return x.Error return x.Error
} }
return "" return nil
} }
func (x *CommandExecuteResponse) GetResults() []*command.ExecuteResult { func (x *CommandExecuteResponse) GetResults() []*command.ExecuteResult {
@ -268,14 +435,14 @@ type CommandQueryResponse struct {
sizeCache protoimpl.SizeCache sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields unknownFields protoimpl.UnknownFields
Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` Error *ResultsError `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"`
Rows []*command.QueryRows `protobuf:"bytes,2,rep,name=rows,proto3" json:"rows,omitempty"` Rows []*command.QueryRows `protobuf:"bytes,2,rep,name=rows,proto3" json:"rows,omitempty"`
} }
func (x *CommandQueryResponse) Reset() { func (x *CommandQueryResponse) Reset() {
*x = CommandQueryResponse{} *x = CommandQueryResponse{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_message_proto_msgTypes[3] mi := &file_cluster_message_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -288,7 +455,7 @@ func (x *CommandQueryResponse) String() string {
func (*CommandQueryResponse) ProtoMessage() {} func (*CommandQueryResponse) ProtoMessage() {}
func (x *CommandQueryResponse) ProtoReflect() protoreflect.Message { func (x *CommandQueryResponse) ProtoReflect() protoreflect.Message {
mi := &file_message_proto_msgTypes[3] mi := &file_cluster_message_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -301,14 +468,14 @@ func (x *CommandQueryResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use CommandQueryResponse.ProtoReflect.Descriptor instead. // Deprecated: Use CommandQueryResponse.ProtoReflect.Descriptor instead.
func (*CommandQueryResponse) Descriptor() ([]byte, []int) { func (*CommandQueryResponse) Descriptor() ([]byte, []int) {
return file_message_proto_rawDescGZIP(), []int{3} return file_cluster_message_proto_rawDescGZIP(), []int{5}
} }
func (x *CommandQueryResponse) GetError() string { func (x *CommandQueryResponse) GetError() *ResultsError {
if x != nil { if x != nil {
return x.Error return x.Error
} }
return "" return nil
} }
func (x *CommandQueryResponse) GetRows() []*command.QueryRows { func (x *CommandQueryResponse) GetRows() []*command.QueryRows {
@ -318,95 +485,138 @@ func (x *CommandQueryResponse) GetRows() []*command.QueryRows {
return nil return nil
} }
var File_message_proto protoreflect.FileDescriptor var File_cluster_message_proto protoreflect.FileDescriptor
var file_message_proto_rawDesc = []byte{ var file_cluster_message_proto_rawDesc = []byte{
0x0a, 0x0d, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x15, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67,
0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72,
0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x1a, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e,
0x1b, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x45, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x64, 0x65,
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xb8, 0x02, 0x0a, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x07, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02,
0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x1b,
0x79, 0x70, 0x65, 0x12, 0x42, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x0a, 0x07, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xf0, 0x02, 0x0a, 0x07,
0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18,
0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79,
0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x70, 0x65, 0x12, 0x42, 0x0a, 0x0f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x72, 0x65,
0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6f,
0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71,
0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52,
0x14, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f,
0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e,
0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71,
0x5f, 0x41, 0x50, 0x49, 0x5f, 0x55, 0x52, 0x4c, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71,
0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x75, 0x65, 0x73, 0x74, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x54, 0x45, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x6c, 0x75, 0x73,
0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x10, 0x03, 0x42, 0x09, 0x0a, 0x07, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x52,
0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x60, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x0b, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x73, 0x22, 0x75, 0x0a, 0x04,
0x6e, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x54, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x21,
0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x0a, 0x1d, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47,
0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x45, 0x54, 0x5f, 0x4e, 0x4f, 0x44, 0x45, 0x5f, 0x41, 0x50, 0x49, 0x5f, 0x55, 0x52, 0x4c, 0x10,
0x6e, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x43, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50,
0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x54, 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x45, 0x5f, 0x45, 0x58, 0x45, 0x43, 0x55, 0x54, 0x45, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x43,
0x6d, 0x61, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0x44, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x52,
0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x59, 0x10, 0x03, 0x42, 0x09, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xc0,
0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x26, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x12,
0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e,
0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x77, 0x73, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x42, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45,
0x22, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x71, 0x72, 0x72, 0x6f, 0x72, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
0x6c, 0x69, 0x74, 0x65, 0x2f, 0x72, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6a, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a,
0x19, 0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55,
0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a,
0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x55, 0x4e,
0x41, 0x55, 0x54, 0x48, 0x4f, 0x52, 0x49, 0x5a, 0x45, 0x44, 0x10, 0x01, 0x12, 0x23, 0x0a, 0x1f,
0x52, 0x45, 0x53, 0x55, 0x4c, 0x54, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x5f, 0x4e, 0x49,
0x4c, 0x5f, 0x51, 0x55, 0x45, 0x52, 0x59, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x45, 0x53, 0x54, 0x10,
0x02, 0x22, 0x77, 0x0a, 0x16, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x45, 0x78, 0x65, 0x63,
0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75,
0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x45, 0x72, 0x72, 0x6f,
0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x07, 0x72, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
0x61, 0x6e, 0x64, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x52, 0x07, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x22, 0x6b, 0x0a, 0x14, 0x43, 0x6f,
0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x2b, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x15, 0x2e, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12,
0x26, 0x0a, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e,
0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x6f, 0x77,
0x73, 0x52, 0x04, 0x72, 0x6f, 0x77, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x72, 0x71, 0x6c, 0x69, 0x74, 0x65, 0x2f, 0x72, 0x71, 0x6c,
0x69, 0x74, 0x65, 0x2f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
} }
var ( var (
file_message_proto_rawDescOnce sync.Once file_cluster_message_proto_rawDescOnce sync.Once
file_message_proto_rawDescData = file_message_proto_rawDesc file_cluster_message_proto_rawDescData = file_cluster_message_proto_rawDesc
) )
func file_message_proto_rawDescGZIP() []byte { func file_cluster_message_proto_rawDescGZIP() []byte {
file_message_proto_rawDescOnce.Do(func() { file_cluster_message_proto_rawDescOnce.Do(func() {
file_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_message_proto_rawDescData) file_cluster_message_proto_rawDescData = protoimpl.X.CompressGZIP(file_cluster_message_proto_rawDescData)
}) })
return file_message_proto_rawDescData return file_cluster_message_proto_rawDescData
} }
var file_message_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_cluster_message_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_message_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_cluster_message_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_message_proto_goTypes = []interface{}{ var file_cluster_message_proto_goTypes = []interface{}{
(Command_Type)(0), // 0: cluster.Command.Type (Command_Type)(0), // 0: cluster.Command.Type
(*Address)(nil), // 1: cluster.Address (ResultsError_Type)(0), // 1: cluster.ResultsError.Type
(*Command)(nil), // 2: cluster.Command (*Credentials)(nil), // 2: cluster.Credentials
(*CommandExecuteResponse)(nil), // 3: cluster.CommandExecuteResponse (*Address)(nil), // 3: cluster.Address
(*CommandQueryResponse)(nil), // 4: cluster.CommandQueryResponse (*Command)(nil), // 4: cluster.Command
(*command.ExecuteRequest)(nil), // 5: command.ExecuteRequest (*ResultsError)(nil), // 5: cluster.ResultsError
(*command.QueryRequest)(nil), // 6: command.QueryRequest (*CommandExecuteResponse)(nil), // 6: cluster.CommandExecuteResponse
(*command.ExecuteResult)(nil), // 7: command.ExecuteResult (*CommandQueryResponse)(nil), // 7: cluster.CommandQueryResponse
(*command.QueryRows)(nil), // 8: command.QueryRows (*command.ExecuteRequest)(nil), // 8: command.ExecuteRequest
} (*command.QueryRequest)(nil), // 9: command.QueryRequest
var file_message_proto_depIdxs = []int32{ (*command.ExecuteResult)(nil), // 10: command.ExecuteResult
0, // 0: cluster.Command.type:type_name -> cluster.Command.Type (*command.QueryRows)(nil), // 11: command.QueryRows
5, // 1: cluster.Command.execute_request:type_name -> command.ExecuteRequest }
6, // 2: cluster.Command.query_request:type_name -> command.QueryRequest var file_cluster_message_proto_depIdxs = []int32{
7, // 3: cluster.CommandExecuteResponse.results:type_name -> command.ExecuteResult 0, // 0: cluster.Command.type:type_name -> cluster.Command.Type
8, // 4: cluster.CommandQueryResponse.rows:type_name -> command.QueryRows 8, // 1: cluster.Command.execute_request:type_name -> command.ExecuteRequest
5, // [5:5] is the sub-list for method output_type 9, // 2: cluster.Command.query_request:type_name -> command.QueryRequest
5, // [5:5] is the sub-list for method input_type 2, // 3: cluster.Command.credentials:type_name -> cluster.Credentials
5, // [5:5] is the sub-list for extension type_name 1, // 4: cluster.ResultsError.type:type_name -> cluster.ResultsError.Type
5, // [5:5] is the sub-list for extension extendee 5, // 5: cluster.CommandExecuteResponse.error:type_name -> cluster.ResultsError
0, // [0:5] is the sub-list for field type_name 10, // 6: cluster.CommandExecuteResponse.results:type_name -> command.ExecuteResult
} 5, // 7: cluster.CommandQueryResponse.error:type_name -> cluster.ResultsError
11, // 8: cluster.CommandQueryResponse.rows:type_name -> command.QueryRows
func init() { file_message_proto_init() } 9, // [9:9] is the sub-list for method output_type
func file_message_proto_init() { 9, // [9:9] is the sub-list for method input_type
if File_message_proto != nil { 9, // [9:9] is the sub-list for extension type_name
9, // [9:9] is the sub-list for extension extendee
0, // [0:9] is the sub-list for field type_name
}
func init() { file_cluster_message_proto_init() }
func file_cluster_message_proto_init() {
if File_cluster_message_proto != nil {
return return
} }
if !protoimpl.UnsafeEnabled { if !protoimpl.UnsafeEnabled {
file_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { file_cluster_message_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Credentials); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_cluster_message_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Address); i { switch v := v.(*Address); i {
case 0: case 0:
return &v.state return &v.state
@ -418,7 +628,7 @@ func file_message_proto_init() {
return nil return nil
} }
} }
file_message_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { file_cluster_message_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Command); i { switch v := v.(*Command); i {
case 0: case 0:
return &v.state return &v.state
@ -430,7 +640,19 @@ func file_message_proto_init() {
return nil return nil
} }
} }
file_message_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { file_cluster_message_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ResultsError); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_cluster_message_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CommandExecuteResponse); i { switch v := v.(*CommandExecuteResponse); i {
case 0: case 0:
return &v.state return &v.state
@ -442,7 +664,7 @@ func file_message_proto_init() {
return nil return nil
} }
} }
file_message_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { file_cluster_message_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CommandQueryResponse); i { switch v := v.(*CommandQueryResponse); i {
case 0: case 0:
return &v.state return &v.state
@ -455,7 +677,7 @@ func file_message_proto_init() {
} }
} }
} }
file_message_proto_msgTypes[1].OneofWrappers = []interface{}{ file_cluster_message_proto_msgTypes[2].OneofWrappers = []interface{}{
(*Command_ExecuteRequest)(nil), (*Command_ExecuteRequest)(nil),
(*Command_QueryRequest)(nil), (*Command_QueryRequest)(nil),
} }
@ -463,19 +685,19 @@ func file_message_proto_init() {
out := protoimpl.TypeBuilder{ out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{ File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_message_proto_rawDesc, RawDescriptor: file_cluster_message_proto_rawDesc,
NumEnums: 1, NumEnums: 2,
NumMessages: 4, NumMessages: 6,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },
GoTypes: file_message_proto_goTypes, GoTypes: file_cluster_message_proto_goTypes,
DependencyIndexes: file_message_proto_depIdxs, DependencyIndexes: file_cluster_message_proto_depIdxs,
EnumInfos: file_message_proto_enumTypes, EnumInfos: file_cluster_message_proto_enumTypes,
MessageInfos: file_message_proto_msgTypes, MessageInfos: file_cluster_message_proto_msgTypes,
}.Build() }.Build()
File_message_proto = out.File File_cluster_message_proto = out.File
file_message_proto_rawDesc = nil file_cluster_message_proto_rawDesc = nil
file_message_proto_goTypes = nil file_cluster_message_proto_goTypes = nil
file_message_proto_depIdxs = nil file_cluster_message_proto_depIdxs = nil
} }

@ -5,6 +5,11 @@ import "command/command.proto";
option go_package = "github.com/rqlite/rqlite/cluster"; option go_package = "github.com/rqlite/rqlite/cluster";
message Credentials {
string username = 1;
string password = 2;
}
message Address { message Address {
string url = 1; string url = 1;
} }
@ -22,14 +27,26 @@ message Command {
command.ExecuteRequest execute_request = 2; command.ExecuteRequest execute_request = 2;
command.QueryRequest query_request = 3; command.QueryRequest query_request = 3;
} }
Credentials credentials = 4;
}
message ResultsError {
enum Type {
RESULTS_ERROR_UNSPECIFIED = 0;
RESULTS_ERROR_UNAUTHORIZED = 1;
RESULTS_ERROR_NIL_QUERY_REQUEST =2;
}
Type type = 1;
string error = 2;
} }
message CommandExecuteResponse { message CommandExecuteResponse {
string error = 1; ResultsError error = 1;
repeated command.ExecuteResult results = 2; repeated command.ExecuteResult results = 2;
} }
message CommandQueryResponse { message CommandQueryResponse {
string error = 1; ResultsError error = 1;
repeated command.QueryRows rows = 2; repeated command.QueryRows rows = 2;
} }

@ -12,6 +12,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/rqlite/rqlite/auth"
"github.com/rqlite/rqlite/command" "github.com/rqlite/rqlite/command"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
@ -63,6 +64,12 @@ type Database interface {
Query(qr *command.QueryRequest) ([]*command.QueryRows, error) Query(qr *command.QueryRequest) ([]*command.QueryRows, error)
} }
// CredentialStore is the interface credential stores must support.
type CredentialStore interface {
// AA authenticates and checks authorization for the given perm.
AA(username, password, perm string) bool
}
// Transport is the interface the network layer must provide. // Transport is the interface the network layer must provide.
type Transport interface { type Transport interface {
net.Listener net.Listener
@ -76,6 +83,8 @@ type Service struct {
db Database // The queryable system. db Database // The queryable system.
credentialStore CredentialStore
mu sync.RWMutex mu sync.RWMutex
https bool // Serving HTTPS? https bool // Serving HTTPS?
apiAddr string // host:port this node serves the HTTP API. apiAddr string // host:port this node serves the HTTP API.
@ -84,12 +93,13 @@ type Service struct {
} }
// New returns a new instance of the cluster service // New returns a new instance of the cluster service
func New(tn Transport, db Database) *Service { func New(tn Transport, db Database, credentialStore CredentialStore) *Service {
return &Service{ return &Service{
tn: tn, tn: tn,
addr: tn.Addr(), addr: tn.Addr(),
db: db, db: db,
logger: log.New(os.Stderr, "[cluster] ", log.LstdFlags), logger: log.New(os.Stderr, "[cluster] ", log.LstdFlags),
credentialStore: credentialStore,
} }
} }
@ -167,6 +177,20 @@ func (s *Service) serve() error {
} }
} }
func (s *Service) checkCommandPerm(c *Command, perm string) bool {
if s.credentialStore == nil {
return true
}
username := ""
password := ""
if c.Credentials != nil {
username = c.Credentials.GetUsername()
password = c.Credentials.GetPassword()
}
return s.credentialStore.AA(username, password, perm)
}
func (s *Service) handleConn(conn net.Conn) { func (s *Service) handleConn(conn net.Conn) {
defer conn.Close() defer conn.Close()
@ -211,14 +235,24 @@ func (s *Service) handleConn(conn net.Conn) {
stats.Add(numExecuteRequest, 1) stats.Add(numExecuteRequest, 1)
resp := &CommandExecuteResponse{} resp := &CommandExecuteResponse{}
er := c.GetExecuteRequest() er := c.GetExecuteRequest()
if er == nil { if er == nil {
resp.Error = "ExecuteRequest is nil" resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_NIL_QUERY_REQUEST,
Error: "Query Request is nil",
}
} else if !s.checkCommandPerm(c, auth.PermExecute) {
resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_UNAUTHORIZED,
Error: "Unauthorized",
}
} else { } else {
res, err := s.db.Execute(er) res, err := s.db.Execute(er)
if err != nil { if err != nil {
resp.Error = err.Error() resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_UNSPECIFIED,
Error: err.Error(),
}
} else { } else {
resp.Results = make([]*command.ExecuteResult, len(res)) resp.Results = make([]*command.ExecuteResult, len(res))
for i := range res { for i := range res {
@ -244,11 +278,22 @@ func (s *Service) handleConn(conn net.Conn) {
qr := c.GetQueryRequest() qr := c.GetQueryRequest()
if qr == nil { if qr == nil {
resp.Error = "QueryRequest is nil" resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_NIL_QUERY_REQUEST,
Error: "Query Request is nil",
}
} else if !s.checkCommandPerm(c, auth.PermQuery) {
resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_UNAUTHORIZED,
Error: "Unauthorized",
}
} else { } else {
res, err := s.db.Query(qr) res, err := s.db.Query(qr)
if err != nil { if err != nil {
resp.Error = err.Error() resp.Error = &ResultsError{
Type: ResultsError_RESULTS_ERROR_UNSPECIFIED,
Error: err.Error(),
}
} else { } else {
resp.Rows = make([]*command.QueryRows, len(res)) resp.Rows = make([]*command.QueryRows, len(res))
for i := range res { for i := range res {

@ -16,12 +16,18 @@ import (
const shortWait = 1 * time.Second const shortWait = 1 * time.Second
const longWait = 5 * time.Second const longWait = 5 * time.Second
const (
NO_USERNAME = ""
NO_PASSWORD = ""
)
func Test_ServiceExecute(t *testing.T) { func Test_ServiceExecute(t *testing.T) {
ln, mux := mustNewMux() ln, mux := mustNewMux()
go mux.Serve() go mux.Serve()
tn := mux.Listen(1) // Could be any byte value. tn := mux.Listen(1) // Could be any byte value.
db := mustNewMockDatabase() db := mustNewMockDatabase()
s := New(tn, db) cred := mustNewMockCredentialStore()
s := New(tn, db, cred)
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -39,7 +45,7 @@ func Test_ServiceExecute(t *testing.T) {
} }
return nil, errors.New("execute failed") return nil, errors.New("execute failed")
} }
_, err := c.Execute(executeRequestFromString("some SQL"), s.Addr(), longWait) _, err := c.Execute(executeRequestFromString("some SQL"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err == nil { if err == nil {
t.Fatalf("client failed to report error") t.Fatalf("client failed to report error")
} }
@ -57,7 +63,7 @@ func Test_ServiceExecute(t *testing.T) {
} }
return []*command.ExecuteResult{result}, nil return []*command.ExecuteResult{result}, nil
} }
res, err := c.Execute(executeRequestFromString("some SQL"), s.Addr(), longWait) res, err := c.Execute(executeRequestFromString("some SQL"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err != nil { if err != nil {
t.Fatalf("failed to execute query: %s", err.Error()) t.Fatalf("failed to execute query: %s", err.Error())
} }
@ -74,7 +80,7 @@ func Test_ServiceExecute(t *testing.T) {
} }
return []*command.ExecuteResult{result}, nil return []*command.ExecuteResult{result}, nil
} }
res, err = c.Execute(executeRequestFromString("some SQL"), s.Addr(), longWait) res, err = c.Execute(executeRequestFromString("some SQL"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err != nil { if err != nil {
t.Fatalf("failed to execute: %s", err.Error()) t.Fatalf("failed to execute: %s", err.Error())
} }
@ -86,7 +92,7 @@ func Test_ServiceExecute(t *testing.T) {
time.Sleep(longWait) time.Sleep(longWait)
return nil, nil return nil, nil
} }
_, err = c.Execute(executeRequestFromString("some SQL"), s.Addr(), shortWait) _, err = c.Execute(executeRequestFromString("some SQL"), s.Addr(), "", "", shortWait)
if err == nil { if err == nil {
t.Fatalf("failed to receive expected error") t.Fatalf("failed to receive expected error")
} }
@ -108,7 +114,8 @@ func Test_ServiceQuery(t *testing.T) {
go mux.Serve() go mux.Serve()
tn := mux.Listen(1) // Could be any byte value. tn := mux.Listen(1) // Could be any byte value.
db := mustNewMockDatabase() db := mustNewMockDatabase()
s := New(tn, db) cred := mustNewMockCredentialStore()
s := New(tn, db, cred)
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -126,7 +133,7 @@ func Test_ServiceQuery(t *testing.T) {
} }
return nil, errors.New("query failed") return nil, errors.New("query failed")
} }
_, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), longWait) _, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err == nil { if err == nil {
t.Fatalf("client failed to report error") t.Fatalf("client failed to report error")
} }
@ -144,7 +151,7 @@ func Test_ServiceQuery(t *testing.T) {
} }
return []*command.QueryRows{rows}, nil return []*command.QueryRows{rows}, nil
} }
res, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), longWait) res, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err != nil { if err != nil {
t.Fatalf("failed to query: %s", err.Error()) t.Fatalf("failed to query: %s", err.Error())
} }
@ -161,7 +168,7 @@ func Test_ServiceQuery(t *testing.T) {
} }
return []*command.QueryRows{rows}, nil return []*command.QueryRows{rows}, nil
} }
res, err = c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), longWait) res, err = c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err != nil { if err != nil {
t.Fatalf("failed to query: %s", err.Error()) t.Fatalf("failed to query: %s", err.Error())
} }
@ -173,7 +180,7 @@ func Test_ServiceQuery(t *testing.T) {
time.Sleep(longWait) time.Sleep(longWait)
return nil, nil return nil, nil
} }
_, err = c.Query(queryRequestFromString("some SQL"), s.Addr(), shortWait) _, err = c.Query(queryRequestFromString("some SQL"), s.Addr(), NO_USERNAME, NO_PASSWORD, shortWait)
if err == nil { if err == nil {
t.Fatalf("failed to receive expected error") t.Fatalf("failed to receive expected error")
} }
@ -197,7 +204,8 @@ func Test_ServiceQueryLarge(t *testing.T) {
go mux.Serve() go mux.Serve()
tn := mux.Listen(1) // Could be any byte value. tn := mux.Listen(1) // Could be any byte value.
db := mustNewMockDatabase() db := mustNewMockDatabase()
s := New(tn, db) cred := mustNewMockCredentialStore()
s := New(tn, db, cred)
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -234,7 +242,7 @@ func Test_ServiceQueryLarge(t *testing.T) {
} }
return []*command.QueryRows{rows}, nil return []*command.QueryRows{rows}, nil
} }
res, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), longWait) res, err := c.Query(queryRequestFromString("SELECT * FROM foo"), s.Addr(), NO_USERNAME, NO_PASSWORD, longWait)
if err != nil { if err != nil {
t.Fatalf("failed to query: %s", err.Error()) t.Fatalf("failed to query: %s", err.Error())
} }

@ -16,7 +16,7 @@ func Test_NewServiceSetGetNodeAPIAddrMuxed(t *testing.T) {
go mux.Serve() go mux.Serve()
tn := mux.Listen(1) // Could be any byte value. tn := mux.Listen(1) // Could be any byte value.
s := New(tn, mustNewMockDatabase()) s := New(tn, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -50,7 +50,7 @@ func Test_NewServiceSetGetNodeAPIAddrMuxedTLS(t *testing.T) {
go mux.Serve() go mux.Serve()
tn := mux.Listen(1) // Could be any byte value. tn := mux.Listen(1) // Could be any byte value.
s := New(tn, mustNewMockDatabase()) s := New(tn, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }

@ -2,6 +2,7 @@ package cluster
import ( import (
"crypto/tls" "crypto/tls"
"fmt"
"net" "net"
"os" "os"
"testing" "testing"
@ -13,7 +14,7 @@ import (
func Test_NewServiceOpenClose(t *testing.T) { func Test_NewServiceOpenClose(t *testing.T) {
ml := mustNewMockTransport() ml := mustNewMockTransport()
s := New(ml, mustNewMockDatabase()) s := New(ml, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -31,7 +32,7 @@ func Test_NewServiceOpenClose(t *testing.T) {
func Test_NewServiceSetGetAPIAddr(t *testing.T) { func Test_NewServiceSetGetAPIAddr(t *testing.T) {
ml := mustNewMockTransport() ml := mustNewMockTransport()
s := New(ml, mustNewMockDatabase()) s := New(ml, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -52,7 +53,7 @@ func Test_NewServiceSetGetAPIAddr(t *testing.T) {
func Test_NewServiceSetGetNodeAPIAddr(t *testing.T) { func Test_NewServiceSetGetNodeAPIAddr(t *testing.T) {
ml := mustNewMockTransport() ml := mustNewMockTransport()
s := New(ml, mustNewMockDatabase()) s := New(ml, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -97,7 +98,7 @@ func Test_NewServiceSetGetNodeAPIAddr(t *testing.T) {
func Test_NewServiceSetGetNodeAPIAddrLocal(t *testing.T) { func Test_NewServiceSetGetNodeAPIAddrLocal(t *testing.T) {
ml := mustNewMockTransport() ml := mustNewMockTransport()
s := New(ml, mustNewMockDatabase()) s := New(ml, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -134,7 +135,7 @@ func Test_NewServiceSetGetNodeAPIAddrLocal(t *testing.T) {
func Test_NewServiceSetGetNodeAPIAddrTLS(t *testing.T) { func Test_NewServiceSetGetNodeAPIAddrTLS(t *testing.T) {
ml := mustNewMockTLSTransport() ml := mustNewMockTLSTransport()
s := New(ml, mustNewMockDatabase()) s := New(ml, mustNewMockDatabase(), mustNewMockCredentialStore())
if s == nil { if s == nil {
t.Fatalf("failed to create cluster service") t.Fatalf("failed to create cluster service")
} }
@ -170,6 +171,82 @@ func Test_NewServiceSetGetNodeAPIAddrTLS(t *testing.T) {
} }
} }
func Test_NewServiceTestExecuteQueryAuthNoCredentials(t *testing.T) {
ml := mustNewMockTransport()
db := mustNewMockDatabase()
// Test that for a cluster with no credential store configed
// all users are authed for both operations
var c CredentialStore = nil
c = nil
s := New(ml, db, c)
if s == nil {
t.Fatalf("failed to create cluster service")
}
if err := s.Open(); err != nil {
t.Fatalf("failed to open cluster service")
}
cl := NewClient(ml, 30*time.Second)
if err := cl.SetLocal(s.Addr(), s); err != nil {
t.Fatalf("failed to set cluster client local parameters: %s", err)
}
er := &command.ExecuteRequest{}
_, err := cl.Execute(er, s.Addr(), NO_USERNAME, NO_PASSWORD, 5*time.Second)
if err != nil {
t.Fatal(err)
}
qr := &command.QueryRequest{}
_, err = cl.Query(qr, s.Addr(), NO_USERNAME, NO_PASSWORD, 5*time.Second)
if err != nil {
t.Fatal(err)
}
}
func Test_NewServiceTestExecuteQueryAuth(t *testing.T) {
ml := mustNewMockTransport()
db := mustNewMockDatabase()
// Test that for a cluster with a credential store configed
// users with execute permissions can execute and users with
// query permissions can query and can't if they don't have those
// permissions
c := mustNewMockCredentialStoreBob()
s := New(ml, db, c)
if s == nil {
t.Fatalf("failed to create cluster service")
}
if err := s.Open(); err != nil {
t.Fatalf("failed to open cluster service")
}
cl := NewClient(ml, 30*time.Second)
if err := cl.SetLocal(s.Addr(), s); err != nil {
t.Fatalf("failed to set cluster client local parameters: %s", err)
}
er := &command.ExecuteRequest{}
_, err := cl.Execute(er, s.Addr(), "alice", "secret1", 5*time.Second)
if err != nil {
t.Fatal("alice improperly unauthorized to execute")
}
_, err = cl.Execute(er, s.Addr(), "bob", "secret1", 5*time.Second)
if err == nil {
t.Fatal("bob improperly authorized to execute")
}
qr := &command.QueryRequest{}
_, err = cl.Query(qr, s.Addr(), "bob", "secret1", 5*time.Second)
if err != nil {
fmt.Println(err)
t.Fatal("bob improperly unauthorized to query")
}
_, err = cl.Query(qr, s.Addr(), "alice", "secret1", 5*time.Second)
if err == nil {
t.Fatal("alice improperly authorized to query")
}
}
type mockTransport struct { type mockTransport struct {
tn net.Listener tn net.Listener
remoteEncrypted bool remoteEncrypted bool
@ -236,7 +313,13 @@ func (m *mockDatabase) Query(qr *command.QueryRequest) ([]*command.QueryRows, er
} }
func mustNewMockDatabase() *mockDatabase { func mustNewMockDatabase() *mockDatabase {
return &mockDatabase{} e := func(er *command.ExecuteRequest) ([]*command.ExecuteResult, error) {
return []*command.ExecuteResult{}, nil
}
q := func(er *command.QueryRequest) ([]*command.QueryRows, error) {
return []*command.QueryRows{}, nil
}
return &mockDatabase{executeFn: e, queryFn: q}
} }
func mustCreateTLSConfig() *tls.Config { func mustCreateTLSConfig() *tls.Config {
@ -258,3 +341,36 @@ func mustCreateTLSConfig() *tls.Config {
return config return config
} }
type mockCredentialStore struct {
HasPermOK bool
aaFunc func(username, password, perm string) bool
}
func (m *mockCredentialStore) AA(username, password, perm string) bool {
if m == nil {
return true
}
if m.aaFunc != nil {
return m.aaFunc(username, password, perm)
}
return m.HasPermOK
}
func mustNewMockCredentialStore() *mockCredentialStore {
return &mockCredentialStore{HasPermOK: true}
}
func mustNewMockCredentialStoreBob() *mockCredentialStore {
f := func(username string, password string, perm string) bool {
fmt.Println(username, password, perm)
if username == "alice" && password == "secret1" && perm == "execute" {
return true
} else if username == "bob" && password == "secret1" && perm == "query" {
return true
}
return false
}
return &mockCredentialStore{aaFunc: f}
}

@ -102,7 +102,7 @@ func main() {
} }
// Create cluster service now, so nodes will be able to learn information about each other. // Create cluster service now, so nodes will be able to learn information about each other.
clstr, err := clusterService(cfg, mux.Listen(cluster.MuxClusterHeader), str) clstr, err := clusterService(cfg, mux.Listen(cluster.MuxClusterHeader), str, credStr)
if err != nil { if err != nil {
log.Fatalf("failed to create cluster service: %s", err.Error()) log.Fatalf("failed to create cluster service: %s", err.Error())
} }
@ -310,8 +310,8 @@ func credentialStore(cfg *Config) (*auth.CredentialsStore, error) {
return cs, nil return cs, nil
} }
func clusterService(cfg *Config, tn cluster.Transport, db cluster.Database) (*cluster.Service, error) { func clusterService(cfg *Config, tn cluster.Transport, db cluster.Database, credStr *auth.CredentialsStore) (*cluster.Service, error) {
c := cluster.New(tn, db) c := cluster.New(tn, db, credStr)
c.SetAPIAddr(cfg.HTTPAdv) c.SetAPIAddr(cfg.HTTPAdv)
c.EnableHTTPS(cfg.X509Cert != "" && cfg.X509Key != "") // Conditions met for an HTTPS API c.EnableHTTPS(cfg.X509Cert != "" && cfg.X509Key != "") // Conditions met for an HTTPS API

@ -38,6 +38,16 @@ var (
ErrUserInfoExists = errors.New("userinfo exists") ErrUserInfoExists = errors.New("userinfo exists")
) )
const (
NO_USERNAME = ""
NO_PASSSWORD = ""
)
type ResultsError interface {
Error() string
IsAuthorized() bool
}
// Database is the interface any queryable system must implement // Database is the interface any queryable system must implement
type Database interface { type Database interface {
// Execute executes a slice of queries, each of which is not expected // Execute executes a slice of queries, each of which is not expected
@ -88,10 +98,10 @@ type Cluster interface {
GetNodeAPIAddr(nodeAddr string, timeout time.Duration) (string, error) GetNodeAPIAddr(nodeAddr string, timeout time.Duration) (string, error)
// Execute performs an Execute Request on a remote node. // Execute performs an Execute Request on a remote node.
Execute(er *command.ExecuteRequest, nodeAddr string, timeout time.Duration) ([]*command.ExecuteResult, error) Execute(er *command.ExecuteRequest, nodeAddr string, username string, password string, timeout time.Duration) ([]*command.ExecuteResult, error)
// Query performs an Query Request on a remote node. // Query performs an Query Request on a remote node.
Query(qr *command.QueryRequest, nodeAddr string, timeout time.Duration) ([]*command.QueryRows, error) Query(qr *command.QueryRequest, nodeAddr string, username string, password string, timeout time.Duration) ([]*command.QueryRows, error)
// Stats returns stats on the Cluster. // Stats returns stats on the Cluster.
Stats() (map[string]interface{}, error) Stats() (map[string]interface{}, error)
@ -1091,7 +1101,17 @@ func (s *Service) execute(w http.ResponseWriter, r *http.Request) {
http.Error(w, ErrLeaderNotFound.Error(), http.StatusServiceUnavailable) http.Error(w, ErrLeaderNotFound.Error(), http.StatusServiceUnavailable)
return return
} }
results, resultsErr = s.cluster.Execute(er, addr, timeout)
username, password, ok := r.BasicAuth()
if !ok {
username = ""
}
results, resultsErr = s.cluster.Execute(er, addr, username, password, timeout)
if resultsErr != nil && resultsErr.Error() == "Unauthorized" {
w.WriteHeader(http.StatusUnauthorized)
return
}
stats.Add(numRemoteExecutions, 1) stats.Add(numRemoteExecutions, 1)
w.Header().Add(ServedByHTTPHeader, addr) w.Header().Add(ServedByHTTPHeader, addr)
} }
@ -1180,7 +1200,15 @@ func (s *Service) handleQuery(w http.ResponseWriter, r *http.Request) {
http.Error(w, ErrLeaderNotFound.Error(), http.StatusServiceUnavailable) http.Error(w, ErrLeaderNotFound.Error(), http.StatusServiceUnavailable)
return return
} }
results, resultsErr = s.cluster.Query(qr, addr, timeout) username, password, ok := r.BasicAuth()
if !ok {
username = ""
}
results, resultsErr = s.cluster.Query(qr, addr, username, password, timeout)
if resultsErr != nil && resultsErr.Error() == "Unauthorized" {
w.WriteHeader(http.StatusUnauthorized)
return
}
stats.Add(numRemoteQueries, 1) stats.Add(numRemoteQueries, 1)
w.Header().Add(ServedByHTTPHeader, addr) w.Header().Add(ServedByHTTPHeader, addr)
} }
@ -1317,7 +1345,7 @@ func (s *Service) runQueue() {
time.Sleep(retryDelay) time.Sleep(retryDelay)
continue continue
} }
_, err = s.cluster.Execute(er, addr, defaultTimeout) _, err = s.cluster.Execute(er, addr, NO_USERNAME, NO_PASSSWORD, defaultTimeout)
if err != nil { if err != nil {
s.logger.Printf("execute queue write failed for sequence number %d: %s", s.logger.Printf("execute queue write failed for sequence number %d: %s",
req.SequenceNumber, err.Error()) req.SequenceNumber, err.Error())

@ -223,9 +223,10 @@ func Test_RemoveBasicAuth(t *testing.T) {
} }
func Test_NewService(t *testing.T) { func Test_NewService(t *testing.T) {
m := &MockStore{} store := &MockStore{}
c := &mockClusterService{} cluster := &mockClusterService{}
s := New("127.0.0.1:0", m, c, nil) cred := &mockCredentialStore{HasPermOK: true}
s := New("127.0.0.1:0", store, cluster, cred)
if s == nil { if s == nil {
t.Fatalf("failed to create new service") t.Fatalf("failed to create new service")
} }
@ -1197,14 +1198,14 @@ func (m *mockClusterService) GetNodeAPIAddr(a string, t time.Duration) (string,
return m.apiAddr, nil return m.apiAddr, nil
} }
func (m *mockClusterService) Execute(er *command.ExecuteRequest, addr string, t time.Duration) ([]*command.ExecuteResult, error) { func (m *mockClusterService) Execute(er *command.ExecuteRequest, addr string, username string, password string, t time.Duration) ([]*command.ExecuteResult, error) {
if m.executeFn != nil { if m.executeFn != nil {
return m.executeFn(er, addr, t) return m.executeFn(er, addr, t)
} }
return nil, nil return nil, nil
} }
func (m *mockClusterService) Query(qr *command.QueryRequest, addr string, t time.Duration) ([]*command.QueryRows, error) { func (m *mockClusterService) Query(qr *command.QueryRequest, addr string, username string, password string, t time.Duration) ([]*command.QueryRows, error) {
if m.queryFn != nil { if m.queryFn != nil {
return m.queryFn(qr, addr, t) return m.queryFn(qr, addr, t)
} }

@ -594,7 +594,7 @@ func mustNodeEncryptedOnDisk(dir string, enableSingle, httpEncrypt bool, mux *tc
node.RaftAddr = node.Store.Addr() node.RaftAddr = node.Store.Addr()
node.ID = node.Store.ID() node.ID = node.Store.ID()
clstr := cluster.New(mux.Listen(cluster.MuxClusterHeader), node.Store) clstr := cluster.New(mux.Listen(cluster.MuxClusterHeader), node.Store, mustNewMockCredentialStore())
if err := clstr.Open(); err != nil { if err := clstr.Open(); err != nil {
panic("failed to open Cluster service)") panic("failed to open Cluster service)")
} }
@ -883,3 +883,23 @@ func copyDir(src string, dst string) (err error) {
return return
} }
type mockCredentialStore struct {
HasPermOK bool
aaFunc func(username, password, perm string) bool
}
func (m *mockCredentialStore) AA(username, password, perm string) bool {
if m == nil {
return true
}
if m.aaFunc != nil {
return m.aaFunc(username, password, perm)
}
return m.HasPermOK
}
func mustNewMockCredentialStore() *mockCredentialStore {
return &mockCredentialStore{HasPermOK: true}
}

@ -30,7 +30,7 @@ func Test_StoreClientSideBySide(t *testing.T) {
if exp, got := "[{}]", asJSON(res); exp != got { if exp, got := "[{}]", asJSON(res); exp != got {
t.Fatalf("unexpected results, expt %s, got %s", exp, got) t.Fatalf("unexpected results, expt %s, got %s", exp, got)
} }
res, err = client.Execute(executeRequestFromString("CREATE TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"), leaderAddr, shortWait) res, err = client.Execute(executeRequestFromString("CREATE TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"), leaderAddr, "", "", shortWait)
if err != nil { if err != nil {
t.Fatalf("failed to execute via remote: %s", err.Error()) t.Fatalf("failed to execute via remote: %s", err.Error())
} }
@ -45,7 +45,7 @@ func Test_StoreClientSideBySide(t *testing.T) {
if exp, got := `[{"last_insert_id":1,"rows_affected":1}]`, asJSON(res); exp != got { if exp, got := `[{"last_insert_id":1,"rows_affected":1}]`, asJSON(res); exp != got {
t.Fatalf("unexpected results, expt %s, got %s", exp, got) t.Fatalf("unexpected results, expt %s, got %s", exp, got)
} }
res, err = client.Execute(executeRequestFromString(`INSERT INTO bar(name) VALUES("fiona")`), leaderAddr, shortWait) res, err = client.Execute(executeRequestFromString(`INSERT INTO bar(name) VALUES("fiona")`), leaderAddr, "", "", shortWait)
if err != nil { if err != nil {
t.Fatalf("failed to execute via remote: %s", err.Error()) t.Fatalf("failed to execute via remote: %s", err.Error())
} }
@ -68,14 +68,14 @@ func Test_StoreClientSideBySide(t *testing.T) {
t.Fatalf("unexpected results, expt %s, got %s", exp, got) t.Fatalf("unexpected results, expt %s, got %s", exp, got)
} }
rows, err = client.Query(queryRequestFromString(`SELECT * FROM foo`), leaderAddr, shortWait) rows, err = client.Query(queryRequestFromString(`SELECT * FROM foo`), leaderAddr, "", "", shortWait)
if err != nil { if err != nil {
t.Fatalf("failed to query via remote: %s", err.Error()) t.Fatalf("failed to query via remote: %s", err.Error())
} }
if exp, got := `[{"columns":["id","name"],"types":["integer","text"],"values":[[1,"fiona"]]}]`, asJSON(rows); exp != got { if exp, got := `[{"columns":["id","name"],"types":["integer","text"],"values":[[1,"fiona"]]}]`, asJSON(rows); exp != got {
t.Fatalf("unexpected results, expt %s, got %s", exp, got) t.Fatalf("unexpected results, expt %s, got %s", exp, got)
} }
rows, err = client.Query(queryRequestFromString(`SELECT * FROM bar`), leaderAddr, shortWait) rows, err = client.Query(queryRequestFromString(`SELECT * FROM bar`), leaderAddr, "", "", shortWait)
if err != nil { if err != nil {
t.Fatalf("failed to query via remote: %s", err.Error()) t.Fatalf("failed to query via remote: %s", err.Error())
} }
@ -90,7 +90,7 @@ func Test_StoreClientSideBySide(t *testing.T) {
if exp, got := `[{"error":"no such table: qux"}]`, asJSON(rows); exp != got { if exp, got := `[{"error":"no such table: qux"}]`, asJSON(rows); exp != got {
t.Fatalf("unexpected results, expt %s, got %s", exp, got) t.Fatalf("unexpected results, expt %s, got %s", exp, got)
} }
rows, err = client.Query(queryRequestFromString(`SELECT * FROM qux`), leaderAddr, shortWait) rows, err = client.Query(queryRequestFromString(`SELECT * FROM qux`), leaderAddr, "", "", shortWait)
if err != nil { if err != nil {
t.Fatalf("failed to query via remote: %s", err.Error()) t.Fatalf("failed to query via remote: %s", err.Error())
} }

Loading…
Cancel
Save