diff --git a/admin/commands/management/register.go b/admin/commands/management/register.go index 95b3bfe98a..b3b6c32745 100644 --- a/admin/commands/management/register.go +++ b/admin/commands/management/register.go @@ -28,12 +28,16 @@ var registerResultT = commands.ParseTemplate(` pmm-agent registered. pmm-agent ID: {{ .PMMAgent.AgentID }} Node ID : {{ .PMMAgent.RunsOnNodeID }} +{{ if .Warning }} +Warning: {{ .Warning }} +{{- end -}} `) type registerResult struct { GenericNode *node.RegisterNodeOKBodyGenericNode `json:"generic_node"` ContainerNode *node.RegisterNodeOKBodyContainerNode `json:"container_node"` PMMAgent *node.RegisterNodeOKBodyPMMAgent `json:"pmm_agent"` + Warning string `json:"warning"` } func (res *registerResult) Result() {} @@ -96,5 +100,6 @@ func (cmd *RegisterCommand) RunCmd() (commands.Result, error) { GenericNode: resp.Payload.GenericNode, ContainerNode: resp.Payload.ContainerNode, PMMAgent: resp.Payload.PMMAgent, + Warning: resp.Payload.Warning, }, nil } diff --git a/admin/commands/management/register_test.go b/admin/commands/management/register_test.go new file mode 100644 index 0000000000..9d4993be13 --- /dev/null +++ b/admin/commands/management/register_test.go @@ -0,0 +1,51 @@ +package management + +import ( + "github.com/percona/pmm/api/managementpb/json/client/node" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestRegisterResult(t *testing.T) { + tests := []struct { + name string + result registerResult + want string + }{ + { + name: "Success", + result: registerResult{ + PMMAgent: &node.RegisterNodeOKBodyPMMAgent{ + AgentID: "/agent_id/new_id", + RunsOnNodeID: "/node_id/second_id", + }, + Warning: "", + }, + want: `pmm-agent registered. +pmm-agent ID: /agent_id/new_id +Node ID : /node_id/second_id +`, + }, + { + name: "With warning", + result: registerResult{ + PMMAgent: &node.RegisterNodeOKBodyPMMAgent{ + AgentID: "/agent_id/warning", + RunsOnNodeID: "/node_id/warning_node", + }, + Warning: "Couldn't create Admin API Key", + }, + want: `pmm-agent registered. +pmm-agent ID: /agent_id/warning +Node ID : /node_id/warning_node + +Warning: Couldn't create Admin API Key +`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, tt.result.String(), "String()") + }) + } +} diff --git a/api/managementpb/json/client/node/register_node_responses.go b/api/managementpb/json/client/node/register_node_responses.go index 747c5965d7..4f72dc8936 100644 --- a/api/managementpb/json/client/node/register_node_responses.go +++ b/api/managementpb/json/client/node/register_node_responses.go @@ -463,6 +463,9 @@ type RegisterNodeOKBody struct { // Token represents token for vmagent auth config. Token string `json:"token,omitempty"` + // Warning message. + Warning string `json:"warning,omitempty"` + // container node ContainerNode *RegisterNodeOKBodyContainerNode `json:"container_node,omitempty"` diff --git a/api/managementpb/json/managementpb.json b/api/managementpb/json/managementpb.json index b5c9de7585..556283e58b 100644 --- a/api/managementpb/json/managementpb.json +++ b/api/managementpb/json/managementpb.json @@ -3889,6 +3889,11 @@ "description": "Token represents token for vmagent auth config.", "type": "string", "x-order": 3 + }, + "warning": { + "description": "Warning message.", + "type": "string", + "x-order": 4 } } } diff --git a/api/managementpb/node.pb.go b/api/managementpb/node.pb.go index 2f557c0dab..61784a6679 100644 --- a/api/managementpb/node.pb.go +++ b/api/managementpb/node.pb.go @@ -212,6 +212,8 @@ type RegisterNodeResponse struct { PmmAgent *inventorypb.PMMAgent `protobuf:"bytes,3,opt,name=pmm_agent,json=pmmAgent,proto3" json:"pmm_agent,omitempty"` // Token represents token for vmagent auth config. Token string `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"` + // Warning message. + Warning string `protobuf:"bytes,5,opt,name=warning,proto3" json:"warning,omitempty"` } func (x *RegisterNodeResponse) Reset() { @@ -274,6 +276,13 @@ func (x *RegisterNodeResponse) GetToken() string { return "" } +func (x *RegisterNodeResponse) GetWarning() string { + if x != nil { + return x.Warning + } + return "" +} + var File_managementpb_node_proto protoreflect.FileDescriptor var file_managementpb_node_proto_rawDesc = []byte{ @@ -332,7 +341,7 @@ var file_managementpb_node_proto_rawDesc = []byte{ 0x6d, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xda, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x67, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf4, 0x01, 0x0a, 0x14, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0c, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, @@ -346,28 +355,30 @@ var file_managementpb_node_proto_rawDesc = []byte{ 0x32, 0x13, 0x2e, 0x69, 0x6e, 0x76, 0x65, 0x6e, 0x74, 0x6f, 0x72, 0x79, 0x2e, 0x50, 0x4d, 0x4d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x70, 0x6d, 0x6d, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, - 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x32, 0xba, 0x01, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0xb1, - 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, - 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x67, - 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x20, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x5e, 0x92, 0x41, 0x34, 0x12, 0x0d, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x1a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, - 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, - 0x20, 0x70, 0x6d, 0x6d, 0x2d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x4e, 0x6f, 0x64, 0x65, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, - 0x65, 0x72, 0x42, 0x8c, 0x01, 0x0a, 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, - 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x61, 0x2f, 0x70, 0x6d, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x4d, 0x58, - 0x58, 0xaa, 0x02, 0x0a, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0xca, 0x02, - 0x0a, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0xe2, 0x02, 0x16, 0x4d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x77, 0x61, 0x72, 0x6e, 0x69, 0x6e, 0x67, 0x32, + 0xba, 0x01, 0x0a, 0x04, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0xb1, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x4e, + 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x92, 0x41, + 0x34, 0x12, 0x0d, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4e, 0x6f, 0x64, 0x65, + 0x1a, 0x23, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x73, 0x20, 0x61, 0x20, 0x6e, 0x65, + 0x77, 0x20, 0x4e, 0x6f, 0x64, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 0x6d, 0x6d, 0x2d, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, + 0x2f, 0x76, 0x31, 0x2f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2f, 0x4e, + 0x6f, 0x64, 0x65, 0x2f, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x42, 0x8c, 0x01, 0x0a, + 0x0e, 0x63, 0x6f, 0x6d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, + 0x09, 0x4e, 0x6f, 0x64, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x27, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x61, + 0x2f, 0x70, 0x6d, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x70, 0x62, 0xa2, 0x02, 0x03, 0x4d, 0x58, 0x58, 0xaa, 0x02, 0x0a, 0x4d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0xca, 0x02, 0x0a, 0x4d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0xe2, 0x02, 0x16, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, + 0x0a, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x33, } var ( diff --git a/api/managementpb/node.pb.validate.go b/api/managementpb/node.pb.validate.go index a92c8487c9..1a4e1b48ad 100644 --- a/api/managementpb/node.pb.validate.go +++ b/api/managementpb/node.pb.validate.go @@ -289,6 +289,8 @@ func (m *RegisterNodeResponse) validate(all bool) error { // no validation rules for Token + // no validation rules for Warning + if len(errors) > 0 { return RegisterNodeResponseMultiError(errors) } diff --git a/api/managementpb/node.proto b/api/managementpb/node.proto index ddb52efe7a..5118d9bd03 100644 --- a/api/managementpb/node.proto +++ b/api/managementpb/node.proto @@ -52,6 +52,8 @@ message RegisterNodeResponse { inventory.PMMAgent pmm_agent = 3; // Token represents token for vmagent auth config. string token = 4; + // Warning message. + string warning = 5; } // Node service provides public Management API methods for Nodes. diff --git a/api/swagger/swagger-dev.json b/api/swagger/swagger-dev.json index 8801f4cba5..a47123b3d6 100644 --- a/api/swagger/swagger-dev.json +++ b/api/swagger/swagger-dev.json @@ -26884,6 +26884,11 @@ "description": "Token represents token for vmagent auth config.", "type": "string", "x-order": 3 + }, + "warning": { + "description": "Warning message.", + "type": "string", + "x-order": 4 } } } diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index f1e0ccb21b..103e748693 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -18053,6 +18053,11 @@ "description": "Token represents token for vmagent auth config.", "type": "string", "x-order": 3 + }, + "warning": { + "description": "Warning message.", + "type": "string", + "x-order": 4 } } } diff --git a/managed/services/grafana/auth_server.go b/managed/services/grafana/auth_server.go index 72d0368b00..2456a771b3 100644 --- a/managed/services/grafana/auth_server.go +++ b/managed/services/grafana/auth_server.go @@ -533,15 +533,7 @@ func cleanPath(p string) (string, error) { func (s *AuthServer) getAuthUser(ctx context.Context, req *http.Request, l *logrus.Entry) (*authUser, *authError) { // check Grafana with some headers from request - authHeaders := make(http.Header) - for _, k := range []string{ - "Authorization", - "Cookie", - } { - if v := req.Header.Get(k); v != "" { - authHeaders.Set(k, v) - } - } + authHeaders := s.authHeaders(req) j, err := json.Marshal(authHeaders) if err != nil { l.Warnf("%s", err) @@ -558,6 +550,19 @@ func (s *AuthServer) getAuthUser(ctx context.Context, req *http.Request, l *logr return s.retrieveRole(ctx, hash, authHeaders, l) } +func (s *AuthServer) authHeaders(req *http.Request) http.Header { + authHeaders := make(http.Header) + for _, k := range []string{ + "Authorization", + "Cookie", + } { + if v := req.Header.Get(k); v != "" { + authHeaders.Set(k, v) + } + } + return authHeaders +} + func (s *AuthServer) retrieveRole(ctx context.Context, hash string, authHeaders http.Header, l *logrus.Entry) (*authUser, *authError) { authUser, err := s.c.getAuthUser(ctx, authHeaders) if err != nil { diff --git a/managed/services/grafana/client.go b/managed/services/grafana/client.go index 4287f6942e..71f4e1e0d3 100644 --- a/managed/services/grafana/client.go +++ b/managed/services/grafana/client.go @@ -219,7 +219,7 @@ func (c *Client) GetUserID(ctx context.Context) (int, error) { // Ctx is used only for cancelation. func (c *Client) getAuthUser(ctx context.Context, authHeaders http.Header) (authUser, error) { // Check if it's API Key - if c.isAPIKeyAuth(authHeaders.Get("Authorization")) { + if c.IsAPIKeyAuth(authHeaders) { role, err := c.getRoleForAPIKey(ctx, authHeaders) return authUser{ role: role, @@ -277,7 +277,9 @@ func (c *Client) getAuthUser(ctx context.Context, authHeaders http.Header) (auth }, nil } -func (c *Client) isAPIKeyAuth(authHeader string) bool { +// IsAPIKeyAuth checks if the request made using API Key. +func (c *Client) IsAPIKeyAuth(headers http.Header) bool { + authHeader := headers.Get("Authorization") switch { case strings.HasPrefix(authHeader, "Bearer"): return true diff --git a/managed/services/management/mock_agents_registry_test.go b/managed/services/management/mock_agents_registry_test.go deleted file mode 100644 index 389a81139a..0000000000 --- a/managed/services/management/mock_agents_registry_test.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// mockAgentsRegistry is an autogenerated mock type for the agentsRegistry type -type mockAgentsRegistry struct { - mock.Mock -} - -// IsConnected provides a mock function with given fields: pmmAgentID -func (_m *mockAgentsRegistry) IsConnected(pmmAgentID string) bool { - ret := _m.Called(pmmAgentID) - - var r0 bool - if rf, ok := ret.Get(0).(func(string) bool); ok { - r0 = rf(pmmAgentID) - } else { - r0 = ret.Get(0).(bool) - } - - return r0 -} - -// Kick provides a mock function with given fields: ctx, pmmAgentID -func (_m *mockAgentsRegistry) Kick(ctx context.Context, pmmAgentID string) { - _m.Called(ctx, pmmAgentID) -} - -// newMockAgentsRegistry creates a new instance of mockAgentsRegistry. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockAgentsRegistry(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockAgentsRegistry { - mock := &mockAgentsRegistry{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_agents_state_updater_test.go b/managed/services/management/mock_agents_state_updater_test.go deleted file mode 100644 index 2115c2a4a8..0000000000 --- a/managed/services/management/mock_agents_state_updater_test.go +++ /dev/null @@ -1,34 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// mockAgentsStateUpdater is an autogenerated mock type for the agentsStateUpdater type -type mockAgentsStateUpdater struct { - mock.Mock -} - -// RequestStateUpdate provides a mock function with given fields: ctx, pmmAgentID -func (_m *mockAgentsStateUpdater) RequestStateUpdate(ctx context.Context, pmmAgentID string) { - _m.Called(ctx, pmmAgentID) -} - -// newMockAgentsStateUpdater creates a new instance of mockAgentsStateUpdater. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockAgentsStateUpdater(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockAgentsStateUpdater { - mock := &mockAgentsStateUpdater{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_api_key_provider_test.go b/managed/services/management/mock_api_key_provider_test.go deleted file mode 100644 index 45ebeb1966..0000000000 --- a/managed/services/management/mock_api_key_provider_test.go +++ /dev/null @@ -1,60 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// mockApiKeyProvider is an autogenerated mock type for the apiKeyProvider type -type mockApiKeyProvider struct { - mock.Mock -} - -// CreateAdminAPIKey provides a mock function with given fields: ctx, name -func (_m *mockApiKeyProvider) CreateAdminAPIKey(ctx context.Context, name string) (int64, string, error) { - ret := _m.Called(ctx, name) - - var r0 int64 - var r1 string - var r2 error - if rf, ok := ret.Get(0).(func(context.Context, string) (int64, string, error)); ok { - return rf(ctx, name) - } - if rf, ok := ret.Get(0).(func(context.Context, string) int64); ok { - r0 = rf(ctx, name) - } else { - r0 = ret.Get(0).(int64) - } - - if rf, ok := ret.Get(1).(func(context.Context, string) string); ok { - r1 = rf(ctx, name) - } else { - r1 = ret.Get(1).(string) - } - - if rf, ok := ret.Get(2).(func(context.Context, string) error); ok { - r2 = rf(ctx, name) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// newMockApiKeyProvider creates a new instance of mockApiKeyProvider. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockApiKeyProvider(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockApiKeyProvider { - mock := &mockApiKeyProvider{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_checks_service_test.go b/managed/services/management/mock_checks_service_test.go deleted file mode 100644 index d28cd5cb01..0000000000 --- a/managed/services/management/mock_checks_service_test.go +++ /dev/null @@ -1,218 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - - check "github.com/percona-platform/saas/pkg/check" - mock "github.com/stretchr/testify/mock" - - services "github.com/percona/pmm/managed/services" -) - -// mockChecksService is an autogenerated mock type for the checksService type -type mockChecksService struct { - mock.Mock -} - -// ChangeInterval provides a mock function with given fields: params -func (_m *mockChecksService) ChangeInterval(params map[string]check.Interval) error { - ret := _m.Called(params) - - var r0 error - if rf, ok := ret.Get(0).(func(map[string]check.Interval) error); ok { - r0 = rf(params) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// DisableChecks provides a mock function with given fields: checkNames -func (_m *mockChecksService) DisableChecks(checkNames []string) error { - ret := _m.Called(checkNames) - - var r0 error - if rf, ok := ret.Get(0).(func([]string) error); ok { - r0 = rf(checkNames) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// EnableChecks provides a mock function with given fields: checkNames -func (_m *mockChecksService) EnableChecks(checkNames []string) error { - ret := _m.Called(checkNames) - - var r0 error - if rf, ok := ret.Get(0).(func([]string) error); ok { - r0 = rf(checkNames) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// GetAdvisors provides a mock function with given fields: -func (_m *mockChecksService) GetAdvisors() ([]check.Advisor, error) { - ret := _m.Called() - - var r0 []check.Advisor - var r1 error - if rf, ok := ret.Get(0).(func() ([]check.Advisor, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() []check.Advisor); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]check.Advisor) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetChecks provides a mock function with given fields: -func (_m *mockChecksService) GetChecks() (map[string]check.Check, error) { - ret := _m.Called() - - var r0 map[string]check.Check - var r1 error - if rf, ok := ret.Get(0).(func() (map[string]check.Check, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() map[string]check.Check); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(map[string]check.Check) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetChecksResults provides a mock function with given fields: ctx, serviceID -func (_m *mockChecksService) GetChecksResults(ctx context.Context, serviceID string) ([]services.CheckResult, error) { - ret := _m.Called(ctx, serviceID) - - var r0 []services.CheckResult - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, string) ([]services.CheckResult, error)); ok { - return rf(ctx, serviceID) - } - if rf, ok := ret.Get(0).(func(context.Context, string) []services.CheckResult); ok { - r0 = rf(ctx, serviceID) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]services.CheckResult) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { - r1 = rf(ctx, serviceID) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetDisabledChecks provides a mock function with given fields: -func (_m *mockChecksService) GetDisabledChecks() ([]string, error) { - ret := _m.Called() - - var r0 []string - var r1 error - if rf, ok := ret.Get(0).(func() ([]string, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() []string); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]string) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// GetSecurityCheckResults provides a mock function with given fields: -func (_m *mockChecksService) GetSecurityCheckResults() ([]services.CheckResult, error) { - ret := _m.Called() - - var r0 []services.CheckResult - var r1 error - if rf, ok := ret.Get(0).(func() ([]services.CheckResult, error)); ok { - return rf() - } - if rf, ok := ret.Get(0).(func() []services.CheckResult); ok { - r0 = rf() - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]services.CheckResult) - } - } - - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// StartChecks provides a mock function with given fields: checkNames -func (_m *mockChecksService) StartChecks(checkNames []string) error { - ret := _m.Called(checkNames) - - var r0 error - if rf, ok := ret.Get(0).(func([]string) error); ok { - r0 = rf(checkNames) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// newMockChecksService creates a new instance of mockChecksService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockChecksService(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockChecksService { - mock := &mockChecksService{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_connection_checker_test.go b/managed/services/management/mock_connection_checker_test.go deleted file mode 100644 index 89be9f50d8..0000000000 --- a/managed/services/management/mock_connection_checker_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" - reform "gopkg.in/reform.v1" - - models "github.com/percona/pmm/managed/models" -) - -// mockConnectionChecker is an autogenerated mock type for the connectionChecker type -type mockConnectionChecker struct { - mock.Mock -} - -// CheckConnectionToService provides a mock function with given fields: ctx, q, service, agent -func (_m *mockConnectionChecker) CheckConnectionToService(ctx context.Context, q *reform.Querier, service *models.Service, agent *models.Agent) error { - ret := _m.Called(ctx, q, service, agent) - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, *reform.Querier, *models.Service, *models.Agent) error); ok { - r0 = rf(ctx, q, service, agent) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// newMockConnectionChecker creates a new instance of mockConnectionChecker. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockConnectionChecker(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockConnectionChecker { - mock := &mockConnectionChecker{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_grafana_client_test.go b/managed/services/management/mock_grafana_client_test.go deleted file mode 100644 index d170c74447..0000000000 --- a/managed/services/management/mock_grafana_client_test.go +++ /dev/null @@ -1,54 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - time "time" - - mock "github.com/stretchr/testify/mock" -) - -// mockGrafanaClient is an autogenerated mock type for the grafanaClient type -type mockGrafanaClient struct { - mock.Mock -} - -// CreateAnnotation provides a mock function with given fields: _a0, _a1, _a2, _a3, _a4 -func (_m *mockGrafanaClient) CreateAnnotation(_a0 context.Context, _a1 []string, _a2 time.Time, _a3 string, _a4 string) (string, error) { - ret := _m.Called(_a0, _a1, _a2, _a3, _a4) - - var r0 string - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []string, time.Time, string, string) (string, error)); ok { - return rf(_a0, _a1, _a2, _a3, _a4) - } - if rf, ok := ret.Get(0).(func(context.Context, []string, time.Time, string, string) string); ok { - r0 = rf(_a0, _a1, _a2, _a3, _a4) - } else { - r0 = ret.Get(0).(string) - } - - if rf, ok := ret.Get(1).(func(context.Context, []string, time.Time, string, string) error); ok { - r1 = rf(_a0, _a1, _a2, _a3, _a4) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// newMockGrafanaClient creates a new instance of mockGrafanaClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockGrafanaClient(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockGrafanaClient { - mock := &mockGrafanaClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_jobs_service_test.go b/managed/services/management/mock_jobs_service_test.go deleted file mode 100644 index 67acf51ef5..0000000000 --- a/managed/services/management/mock_jobs_service_test.go +++ /dev/null @@ -1,39 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import mock "github.com/stretchr/testify/mock" - -// mockJobsService is an autogenerated mock type for the jobsService type -type mockJobsService struct { - mock.Mock -} - -// StopJob provides a mock function with given fields: jobID -func (_m *mockJobsService) StopJob(jobID string) error { - ret := _m.Called(jobID) - - var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(jobID) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// newMockJobsService creates a new instance of mockJobsService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockJobsService(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockJobsService { - mock := &mockJobsService{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_prometheus_service_test.go b/managed/services/management/mock_prometheus_service_test.go deleted file mode 100644 index 974768fb28..0000000000 --- a/managed/services/management/mock_prometheus_service_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import mock "github.com/stretchr/testify/mock" - -// mockPrometheusService is an autogenerated mock type for the prometheusService type -type mockPrometheusService struct { - mock.Mock -} - -// RequestConfigurationUpdate provides a mock function with given fields: -func (_m *mockPrometheusService) RequestConfigurationUpdate() { - _m.Called() -} - -// newMockPrometheusService creates a new instance of mockPrometheusService. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockPrometheusService(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockPrometheusService { - mock := &mockPrometheusService{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_version_cache_test.go b/managed/services/management/mock_version_cache_test.go deleted file mode 100644 index fd25485e30..0000000000 --- a/managed/services/management/mock_version_cache_test.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import mock "github.com/stretchr/testify/mock" - -// mockVersionCache is an autogenerated mock type for the versionCache type -type mockVersionCache struct { - mock.Mock -} - -// RequestSoftwareVersionsUpdate provides a mock function with given fields: -func (_m *mockVersionCache) RequestSoftwareVersionsUpdate() { - _m.Called() -} - -// newMockVersionCache creates a new instance of mockVersionCache. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockVersionCache(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockVersionCache { - mock := &mockVersionCache{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/mock_victoria_metrics_client_test.go b/managed/services/management/mock_victoria_metrics_client_test.go deleted file mode 100644 index f94d27b297..0000000000 --- a/managed/services/management/mock_victoria_metrics_client_test.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package management - -import ( - context "context" - time "time" - - v1 "github.com/prometheus/client_golang/api/prometheus/v1" - model "github.com/prometheus/common/model" - mock "github.com/stretchr/testify/mock" -) - -// mockVictoriaMetricsClient is an autogenerated mock type for the victoriaMetricsClient type -type mockVictoriaMetricsClient struct { - mock.Mock -} - -// Query provides a mock function with given fields: ctx, query, ts, opts -func (_m *mockVictoriaMetricsClient) Query(ctx context.Context, query string, ts time.Time, opts ...v1.Option) (model.Value, v1.Warnings, error) { - _va := make([]interface{}, len(opts)) - for _i := range opts { - _va[_i] = opts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, query, ts) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) - - var r0 model.Value - var r1 v1.Warnings - var r2 error - if rf, ok := ret.Get(0).(func(context.Context, string, time.Time, ...v1.Option) (model.Value, v1.Warnings, error)); ok { - return rf(ctx, query, ts, opts...) - } - if rf, ok := ret.Get(0).(func(context.Context, string, time.Time, ...v1.Option) model.Value); ok { - r0 = rf(ctx, query, ts, opts...) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(model.Value) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, string, time.Time, ...v1.Option) v1.Warnings); ok { - r1 = rf(ctx, query, ts, opts...) - } else { - if ret.Get(1) != nil { - r1 = ret.Get(1).(v1.Warnings) - } - } - - if rf, ok := ret.Get(2).(func(context.Context, string, time.Time, ...v1.Option) error); ok { - r2 = rf(ctx, query, ts, opts...) - } else { - r2 = ret.Error(2) - } - - return r0, r1, r2 -} - -// newMockVictoriaMetricsClient creates a new instance of mockVictoriaMetricsClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func newMockVictoriaMetricsClient(t interface { - mock.TestingT - Cleanup(func()) -}, -) *mockVictoriaMetricsClient { - mock := &mockVictoriaMetricsClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/managed/services/management/node.go b/managed/services/management/node.go index 0c17d5e3ea..9116888983 100644 --- a/managed/services/management/node.go +++ b/managed/services/management/node.go @@ -19,9 +19,12 @@ import ( "context" "fmt" "math/rand" + "net/http" "github.com/AlekSi/pointer" + "github.com/sirupsen/logrus" "google.golang.org/grpc/codes" + "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "gopkg.in/reform.v1" @@ -35,6 +38,7 @@ import ( type apiKeyProvider interface { CreateAdminAPIKey(ctx context.Context, name string) (int64, string, error) + IsAPIKeyAuth(headers http.Header) bool } // NodeService represents service for working with nodes. @@ -136,10 +140,25 @@ func (s *NodeService) Register(ctx context.Context, req *managementpb.RegisterNo return nil, e } - apiKeyName := fmt.Sprintf("pmm-agent-%s-%d", req.NodeName, rand.Int63()) //nolint:gosec - _, res.Token, e = s.akp.CreateAdminAPIKey(ctx, apiKeyName) - if e != nil { - return nil, e + // get authorization from headers. + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, fmt.Errorf("cannot get headers from metadata") + } + authorizationHeaders := md.Get("Authorization") + if len(authorizationHeaders) == 0 { + return nil, status.Error(codes.Unauthenticated, "Authorization error.") + } + var headers http.Header + headers.Set("Authorization", authorizationHeaders[0]) + if !s.akp.IsAPIKeyAuth(headers) { + apiKeyName := fmt.Sprintf("pmm-agent-%s-%d", req.NodeName, rand.Int63()) //nolint:gosec + _, res.Token, e = s.akp.CreateAdminAPIKey(ctx, apiKeyName) + if e != nil { + msg := fmt.Sprintf("Couldn't create Admin API Key: %s", e) + logrus.Errorln(msg) + res.Warning = msg + } } return res, nil