Add JWT shared secret influxdb auth
Refactor --new-sources to simplify adding shared secretspull/10616/head
parent
fa9e118686
commit
8dc08278bd
|
@ -17,6 +17,7 @@ func MarshalSource(s chronograf.Source) ([]byte, error) {
|
|||
Type: s.Type,
|
||||
Username: s.Username,
|
||||
Password: s.Password,
|
||||
SharedSecret: s.SharedSecret,
|
||||
URL: s.URL,
|
||||
MetaURL: s.MetaURL,
|
||||
InsecureSkipVerify: s.InsecureSkipVerify,
|
||||
|
@ -37,6 +38,7 @@ func UnmarshalSource(data []byte, s *chronograf.Source) error {
|
|||
s.Type = pb.Type
|
||||
s.Username = pb.Username
|
||||
s.Password = pb.Password
|
||||
s.SharedSecret = pb.SharedSecret
|
||||
s.URL = pb.URL
|
||||
s.MetaURL = pb.MetaURL
|
||||
s.InsecureSkipVerify = pb.InsecureSkipVerify
|
||||
|
|
|
@ -51,6 +51,7 @@ type Source struct {
|
|||
Telegraf string `protobuf:"bytes,8,opt,name=Telegraf,proto3" json:"Telegraf,omitempty"`
|
||||
InsecureSkipVerify bool `protobuf:"varint,9,opt,name=InsecureSkipVerify,proto3" json:"InsecureSkipVerify,omitempty"`
|
||||
MetaURL string `protobuf:"bytes,10,opt,name=MetaURL,proto3" json:"MetaURL,omitempty"`
|
||||
SharedSecret string `protobuf:"bytes,11,opt,name=SharedSecret,proto3" json:"SharedSecret,omitempty"`
|
||||
}
|
||||
|
||||
func (m *Source) Reset() { *m = Source{} }
|
||||
|
@ -293,59 +294,60 @@ func init() {
|
|||
func init() { proto.RegisterFile("internal.proto", fileDescriptorInternal) }
|
||||
|
||||
var fileDescriptorInternal = []byte{
|
||||
// 858 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xdd, 0x6e, 0xe3, 0x44,
|
||||
0x14, 0xd6, 0xc4, 0x76, 0x62, 0x9f, 0xee, 0x16, 0x34, 0x5a, 0xb1, 0x06, 0x6e, 0x22, 0x0b, 0xa4,
|
||||
0x82, 0x44, 0x41, 0xec, 0x13, 0xb4, 0xb5, 0x84, 0x42, 0xbb, 0x4b, 0x99, 0xb4, 0xe5, 0x0a, 0xad,
|
||||
0x26, 0xc9, 0x49, 0x6b, 0xed, 0x24, 0x36, 0x63, 0xbb, 0x59, 0xbf, 0x02, 0x57, 0x3c, 0x01, 0x12,
|
||||
0x12, 0x57, 0x5c, 0xf2, 0x02, 0x3c, 0x04, 0x2f, 0x84, 0xce, 0xcc, 0xf8, 0x27, 0x6c, 0x41, 0x7b,
|
||||
0xb5, 0x77, 0xf3, 0x9d, 0x33, 0xf9, 0xe6, 0xfc, 0x7c, 0x9f, 0x03, 0x87, 0xd9, 0xb6, 0x42, 0xbd,
|
||||
0x95, 0xea, 0xb8, 0xd0, 0x79, 0x95, 0xf3, 0xb0, 0xc5, 0xc9, 0xcf, 0x23, 0x18, 0xcf, 0xf3, 0x5a,
|
||||
0x2f, 0x91, 0x1f, 0xc2, 0x68, 0x96, 0xc6, 0x6c, 0xca, 0x8e, 0x3c, 0x31, 0x9a, 0xa5, 0x9c, 0x83,
|
||||
0xff, 0x42, 0x6e, 0x30, 0x1e, 0x4d, 0xd9, 0x51, 0x24, 0xcc, 0x99, 0x62, 0x57, 0x4d, 0x81, 0xb1,
|
||||
0x67, 0x63, 0x74, 0xe6, 0x1f, 0x41, 0x78, 0x5d, 0x12, 0xdb, 0x06, 0x63, 0xdf, 0xc4, 0x3b, 0x4c,
|
||||
0xb9, 0x4b, 0x59, 0x96, 0xbb, 0x5c, 0xaf, 0xe2, 0xc0, 0xe6, 0x5a, 0xcc, 0xdf, 0x07, 0xef, 0x5a,
|
||||
0x5c, 0xc4, 0x63, 0x13, 0xa6, 0x23, 0x8f, 0x61, 0x92, 0xe2, 0x5a, 0xd6, 0xaa, 0x8a, 0x27, 0x53,
|
||||
0x76, 0x14, 0x8a, 0x16, 0x12, 0xcf, 0x15, 0x2a, 0xbc, 0xd5, 0x72, 0x1d, 0x87, 0x96, 0xa7, 0xc5,
|
||||
0xfc, 0x18, 0xf8, 0x6c, 0x5b, 0xe2, 0xb2, 0xd6, 0x38, 0x7f, 0x95, 0x15, 0x37, 0xa8, 0xb3, 0x75,
|
||||
0x13, 0x47, 0x86, 0xe0, 0x81, 0x0c, 0xbd, 0xf2, 0x1c, 0x2b, 0x49, 0x6f, 0x83, 0xa1, 0x6a, 0x61,
|
||||
0xf2, 0x0b, 0x83, 0x28, 0x95, 0xe5, 0xdd, 0x22, 0x97, 0x7a, 0xf5, 0x56, 0xf3, 0xf8, 0x02, 0x82,
|
||||
0x25, 0x2a, 0x55, 0xc6, 0xde, 0xd4, 0x3b, 0x3a, 0xf8, 0xfa, 0xe9, 0x71, 0x37, 0xe8, 0x8e, 0xe7,
|
||||
0x0c, 0x95, 0x12, 0xf6, 0x16, 0xff, 0x0a, 0xa2, 0x0a, 0x37, 0x85, 0x92, 0x15, 0x96, 0xb1, 0x6f,
|
||||
0x7e, 0xc2, 0xfb, 0x9f, 0x5c, 0xb9, 0x94, 0xe8, 0x2f, 0x25, 0x7f, 0x30, 0x78, 0xbc, 0x47, 0xc5,
|
||||
0x1f, 0x01, 0x7b, 0x6d, 0xaa, 0x0a, 0x04, 0x7b, 0x4d, 0xa8, 0x31, 0x15, 0x05, 0x82, 0x35, 0x84,
|
||||
0x76, 0x66, 0x37, 0x81, 0x60, 0x3b, 0x42, 0x77, 0x66, 0x23, 0x81, 0x60, 0x77, 0xfc, 0x33, 0x98,
|
||||
0xfc, 0x54, 0xa3, 0xce, 0xb0, 0x8c, 0x03, 0xf3, 0xf2, 0x7b, 0xfd, 0xcb, 0xdf, 0xd7, 0xa8, 0x1b,
|
||||
0xd1, 0xe6, 0xa9, 0x53, 0xb3, 0x4d, 0xbb, 0x1a, 0x73, 0xa6, 0x58, 0x45, 0x9b, 0x9f, 0xd8, 0x18,
|
||||
0x9d, 0xdd, 0x84, 0xec, 0x3e, 0x46, 0xb3, 0x34, 0xf9, 0x8b, 0xd1, 0x9a, 0x6c, 0xe9, 0x83, 0xf1,
|
||||
0x99, 0x24, 0xff, 0x10, 0x42, 0x6a, 0xeb, 0xe5, 0xbd, 0xd4, 0x6e, 0x84, 0x13, 0xc2, 0x37, 0x52,
|
||||
0xf3, 0x2f, 0x61, 0x7c, 0x2f, 0x55, 0x8d, 0x0f, 0x8c, 0xb1, 0xa5, 0xbb, 0xa1, 0xbc, 0x70, 0xd7,
|
||||
0xba, 0x62, 0xfc, 0x41, 0x31, 0x4f, 0x20, 0x50, 0x72, 0x81, 0xca, 0xe9, 0xcc, 0x02, 0x5a, 0x10,
|
||||
0x75, 0xd5, 0x98, 0x5e, 0x1e, 0x64, 0xb6, 0xbd, 0xdb, 0x5b, 0xc9, 0x35, 0x3c, 0xde, 0x7b, 0xb1,
|
||||
0x7b, 0x89, 0xed, 0xbf, 0x64, 0xea, 0x70, 0x6d, 0x58, 0x40, 0x12, 0x2d, 0x51, 0xe1, 0xb2, 0xc2,
|
||||
0x95, 0x59, 0x41, 0x28, 0x3a, 0x9c, 0xfc, 0xc6, 0x7a, 0x5e, 0xf3, 0x1e, 0x89, 0x70, 0x99, 0x6f,
|
||||
0x36, 0x72, 0xbb, 0x72, 0xd4, 0x2d, 0xa4, 0xb9, 0xad, 0x16, 0x8e, 0x7a, 0xb4, 0x5a, 0x10, 0xd6,
|
||||
0x85, 0x33, 0xdc, 0x48, 0x17, 0x7c, 0x0a, 0x07, 0x1b, 0x94, 0x65, 0xad, 0x71, 0x83, 0xdb, 0xca,
|
||||
0x8d, 0x60, 0x18, 0xe2, 0x4f, 0x61, 0x52, 0xc9, 0xdb, 0x97, 0xaf, 0xb0, 0x71, 0xb3, 0x18, 0x57,
|
||||
0xf2, 0xf6, 0x1c, 0x1b, 0xfe, 0x31, 0x44, 0xeb, 0x0c, 0xd5, 0xca, 0xa4, 0xec, 0x72, 0x43, 0x13,
|
||||
0x38, 0xc7, 0x26, 0xf9, 0x9d, 0xc1, 0x78, 0x8e, 0xfa, 0x1e, 0xf5, 0x5b, 0x29, 0x7f, 0xe8, 0x7a,
|
||||
0xef, 0x7f, 0x5c, 0xef, 0x3f, 0xec, 0xfa, 0xa0, 0x77, 0xfd, 0x13, 0x08, 0xe6, 0x7a, 0x39, 0x4b,
|
||||
0x4d, 0x45, 0x9e, 0xb0, 0x80, 0x7f, 0x00, 0xe3, 0x93, 0x65, 0x95, 0xdd, 0xa3, 0xfb, 0x14, 0x38,
|
||||
0x94, 0xfc, 0xca, 0x60, 0x7c, 0x21, 0x9b, 0xbc, 0xae, 0xde, 0x50, 0xd8, 0x14, 0x0e, 0x4e, 0x8a,
|
||||
0x42, 0x65, 0x4b, 0x59, 0x65, 0xf9, 0xd6, 0x55, 0x3b, 0x0c, 0xd1, 0x8d, 0xe7, 0x83, 0xd9, 0xd9,
|
||||
0xba, 0x87, 0x21, 0xfe, 0x09, 0x04, 0x67, 0xc6, 0xd0, 0xd6, 0x9d, 0x87, 0xbd, 0x5e, 0xac, 0x8f,
|
||||
0x4d, 0x92, 0x1a, 0x3c, 0xa9, 0xab, 0x7c, 0xad, 0xf2, 0x9d, 0xe9, 0x24, 0x14, 0x1d, 0x4e, 0xfe,
|
||||
0x66, 0xe0, 0xbf, 0x2b, 0xa3, 0x3e, 0x02, 0x96, 0xb9, 0x45, 0xb2, 0xac, 0xb3, 0xed, 0x64, 0x60,
|
||||
0xdb, 0x18, 0x26, 0x8d, 0x96, 0xdb, 0x5b, 0x2c, 0xe3, 0x70, 0xea, 0x1d, 0x79, 0xa2, 0x85, 0x26,
|
||||
0x63, 0x3c, 0x52, 0xc6, 0xd1, 0xd4, 0x23, 0x05, 0x3a, 0xd8, 0x69, 0x1e, 0x7a, 0xcd, 0x27, 0x7f,
|
||||
0x32, 0x08, 0x3a, 0xe5, 0x9e, 0xed, 0x2b, 0xf7, 0xac, 0x57, 0x6e, 0x7a, 0xda, 0x2a, 0x37, 0x3d,
|
||||
0x25, 0x2c, 0x2e, 0x5b, 0xe5, 0x8a, 0x4b, 0x9a, 0xda, 0x37, 0x3a, 0xaf, 0x8b, 0xd3, 0xc6, 0x8e,
|
||||
0x37, 0x12, 0x1d, 0xa6, 0x75, 0xff, 0x70, 0x87, 0xda, 0xf5, 0x1c, 0x09, 0x87, 0x48, 0x1c, 0x17,
|
||||
0xc6, 0xd5, 0xb6, 0x4b, 0x0b, 0xf8, 0xa7, 0x10, 0x08, 0xea, 0xc2, 0xb4, 0xba, 0x37, 0x20, 0x13,
|
||||
0x16, 0x36, 0x9b, 0x3c, 0x73, 0xd7, 0x88, 0xe5, 0xba, 0x28, 0x50, 0x3b, 0x4d, 0x5b, 0x60, 0xb8,
|
||||
0xf3, 0x1d, 0xda, 0xcf, 0x91, 0x27, 0x2c, 0x48, 0x7e, 0x84, 0xe8, 0x44, 0xa1, 0xae, 0x44, 0xad,
|
||||
0xde, 0xfc, 0x88, 0x71, 0xf0, 0xbf, 0x9d, 0x7f, 0xf7, 0xa2, 0x75, 0x02, 0x9d, 0x7b, 0xfd, 0x7a,
|
||||
0xff, 0xd2, 0xef, 0xb9, 0x2c, 0xe4, 0x2c, 0x35, 0x8b, 0xf5, 0x84, 0x43, 0xc9, 0xe7, 0xe0, 0x93,
|
||||
0x4f, 0x06, 0xcc, 0xfe, 0x7f, 0x79, 0x6c, 0x31, 0x36, 0xff, 0xd6, 0xcf, 0xfe, 0x09, 0x00, 0x00,
|
||||
0xff, 0xff, 0xa7, 0xc6, 0x53, 0x22, 0xbf, 0x07, 0x00, 0x00,
|
||||
// 876 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xbc, 0x55, 0xdf, 0x6e, 0xe3, 0xc4,
|
||||
0x17, 0xd6, 0xc4, 0x76, 0x62, 0x9f, 0x76, 0xfb, 0xfb, 0x69, 0xb4, 0x62, 0x0d, 0xdc, 0x44, 0x16,
|
||||
0x48, 0x01, 0x89, 0x82, 0xd8, 0x27, 0x68, 0x6b, 0x09, 0x85, 0x76, 0x97, 0x32, 0x69, 0xcb, 0x15,
|
||||
0x5a, 0x4d, 0x9c, 0x93, 0xc6, 0x5a, 0x27, 0x36, 0x63, 0xbb, 0x59, 0xbf, 0x05, 0x4f, 0x80, 0x84,
|
||||
0xc4, 0x15, 0x17, 0x5c, 0xf0, 0x02, 0x3c, 0x04, 0x2f, 0x84, 0xce, 0xcc, 0xf8, 0x4f, 0xd8, 0x82,
|
||||
0xf6, 0x8a, 0xbb, 0xf9, 0xce, 0x19, 0x7f, 0xe7, 0xdf, 0x77, 0xc6, 0x70, 0x92, 0xee, 0x2a, 0x54,
|
||||
0x3b, 0x99, 0x9d, 0x16, 0x2a, 0xaf, 0x72, 0xee, 0xb7, 0x38, 0xfa, 0x6d, 0x04, 0xe3, 0x45, 0x5e,
|
||||
0xab, 0x04, 0xf9, 0x09, 0x8c, 0xe6, 0x71, 0xc8, 0xa6, 0x6c, 0xe6, 0x88, 0xd1, 0x3c, 0xe6, 0x1c,
|
||||
0xdc, 0x97, 0x72, 0x8b, 0xe1, 0x68, 0xca, 0x66, 0x81, 0xd0, 0x67, 0xb2, 0xdd, 0x34, 0x05, 0x86,
|
||||
0x8e, 0xb1, 0xd1, 0x99, 0x7f, 0x00, 0xfe, 0x6d, 0x49, 0x6c, 0x5b, 0x0c, 0x5d, 0x6d, 0xef, 0x30,
|
||||
0xf9, 0xae, 0x65, 0x59, 0xee, 0x73, 0xb5, 0x0a, 0x3d, 0xe3, 0x6b, 0x31, 0xff, 0x3f, 0x38, 0xb7,
|
||||
0xe2, 0x2a, 0x1c, 0x6b, 0x33, 0x1d, 0x79, 0x08, 0x93, 0x18, 0xd7, 0xb2, 0xce, 0xaa, 0x70, 0x32,
|
||||
0x65, 0x33, 0x5f, 0xb4, 0x90, 0x78, 0x6e, 0x30, 0xc3, 0x7b, 0x25, 0xd7, 0xa1, 0x6f, 0x78, 0x5a,
|
||||
0xcc, 0x4f, 0x81, 0xcf, 0x77, 0x25, 0x26, 0xb5, 0xc2, 0xc5, 0xeb, 0xb4, 0xb8, 0x43, 0x95, 0xae,
|
||||
0x9b, 0x30, 0xd0, 0x04, 0x8f, 0x78, 0x28, 0xca, 0x0b, 0xac, 0x24, 0xc5, 0x06, 0x4d, 0xd5, 0x42,
|
||||
0x1e, 0xc1, 0xf1, 0x62, 0x23, 0x15, 0xae, 0x16, 0x98, 0x28, 0xac, 0xc2, 0x23, 0xed, 0x3e, 0xb0,
|
||||
0x45, 0x3f, 0x32, 0x08, 0x62, 0x59, 0x6e, 0x96, 0xb9, 0x54, 0xab, 0x77, 0xea, 0xd9, 0x67, 0xe0,
|
||||
0x25, 0x98, 0x65, 0x65, 0xe8, 0x4c, 0x9d, 0xd9, 0xd1, 0x97, 0xcf, 0x4e, 0xbb, 0x61, 0x74, 0x3c,
|
||||
0x17, 0x98, 0x65, 0xc2, 0xdc, 0xe2, 0x5f, 0x40, 0x50, 0xe1, 0xb6, 0xc8, 0x64, 0x85, 0x65, 0xe8,
|
||||
0xea, 0x4f, 0x78, 0xff, 0xc9, 0x8d, 0x75, 0x89, 0xfe, 0x52, 0xf4, 0x2b, 0x83, 0x27, 0x07, 0x54,
|
||||
0xfc, 0x18, 0xd8, 0x1b, 0x9d, 0x95, 0x27, 0xd8, 0x1b, 0x42, 0x8d, 0xce, 0xc8, 0x13, 0xac, 0x21,
|
||||
0xb4, 0xd7, 0xf3, 0xf3, 0x04, 0xdb, 0x13, 0xda, 0xe8, 0xa9, 0x79, 0x82, 0x6d, 0xf8, 0x27, 0x30,
|
||||
0xf9, 0xa1, 0x46, 0x95, 0x62, 0x19, 0x7a, 0x3a, 0xf2, 0xff, 0xfa, 0xc8, 0xdf, 0xd6, 0xa8, 0x1a,
|
||||
0xd1, 0xfa, 0xa9, 0x52, 0x3d, 0x71, 0x33, 0x3e, 0x7d, 0x26, 0x5b, 0x45, 0xea, 0x98, 0x18, 0x1b,
|
||||
0x9d, 0x6d, 0x87, 0xcc, 0xcc, 0x46, 0xf3, 0x38, 0xfa, 0x83, 0xd1, 0x28, 0x4d, 0xea, 0x83, 0xf6,
|
||||
0x69, 0x27, 0x7f, 0x1f, 0x7c, 0x2a, 0xeb, 0xd5, 0x83, 0x54, 0xb6, 0x85, 0x13, 0xc2, 0x77, 0x52,
|
||||
0xf1, 0xcf, 0x61, 0xfc, 0x20, 0xb3, 0x1a, 0x1f, 0x69, 0x63, 0x4b, 0x77, 0x47, 0x7e, 0x61, 0xaf,
|
||||
0x75, 0xc9, 0xb8, 0x83, 0x64, 0x9e, 0x82, 0x97, 0xc9, 0x25, 0x66, 0x56, 0x8b, 0x06, 0xd0, 0x80,
|
||||
0xa8, 0xaa, 0x46, 0xd7, 0xf2, 0x28, 0xb3, 0xa9, 0xdd, 0xdc, 0x8a, 0x6e, 0xe1, 0xc9, 0x41, 0xc4,
|
||||
0x2e, 0x12, 0x3b, 0x8c, 0xa4, 0xf3, 0xb0, 0x65, 0x18, 0x40, 0x32, 0x2e, 0x31, 0xc3, 0xa4, 0xc2,
|
||||
0x95, 0x1e, 0x81, 0x2f, 0x3a, 0x1c, 0xfd, 0xcc, 0x7a, 0x5e, 0x1d, 0x8f, 0x84, 0x9a, 0xe4, 0xdb,
|
||||
0xad, 0xdc, 0xad, 0x2c, 0x75, 0x0b, 0xa9, 0x6f, 0xab, 0xa5, 0xa5, 0x1e, 0xad, 0x96, 0x84, 0x55,
|
||||
0x61, 0x97, 0x72, 0xa4, 0x0a, 0x3e, 0x85, 0xa3, 0x2d, 0xca, 0xb2, 0x56, 0xb8, 0xc5, 0x5d, 0x65,
|
||||
0x5b, 0x30, 0x34, 0xf1, 0x67, 0x30, 0xa9, 0xe4, 0xfd, 0xab, 0xd7, 0xd8, 0xd8, 0x5e, 0x8c, 0x2b,
|
||||
0x79, 0x7f, 0x89, 0x0d, 0xff, 0x10, 0x82, 0x75, 0x8a, 0xd9, 0x4a, 0xbb, 0xcc, 0x70, 0x7d, 0x6d,
|
||||
0xb8, 0xc4, 0x26, 0xfa, 0x85, 0xc1, 0x78, 0x81, 0xea, 0x01, 0xd5, 0x3b, 0x29, 0x7f, 0xf8, 0x32,
|
||||
0x38, 0xff, 0xf2, 0x32, 0xb8, 0x8f, 0xbf, 0x0c, 0x5e, 0xff, 0x32, 0x3c, 0x05, 0x6f, 0xa1, 0x92,
|
||||
0x79, 0xac, 0x33, 0x72, 0x84, 0x01, 0xfc, 0x3d, 0x18, 0x9f, 0x25, 0x55, 0xfa, 0x80, 0xf6, 0xb9,
|
||||
0xb0, 0x28, 0xfa, 0x89, 0xc1, 0xf8, 0x4a, 0x36, 0x79, 0x5d, 0xbd, 0xa5, 0xb0, 0x29, 0x1c, 0x9d,
|
||||
0x15, 0x45, 0x96, 0x26, 0xb2, 0x4a, 0xf3, 0x9d, 0xcd, 0x76, 0x68, 0xa2, 0x1b, 0x2f, 0x06, 0xbd,
|
||||
0x33, 0x79, 0x0f, 0x4d, 0xfc, 0x23, 0xf0, 0x2e, 0xf4, 0x42, 0x9b, 0xed, 0x3c, 0xe9, 0xf5, 0x62,
|
||||
0xf6, 0x58, 0x3b, 0xa9, 0xc0, 0xb3, 0xba, 0xca, 0xd7, 0x59, 0xbe, 0xd7, 0x95, 0xf8, 0xa2, 0xc3,
|
||||
0xd1, 0x9f, 0x0c, 0xdc, 0xff, 0x6a, 0x51, 0x8f, 0x81, 0xa5, 0x76, 0x90, 0x2c, 0xed, 0xd6, 0x76,
|
||||
0x32, 0x58, 0xdb, 0x10, 0x26, 0x8d, 0x92, 0xbb, 0x7b, 0x2c, 0x43, 0x7f, 0xea, 0xcc, 0x1c, 0xd1,
|
||||
0x42, 0xed, 0xd1, 0x3b, 0x52, 0x86, 0xc1, 0xd4, 0x21, 0x05, 0x5a, 0xd8, 0x69, 0x1e, 0x7a, 0xcd,
|
||||
0x47, 0xbf, 0x33, 0xf0, 0x3a, 0xe5, 0x5e, 0x1c, 0x2a, 0xf7, 0xa2, 0x57, 0x6e, 0x7c, 0xde, 0x2a,
|
||||
0x37, 0x3e, 0x27, 0x2c, 0xae, 0x5b, 0xe5, 0x8a, 0x6b, 0xea, 0xda, 0x57, 0x2a, 0xaf, 0x8b, 0xf3,
|
||||
0xc6, 0xb4, 0x37, 0x10, 0x1d, 0xa6, 0x71, 0x7f, 0xb7, 0x41, 0x65, 0x6b, 0x0e, 0x84, 0x45, 0x24,
|
||||
0x8e, 0x2b, 0xbd, 0xd5, 0xa6, 0x4a, 0x03, 0xf8, 0xc7, 0xe0, 0x09, 0xaa, 0x42, 0x97, 0x7a, 0xd0,
|
||||
0x20, 0x6d, 0x16, 0xc6, 0x1b, 0x3d, 0xb7, 0xd7, 0x88, 0xe5, 0xb6, 0x28, 0x50, 0x59, 0x4d, 0x1b,
|
||||
0xa0, 0xb9, 0xf3, 0x3d, 0x9a, 0xe7, 0xc8, 0x11, 0x06, 0x44, 0xdf, 0x43, 0x70, 0x96, 0xa1, 0xaa,
|
||||
0x44, 0x9d, 0xbd, 0xfd, 0x88, 0x71, 0x70, 0xbf, 0x5e, 0x7c, 0xf3, 0xb2, 0xdd, 0x04, 0x3a, 0xf7,
|
||||
0xfa, 0x75, 0xfe, 0xa6, 0xdf, 0x4b, 0x59, 0xc8, 0x79, 0xac, 0x07, 0xeb, 0x08, 0x8b, 0xa2, 0x4f,
|
||||
0xc1, 0xa5, 0x3d, 0x19, 0x30, 0xbb, 0xff, 0xb4, 0x63, 0xcb, 0xb1, 0xfe, 0xa3, 0x3f, 0xff, 0x2b,
|
||||
0x00, 0x00, 0xff, 0xff, 0x0f, 0x40, 0x84, 0xea, 0xe3, 0x07, 0x00, 0x00,
|
||||
}
|
||||
|
|
|
@ -2,23 +2,24 @@ syntax = "proto3";
|
|||
package internal;
|
||||
|
||||
message Source {
|
||||
int64 ID = 1; // ID is the unique ID of the source
|
||||
string Name = 2; // Name is the user-defined name for the source
|
||||
string Type = 3; // Type specifies which kinds of source (enterprise vs oss)
|
||||
string Username = 4; // Username is the username to connect to the source
|
||||
int64 ID = 1; // ID is the unique ID of the source
|
||||
string Name = 2; // Name is the user-defined name for the source
|
||||
string Type = 3; // Type specifies which kinds of source (enterprise vs oss)
|
||||
string Username = 4; // Username is the username to connect to the source
|
||||
string Password = 5;
|
||||
string URL = 6; // URL are the connections to the source
|
||||
bool Default = 7; // Flags an source as the default.
|
||||
string Telegraf = 8; // Telegraf is the db telegraf is written to. By default it is "telegraf"
|
||||
bool InsecureSkipVerify = 9; // InsecureSkipVerify accepts any certificate from the influx server
|
||||
string URL = 6; // URL are the connections to the source
|
||||
bool Default = 7; // Flags an source as the default.
|
||||
string Telegraf = 8; // Telegraf is the db telegraf is written to. By default it is "telegraf"
|
||||
bool InsecureSkipVerify = 9; // InsecureSkipVerify accepts any certificate from the influx server
|
||||
string MetaURL = 10; // MetaURL is the connection URL for the meta node.
|
||||
string SharedSecret = 11; // SharedSecret signs the optional InfluxDB JWT Authorization
|
||||
}
|
||||
|
||||
message Dashboard {
|
||||
int64 ID = 1; // ID is the unique ID of the dashboard
|
||||
string Name = 2; // Name is the user-defined name of the dashboard
|
||||
repeated DashboardCell cells = 3; // a representation of all visual data required for rendering the dashboard
|
||||
repeated Template templates = 4; // Templates replace template variables within InfluxQL
|
||||
repeated Template templates = 4; // Templates replace template variables within InfluxQL
|
||||
}
|
||||
|
||||
message DashboardCell {
|
||||
|
|
|
@ -40,6 +40,38 @@ func TestMarshalSource(t *testing.T) {
|
|||
t.Fatalf("source protobuf copy error: got %#v, expected %#v", vv, v)
|
||||
}
|
||||
}
|
||||
func TestMarshalSourceWithSecret(t *testing.T) {
|
||||
v := chronograf.Source{
|
||||
ID: 12,
|
||||
Name: "Fountain of Truth",
|
||||
Type: "influx",
|
||||
Username: "docbrown",
|
||||
SharedSecret: "hunter2s",
|
||||
URL: "http://twin-pines.mall.io:8086",
|
||||
MetaURL: "http://twin-pines.meta.io:8086",
|
||||
Default: true,
|
||||
Telegraf: "telegraf",
|
||||
}
|
||||
|
||||
var vv chronograf.Source
|
||||
if buf, err := internal.MarshalSource(v); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if err := internal.UnmarshalSource(buf, &vv); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(v, vv) {
|
||||
t.Fatalf("source protobuf copy error: got %#v, expected %#v", vv, v)
|
||||
}
|
||||
|
||||
// Test if the new insecureskipverify works
|
||||
v.InsecureSkipVerify = true
|
||||
if buf, err := internal.MarshalSource(v); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if err := internal.UnmarshalSource(buf, &vv); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !reflect.DeepEqual(v, vv) {
|
||||
t.Fatalf("source protobuf copy error: got %#v, expected %#v", vv, v)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarshalServer(t *testing.T) {
|
||||
v := chronograf.Server{
|
||||
|
|
|
@ -346,6 +346,7 @@ type Source struct {
|
|||
Type string `json:"type,omitempty"` // Type specifies which kinds of source (enterprise vs oss)
|
||||
Username string `json:"username,omitempty"` // Username is the username to connect to the source
|
||||
Password string `json:"password,omitempty"` // Password is in CLEARTEXT
|
||||
SharedSecret string `json:"sharedSecret,omitempty"` // ShareSecret is the optional signing secret for Influx JWT authorization
|
||||
URL string `json:"url"` // URL are the connections to the source
|
||||
MetaURL string `json:"metaUrl,omitempty"` // MetaURL is the url for the meta node
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"` // InsecureSkipVerify as true means any certificate presented by the source is accepted.
|
||||
|
@ -625,44 +626,3 @@ type LayoutStore interface {
|
|||
// Update the dashboard in the store.
|
||||
Update(context.Context, Layout) error
|
||||
}
|
||||
|
||||
// SourceAndKapacitor is used to parse any NewSources server flag arguments
|
||||
type SourceAndKapacitor struct {
|
||||
Source Source `json:"influxdb"`
|
||||
Kapacitor Server `json:"kapacitor"`
|
||||
}
|
||||
|
||||
// NewSources adds sources to BoltDb idempotently by name, as well as respective kapacitors
|
||||
func NewSources(ctx context.Context, sourcesStore SourcesStore, serversStore ServersStore, srcsKaps []SourceAndKapacitor, logger Logger) error {
|
||||
srcs, err := sourcesStore.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
SourceLoop:
|
||||
for _, srcKap := range srcsKaps {
|
||||
for _, src := range srcs {
|
||||
// If source already exists, do nothing
|
||||
if src.Name == srcKap.Source.Name {
|
||||
logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSources", src.Name).
|
||||
Info("Source already exists")
|
||||
continue SourceLoop
|
||||
}
|
||||
}
|
||||
|
||||
src, err := sourcesStore.Add(ctx, srcKap.Source)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
srcKap.Kapacitor.SrcID = src.ID
|
||||
_, err = serversStore.Add(ctx, srcKap.Kapacitor)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package chronograf_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/mocks"
|
||||
)
|
||||
|
||||
func Test_NewSources(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
srcsKaps := []chronograf.SourceAndKapacitor{
|
||||
{
|
||||
Source: chronograf.Source{
|
||||
Default: true,
|
||||
InsecureSkipVerify: false,
|
||||
MetaURL: "http://metaurl.com",
|
||||
Name: "Influx 1",
|
||||
Password: "pass1",
|
||||
Telegraf: "telegraf",
|
||||
URL: "http://localhost:8086",
|
||||
Username: "user1",
|
||||
},
|
||||
Kapacitor: chronograf.Server{
|
||||
Active: true,
|
||||
Name: "Kapa 1",
|
||||
URL: "http://localhost:9092",
|
||||
},
|
||||
},
|
||||
}
|
||||
saboteurSrcsKaps := []chronograf.SourceAndKapacitor{
|
||||
{
|
||||
Source: chronograf.Source{
|
||||
Name: "Influx 1",
|
||||
},
|
||||
Kapacitor: chronograf.Server{
|
||||
Name: "Kapa Aspiring Saboteur",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
srcs := []chronograf.Source{}
|
||||
srcsStore := mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return srcs, nil
|
||||
},
|
||||
AddF: func(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
srcs = append(srcs, src)
|
||||
return src, nil
|
||||
},
|
||||
}
|
||||
srvs := []chronograf.Server{}
|
||||
srvsStore := mocks.ServersStore{
|
||||
AddF: func(ctx context.Context, srv chronograf.Server) (chronograf.Server, error) {
|
||||
srvs = append(srvs, srv)
|
||||
return srv, nil
|
||||
},
|
||||
}
|
||||
|
||||
err := chronograf.NewSources(ctx, &srcsStore, &srvsStore, srcsKaps, &mocks.TestLogger{})
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error when creating New Sources. Error:", err)
|
||||
}
|
||||
if len(srcs) != 1 {
|
||||
t.Error("Expected one source in sourcesStore")
|
||||
}
|
||||
if len(srvs) != 1 {
|
||||
t.Error("Expected one source in serversStore")
|
||||
}
|
||||
|
||||
err = chronograf.NewSources(ctx, &srcsStore, &srvsStore, saboteurSrcsKaps, &mocks.TestLogger{})
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error when creating New Sources. Error:", err)
|
||||
}
|
||||
if len(srcs) != 1 {
|
||||
t.Error("Expected one source in sourcesStore")
|
||||
}
|
||||
if len(srvs) != 1 {
|
||||
t.Error("Expected one source in serversStore")
|
||||
}
|
||||
if !reflect.DeepEqual(srcs[0], srcsKaps[0].Source) {
|
||||
t.Error("Expected source in sourceStore to remain unchanged")
|
||||
}
|
||||
}
|
|
@ -120,13 +120,17 @@ func (c *Client) Connect(ctx context.Context, src *chronograf.Source) error {
|
|||
|
||||
c.dataNodes = ring.New(len(cluster.DataNodes))
|
||||
for _, dn := range cluster.DataNodes {
|
||||
cl, err := influx.NewClient(dn.HTTPAddr, c.Logger)
|
||||
if err != nil {
|
||||
continue
|
||||
} else {
|
||||
c.dataNodes.Value = cl
|
||||
c.dataNodes = c.dataNodes.Next()
|
||||
cl := &influx.Client{
|
||||
Logger: c.Logger,
|
||||
}
|
||||
dataSrc := &chronograf.Source{}
|
||||
*dataSrc = *src
|
||||
dataSrc.URL = dn.HTTPAddr
|
||||
if err := cl.Connect(ctx, dataSrc); err != nil {
|
||||
continue
|
||||
}
|
||||
c.dataNodes.Value = cl
|
||||
c.dataNodes = c.dataNodes.Next()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -28,25 +28,9 @@ var (
|
|||
// Client is a device for retrieving time series data from an InfluxDB instance
|
||||
type Client struct {
|
||||
URL *url.URL
|
||||
Bearer Bearer
|
||||
InsecureSkipVerify bool
|
||||
|
||||
Logger chronograf.Logger
|
||||
}
|
||||
|
||||
// NewClient initializes an HTTP Client for InfluxDB. UDP, although supported
|
||||
// for querying InfluxDB, is not supported here to remove the need to
|
||||
// explicitly Close the client.
|
||||
func NewClient(host string, lg chronograf.Logger) (*Client, error) {
|
||||
l := lg.WithField("host", host)
|
||||
u, err := url.Parse(host)
|
||||
if err != nil {
|
||||
l.Error("Error initialize influx client: err:", err)
|
||||
return nil, err
|
||||
}
|
||||
return &Client{
|
||||
URL: u,
|
||||
Logger: l,
|
||||
}, nil
|
||||
Logger chronograf.Logger
|
||||
}
|
||||
|
||||
// Response is a partial JSON decoded InfluxQL response used
|
||||
|
@ -88,6 +72,15 @@ func (c *Client) query(u *url.URL, q chronograf.Query) (chronograf.Response, err
|
|||
params.Set("epoch", "ms") // TODO(timraymond): set this based on analysis
|
||||
req.URL.RawQuery = params.Encode()
|
||||
|
||||
if c.Bearer != nil && u.User != nil {
|
||||
token, err := c.Bearer.Token(u.User.Username())
|
||||
if err != nil {
|
||||
logs.Error("Error creating token", err)
|
||||
return nil, fmt.Errorf("Unable to create token")
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
}
|
||||
|
||||
hc := &http.Client{}
|
||||
if c.InsecureSkipVerify {
|
||||
hc.Transport = skipVerifyTransport
|
||||
|
@ -157,7 +150,7 @@ func (c *Client) Query(ctx context.Context, q chronograf.Query) (chronograf.Resp
|
|||
}
|
||||
}
|
||||
|
||||
// Connect caches the URL for the data source
|
||||
// Connect caches the URL and optional Bearer Authorization for the data source
|
||||
func (c *Client) Connect(ctx context.Context, src *chronograf.Source) error {
|
||||
u, err := url.Parse(src.URL)
|
||||
if err != nil {
|
||||
|
@ -169,6 +162,16 @@ func (c *Client) Connect(ctx context.Context, src *chronograf.Source) error {
|
|||
c.InsecureSkipVerify = src.InsecureSkipVerify
|
||||
}
|
||||
c.URL = u
|
||||
|
||||
// Optionally, add the shared secret JWT token creation
|
||||
if src.Username != "" && src.SharedSecret != "" {
|
||||
c.Bearer = &BearerJWT{
|
||||
src.SharedSecret,
|
||||
}
|
||||
} else {
|
||||
// Clear out the bearer if not needed
|
||||
c.Bearer = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -2,16 +2,34 @@ package influx_test
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
gojwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/influx"
|
||||
"github.com/influxdata/chronograf/log"
|
||||
)
|
||||
|
||||
// NewClient initializes an HTTP Client for InfluxDB.
|
||||
func NewClient(host string, lg chronograf.Logger) (*influx.Client, error) {
|
||||
l := lg.WithField("host", host)
|
||||
u, err := url.Parse(host)
|
||||
if err != nil {
|
||||
l.Error("Error initialize influx client: err:", err)
|
||||
return nil, err
|
||||
}
|
||||
return &influx.Client{
|
||||
URL: u,
|
||||
Logger: l,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func Test_Influx_MakesRequestsToQueryEndpoint(t *testing.T) {
|
||||
t.Parallel()
|
||||
called := false
|
||||
|
@ -26,7 +44,7 @@ func Test_Influx_MakesRequestsToQueryEndpoint(t *testing.T) {
|
|||
defer ts.Close()
|
||||
|
||||
var series chronograf.TimeSeries
|
||||
series, err := influx.NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
series, err := NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error initializing client: err:", err)
|
||||
}
|
||||
|
@ -44,6 +62,126 @@ func Test_Influx_MakesRequestsToQueryEndpoint(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
type MockBearer struct {
|
||||
Bearer string
|
||||
Error error
|
||||
}
|
||||
|
||||
func (m *MockBearer) Token(username string) (string, error) {
|
||||
return m.Bearer, m.Error
|
||||
}
|
||||
func Test_Influx_AuthorizationBearer(t *testing.T) {
|
||||
t.Parallel()
|
||||
want := "Bearer ********"
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write([]byte(`{}`))
|
||||
got := r.Header.Get("Authorization")
|
||||
if got != want {
|
||||
t.Errorf("Test_Influx_AuthorizationBearer got %s want %s", got, want)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
bearer := &MockBearer{
|
||||
Bearer: "********",
|
||||
}
|
||||
|
||||
u, _ := url.Parse(ts.URL)
|
||||
u.User = url.UserPassword("AzureDiamond", "hunter2")
|
||||
series := &influx.Client{
|
||||
URL: u,
|
||||
Bearer: bearer,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
}
|
||||
|
||||
query := chronograf.Query{
|
||||
Command: "show databases",
|
||||
}
|
||||
_, err := series.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error but was", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Influx_AuthorizationBearerCtx(t *testing.T) {
|
||||
t.Parallel()
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
rw.Write([]byte(`{}`))
|
||||
got := r.Header.Get("Authorization")
|
||||
if got == "" {
|
||||
t.Error("Test_Influx_AuthorizationBearerCtx got empty string")
|
||||
}
|
||||
incomingToken := strings.Split(got, " ")[1]
|
||||
|
||||
alg := func(token *gojwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*gojwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return []byte("hunter2"), nil
|
||||
}
|
||||
claims := &gojwt.MapClaims{}
|
||||
token, err := gojwt.ParseWithClaims(string(incomingToken), claims, alg)
|
||||
if err != nil {
|
||||
t.Errorf("Test_Influx_AuthorizationBearerCtx unexpected claims error %v", err)
|
||||
}
|
||||
if !token.Valid {
|
||||
t.Error("Test_Influx_AuthorizationBearerCtx unexpected valid claim")
|
||||
}
|
||||
if err := claims.Valid(); err != nil {
|
||||
t.Errorf("Test_Influx_AuthorizationBearerCtx not expires already %v", err)
|
||||
}
|
||||
user := (*claims)["username"].(string)
|
||||
if user != "AzureDiamond" {
|
||||
t.Errorf("Test_Influx_AuthorizationBearerCtx expected username AzureDiamond but got %s", user)
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
|
||||
series := &influx.Client{
|
||||
Logger: log.New(log.DebugLevel),
|
||||
}
|
||||
|
||||
err := series.Connect(context.Background(), &chronograf.Source{
|
||||
Username: "AzureDiamond",
|
||||
SharedSecret: "hunter2",
|
||||
URL: ts.URL,
|
||||
InsecureSkipVerify: true,
|
||||
})
|
||||
|
||||
query := chronograf.Query{
|
||||
Command: "show databases",
|
||||
}
|
||||
_, err = series.Query(context.Background(), query)
|
||||
if err != nil {
|
||||
t.Fatal("Expected no error but was", err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Influx_AuthorizationBearerFailure(t *testing.T) {
|
||||
t.Parallel()
|
||||
bearer := &MockBearer{
|
||||
Error: fmt.Errorf("cracked1337"),
|
||||
}
|
||||
|
||||
u, _ := url.Parse("http://haxored.net")
|
||||
u.User = url.UserPassword("AzureDiamond", "hunter2")
|
||||
series := &influx.Client{
|
||||
URL: u,
|
||||
Bearer: bearer,
|
||||
Logger: log.New(log.DebugLevel),
|
||||
}
|
||||
|
||||
query := chronograf.Query{
|
||||
Command: "show databases",
|
||||
}
|
||||
_, err := series.Query(context.Background(), query)
|
||||
if err == nil {
|
||||
t.Fatal("Test_Influx_AuthorizationBearerFailure Expected error but received nil")
|
||||
}
|
||||
}
|
||||
|
||||
func Test_Influx_HTTPS_Failure(t *testing.T) {
|
||||
called := false
|
||||
ts := httptest.NewTLSServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
||||
|
@ -53,7 +191,7 @@ func Test_Influx_HTTPS_Failure(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
var series chronograf.TimeSeries
|
||||
series, err := influx.NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
series, err := NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error initializing client: err:", err)
|
||||
}
|
||||
|
@ -97,7 +235,7 @@ func Test_Influx_HTTPS_InsecureSkipVerify(t *testing.T) {
|
|||
|
||||
ctx := context.Background()
|
||||
var series chronograf.TimeSeries
|
||||
series, err := influx.NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
series, err := NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
if err != nil {
|
||||
t.Fatal("Unexpected error initializing client: err:", err)
|
||||
}
|
||||
|
@ -166,7 +304,7 @@ func Test_Influx_CancelsInFlightRequests(t *testing.T) {
|
|||
ts.Close()
|
||||
}()
|
||||
|
||||
series, _ := influx.NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
series, _ := NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
errs := make(chan (error))
|
||||
|
@ -209,7 +347,7 @@ func Test_Influx_CancelsInFlightRequests(t *testing.T) {
|
|||
}
|
||||
|
||||
func Test_Influx_RejectsInvalidHosts(t *testing.T) {
|
||||
_, err := influx.NewClient(":", log.New(log.DebugLevel))
|
||||
_, err := NewClient(":", log.New(log.DebugLevel))
|
||||
if err == nil {
|
||||
t.Fatal("Expected err but was nil")
|
||||
}
|
||||
|
@ -221,7 +359,7 @@ func Test_Influx_ReportsInfluxErrs(t *testing.T) {
|
|||
}))
|
||||
defer ts.Close()
|
||||
|
||||
cl, err := influx.NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
cl, err := NewClient(ts.URL, log.New(log.DebugLevel))
|
||||
if err != nil {
|
||||
t.Fatal("Encountered unexpected error while initializing influx client: err:", err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package influx
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
)
|
||||
|
||||
// Bearer generates tokens for Authorization: Bearer
|
||||
type Bearer interface {
|
||||
Token(username string) (string, error)
|
||||
}
|
||||
|
||||
// BearerJWT is the default Bearer for InfluxDB
|
||||
type BearerJWT struct {
|
||||
SharedSecret string
|
||||
}
|
||||
|
||||
// Token returns the expected InfluxDB JWT signed with the sharedSecret
|
||||
func (b *BearerJWT) Token(username string) (string, error) {
|
||||
return JWT(username, b.SharedSecret, time.Now)
|
||||
}
|
||||
|
||||
// Now returns the current time
|
||||
type Now func() time.Time
|
||||
|
||||
// JWT returns a token string accepted by InfluxDB using the sharedSecret as an Authorization: Bearer header
|
||||
func JWT(username, sharedSecret string, now Now) (string, error) {
|
||||
token := &jwt.Token{
|
||||
Header: map[string]interface{}{
|
||||
"typ": "JWT",
|
||||
"alg": jwt.SigningMethodHS512.Alg(),
|
||||
},
|
||||
Claims: jwt.MapClaims{
|
||||
"username": username,
|
||||
"exp": now().Add(time.Minute).Unix(),
|
||||
},
|
||||
Method: jwt.SigningMethodHS512,
|
||||
}
|
||||
return token.SignedString([]byte(sharedSecret))
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package influx
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestJWT(t *testing.T) {
|
||||
type args struct {
|
||||
username string
|
||||
sharedSecret string
|
||||
now Now
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "",
|
||||
args: args{
|
||||
username: "AzureDiamond",
|
||||
sharedSecret: "hunter2",
|
||||
now: func() time.Time {
|
||||
return time.Unix(0, 0)
|
||||
},
|
||||
},
|
||||
want: "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjYwLCJ1c2VybmFtZSI6IkF6dXJlRGlhbW9uZCJ9.kUWGwcpCPwV7MEk7luO1rt8036LyvG4bRL_CfseQGmz4b0S34gATx30g4xvqVAV6bwwYE0YU3P8FjG8ij4kc5g",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := JWT(tt.args.username, tt.args.sharedSecret, tt.args.now)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("JWT() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("JWT() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package server
|
|||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
|
@ -51,7 +50,7 @@ type Server struct {
|
|||
KapacitorUsername string `long:"kapacitor-username" description:"Username of your Kapacitor instance" env:"KAPACITOR_USERNAME"`
|
||||
KapacitorPassword string `long:"kapacitor-password" description:"Password of your Kapacitor instance" env:"KAPACITOR_PASSWORD"`
|
||||
|
||||
NewSources string `long:"new-sources" description:"Config for adding a new InfluxDb source and Kapacitor server, in JSON as an array of objects, and surrounded by single quotes. E.g. --new-sources='[{\"influxdb\":{\"name\":\"Influx 1\",\"username\":\"user1\",\"password\":\"pass1\",\"url\":\"http://localhost:8086\",\"metaUrl\":\"http://metaurl.com\",\"insecureSkipVerify\":false,\"default\":true,\"telegraf\":\"telegraf\"},\"kapacitor\":{\"name\":\"Kapa 1\",\"url\":\"http://localhost:9092\",\"active\":true}}]'" env:"NEW_SOURCES"`
|
||||
NewSources string `long:"new-sources" description:"Config for adding a new InfluxDB source and Kapacitor server, in JSON as an array of objects, and surrounded by single quotes. E.g. --new-sources='[{\"influxdb\":{\"name\":\"Influx 1\",\"username\":\"user1\",\"password\":\"pass1\",\"url\":\"http://localhost:8086\",\"metaUrl\":\"http://metaurl.com\",\"insecureSkipVerify\":false,\"default\":true,\"telegraf\":\"telegraf\",\"sharedSecret\":\"hunter2\"},\"kapacitor\":{\"name\":\"Kapa 1\",\"url\":\"http://localhost:9092\",\"active\":true}}]'" env:"NEW_SOURCES" hidden:"true"`
|
||||
|
||||
Develop bool `short:"d" long:"develop" description:"Run server in develop mode."`
|
||||
BoltPath string `short:"b" long:"bolt-path" description:"Full path to boltDB file (/var/lib/chronograf/chronograf-v1.db)" env:"BOLT_PATH" default:"chronograf-v1.db"`
|
||||
|
@ -301,8 +300,13 @@ func (s *Server) Serve(ctx context.Context) error {
|
|||
return err
|
||||
}
|
||||
service := openService(ctx, s.BoltPath, layoutBuilder, sourcesBuilder, kapacitorBuilder, logger, s.useAuth())
|
||||
|
||||
go processNewSources(ctx, service, s.NewSources, logger)
|
||||
if err := service.HandleNewSources(ctx, s.NewSources); err != nil {
|
||||
logger.
|
||||
WithField("component", "server").
|
||||
WithField("new-sources", "invalid").
|
||||
Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
basepath = s.Basepath
|
||||
if basepath != "" && s.PrefixRoutes == false {
|
||||
|
@ -437,33 +441,6 @@ func openService(ctx context.Context, boltPath string, lBuilder LayoutBuilder, s
|
|||
}
|
||||
}
|
||||
|
||||
// processNewSources parses and persists new sources passed in via server flag
|
||||
func processNewSources(ctx context.Context, service Service, newSources string, logger chronograf.Logger) error {
|
||||
if newSources == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var srcsKaps []chronograf.SourceAndKapacitor
|
||||
// On JSON unmarshal error, continue server process without new source and write error to log
|
||||
if err := json.Unmarshal([]byte(newSources), &srcsKaps); err != nil {
|
||||
logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSources", "invalid").
|
||||
Error(err)
|
||||
}
|
||||
|
||||
// Add any new sources and kapacitors as specified via server flag
|
||||
if err := chronograf.NewSources(ctx, service.SourcesStore, service.ServersStore, srcsKaps, logger); err != nil {
|
||||
// Continue with server run even if adding NewSources fails
|
||||
logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSources", "invalid").
|
||||
Error(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// reportUsageStats starts periodic server reporting.
|
||||
func reportUsageStats(bi BuildInfo, logger chronograf.Logger) {
|
||||
rand.Seed(time.Now().UTC().UnixNano())
|
||||
|
|
|
@ -43,18 +43,15 @@ type InfluxClient struct{}
|
|||
|
||||
// New creates a client to connect to OSS or enterprise
|
||||
func (c *InfluxClient) New(src chronograf.Source, logger chronograf.Logger) (chronograf.TimeSeries, error) {
|
||||
if src.Type == chronograf.InfluxEnterprise && src.MetaURL != "" {
|
||||
dataNode := &influx.Client{
|
||||
Logger: logger,
|
||||
}
|
||||
if err := dataNode.Connect(context.TODO(), &src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tls := strings.Contains(src.MetaURL, "https")
|
||||
return enterprise.NewClientWithTimeSeries(logger, src.MetaURL, src.Username, src.Password, tls, dataNode)
|
||||
}
|
||||
return &influx.Client{
|
||||
client := &influx.Client{
|
||||
Logger: logger,
|
||||
}, nil
|
||||
}
|
||||
if err := client.Connect(context.TODO(), &src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if src.Type == chronograf.InfluxEnterprise && src.MetaURL != "" {
|
||||
tls := strings.Contains(src.MetaURL, "https")
|
||||
return enterprise.NewClientWithTimeSeries(logger, src.MetaURL, src.Username, src.Password, tls, client)
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
|
|
@ -34,8 +34,9 @@ func newSourceResponse(src chronograf.Source) sourceResponse {
|
|||
src.Telegraf = "telegraf"
|
||||
}
|
||||
|
||||
// Omit the password on response
|
||||
// Omit the password and shared secret on response
|
||||
src.Password = ""
|
||||
src.SharedSecret = ""
|
||||
|
||||
httpAPISrcs := "/chronograf/v1/sources"
|
||||
res := sourceResponse{
|
||||
|
@ -99,6 +100,7 @@ func (h *Service) tsdbType(ctx context.Context, src *chronograf.Source) (string,
|
|||
cli := &influx.Client{
|
||||
Logger: h.Logger,
|
||||
}
|
||||
|
||||
if err := cli.Connect(ctx, src); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
@ -293,3 +295,69 @@ func ValidSourceRequest(s chronograf.Source) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HandleNewSources parses and persists new sources passed in via server flag
|
||||
func (h *Service) HandleNewSources(ctx context.Context, input string) error {
|
||||
if input == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
var srcsKaps []struct {
|
||||
Source chronograf.Source `json:"influxdb"`
|
||||
Kapacitor chronograf.Server `json:"kapacitor"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(input), &srcsKaps); err != nil {
|
||||
h.Logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSources", "invalid").
|
||||
Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, sk := range srcsKaps {
|
||||
if err := ValidSourceRequest(sk.Source); err != nil {
|
||||
return err
|
||||
}
|
||||
// Add any new sources and kapacitors as specified via server flag
|
||||
if err := h.newSourceKapacitor(ctx, sk.Source, sk.Kapacitor); err != nil {
|
||||
// Continue with server run even if adding NewSource fails
|
||||
h.Logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSource", "invalid").
|
||||
Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// newSourceKapacitor adds sources to BoltDB idempotently by name, as well as respective kapacitors
|
||||
func (h *Service) newSourceKapacitor(ctx context.Context, src chronograf.Source, kapa chronograf.Server) error {
|
||||
srcs, err := h.SourcesStore.All(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, s := range srcs {
|
||||
// If source already exists, do nothing
|
||||
if s.Name == src.Name {
|
||||
h.Logger.
|
||||
WithField("component", "server").
|
||||
WithField("NewSource", s.Name).
|
||||
Info("Source already exists")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
src, err = h.SourcesStore.Add(ctx, src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
kapa.SrcID = src.ID
|
||||
if _, err := h.ServersStore.Add(ctx, kapa); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/influxdata/chronograf"
|
||||
"github.com/influxdata/chronograf/mocks"
|
||||
)
|
||||
|
||||
func Test_newSourceResponse(t *testing.T) {
|
||||
|
@ -66,3 +69,180 @@ func Test_newSourceResponse(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestService_newSourceKapacitor(t *testing.T) {
|
||||
type fields struct {
|
||||
SourcesStore chronograf.SourcesStore
|
||||
ServersStore chronograf.ServersStore
|
||||
Logger chronograf.Logger
|
||||
}
|
||||
type args struct {
|
||||
ctx context.Context
|
||||
src chronograf.Source
|
||||
kapa chronograf.Server
|
||||
}
|
||||
srcCount := 0
|
||||
srvCount := 0
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
wantSrc int
|
||||
wantSrv int
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Add when no existing sources",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return []chronograf.Source{}, nil
|
||||
},
|
||||
AddF: func(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
srcCount++
|
||||
src.ID = srcCount
|
||||
return src, nil
|
||||
},
|
||||
},
|
||||
ServersStore: &mocks.ServersStore{
|
||||
AddF: func(ctx context.Context, srv chronograf.Server) (chronograf.Server, error) {
|
||||
srvCount++
|
||||
return srv, nil
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
src: chronograf.Source{
|
||||
Name: "Influx 1",
|
||||
},
|
||||
kapa: chronograf.Server{
|
||||
Name: "Kapa 1",
|
||||
},
|
||||
},
|
||||
wantSrc: 1,
|
||||
wantSrv: 1,
|
||||
},
|
||||
{
|
||||
name: "Should not add if existing source",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return []chronograf.Source{
|
||||
{
|
||||
Name: "Influx 1",
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
AddF: func(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
srcCount++
|
||||
src.ID = srcCount
|
||||
return src, nil
|
||||
},
|
||||
},
|
||||
ServersStore: &mocks.ServersStore{
|
||||
AddF: func(ctx context.Context, srv chronograf.Server) (chronograf.Server, error) {
|
||||
srvCount++
|
||||
return srv, nil
|
||||
},
|
||||
},
|
||||
Logger: &mocks.TestLogger{},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
src: chronograf.Source{
|
||||
Name: "Influx 1",
|
||||
},
|
||||
kapa: chronograf.Server{
|
||||
Name: "Kapa 1",
|
||||
},
|
||||
},
|
||||
wantSrc: 0,
|
||||
wantSrv: 0,
|
||||
},
|
||||
{
|
||||
name: "Error if All returns error",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return nil, fmt.Errorf("error")
|
||||
},
|
||||
},
|
||||
Logger: &mocks.TestLogger{},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Error if Add returns error",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return []chronograf.Source{}, nil
|
||||
},
|
||||
AddF: func(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
return chronograf.Source{}, fmt.Errorf("error")
|
||||
},
|
||||
},
|
||||
Logger: &mocks.TestLogger{},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "Error if kapa add is error",
|
||||
fields: fields{
|
||||
SourcesStore: &mocks.SourcesStore{
|
||||
AllF: func(ctx context.Context) ([]chronograf.Source, error) {
|
||||
return []chronograf.Source{}, nil
|
||||
},
|
||||
AddF: func(ctx context.Context, src chronograf.Source) (chronograf.Source, error) {
|
||||
srcCount++
|
||||
src.ID = srcCount
|
||||
return src, nil
|
||||
},
|
||||
},
|
||||
ServersStore: &mocks.ServersStore{
|
||||
AddF: func(ctx context.Context, srv chronograf.Server) (chronograf.Server, error) {
|
||||
srvCount++
|
||||
return chronograf.Server{}, fmt.Errorf("error")
|
||||
},
|
||||
},
|
||||
Logger: &mocks.TestLogger{},
|
||||
},
|
||||
args: args{
|
||||
ctx: context.Background(),
|
||||
src: chronograf.Source{
|
||||
Name: "Influx 1",
|
||||
},
|
||||
kapa: chronograf.Server{
|
||||
Name: "Kapa 1",
|
||||
},
|
||||
},
|
||||
wantSrc: 1,
|
||||
wantSrv: 1,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
srcCount = 0
|
||||
srvCount = 0
|
||||
h := &Service{
|
||||
SourcesStore: tt.fields.SourcesStore,
|
||||
ServersStore: tt.fields.ServersStore,
|
||||
Logger: tt.fields.Logger,
|
||||
}
|
||||
if err := h.newSourceKapacitor(tt.args.ctx, tt.args.src, tt.args.kapa); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Service.newSourceKapacitor() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
if tt.wantSrc != srcCount {
|
||||
t.Errorf("Service.newSourceKapacitor() count = %d, wantSrc %d", srcCount, tt.wantSrc)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
8083
server/swagger.json
8083
server/swagger.json
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue