From 5858292bb3ed81ffa1dbe770cb9f4927cef8ea68 Mon Sep 17 00:00:00 2001 From: Nick Chen Date: Mon, 12 Dec 2022 09:44:35 -0800 Subject: [PATCH 1/2] fix: detect nginx deletes and use the new binary path --- src/core/nginx.go | 33 +++++++++++++++---- src/core/nginx_test.go | 27 +++++++++++++++ .../nginx/agent/v2/src/core/nginx.go | 33 +++++++++++++++---- .../nginx/agent/v2/src/plugins/nginx.go | 2 +- 4 files changed, 80 insertions(+), 15 deletions(-) diff --git a/src/core/nginx.go b/src/core/nginx.go index 93cd0eca4..a1a432f11 100644 --- a/src/core/nginx.go +++ b/src/core/nginx.go @@ -132,12 +132,7 @@ func (n *NginxBinaryType) GetChildProcesses() map[string][]*proto.NginxDetails { } func (n *NginxBinaryType) GetNginxIDForProcess(nginxProcess Process) string { - defaulted := false - if nginxProcess.Path == "" { - nginxProcess.Path = defaultToNginxCommandForProcessPath() - defaulted = true - } - + defaulted := n.sanitizeProcessPath(&nginxProcess) info := n.getNginxInfoFrom(nginxProcess.Path) // reset the process path from the default to what NGINX tells us @@ -160,13 +155,21 @@ func (n *NginxBinaryType) GetNginxDetailsByID(nginxID string) *proto.NginxDetail return n.nginxDetailsMap[nginxID] } -func (n *NginxBinaryType) GetNginxDetailsFromProcess(nginxProcess Process) *proto.NginxDetails { +func (n *NginxBinaryType) sanitizeProcessPath(nginxProcess *Process) bool { defaulted := false if nginxProcess.Path == "" { nginxProcess.Path = defaultToNginxCommandForProcessPath() defaulted = true } + if strings.Contains(nginxProcess.Path, execDeleted) { + log.Infof("nginx was upgraded (process), using new info") + nginxProcess.Path = sanitizeExecDeletedPath(nginxProcess.Path) + } + return defaulted +} +func (n *NginxBinaryType) GetNginxDetailsFromProcess(nginxProcess Process) *proto.NginxDetails { + defaulted := n.sanitizeProcessPath(&nginxProcess) info := n.getNginxInfoFrom(nginxProcess.Path) // reset the process path from the default to what NGINX tells us @@ -537,6 +540,10 @@ func (n *NginxBinaryType) getNginxInfoFrom(ngxExe string) *nginxInfo { if ngxExe == "" { return &nginxInfo{} } + if strings.Contains(ngxExe, execDeleted) { + log.Infof("nginx was upgraded, using new info") + ngxExe = sanitizeExecDeletedPath(ngxExe) + } if info, ok := n.nginxInfoMap[ngxExe]; ok { stat, err := os.Stat(ngxExe) if err == nil && stat.ModTime().Equal(info.mtime) { @@ -554,6 +561,18 @@ func (n *NginxBinaryType) getNginxInfoFrom(ngxExe string) *nginxInfo { return info } +const ( + execDeleted = "(deleted)" +) + +func sanitizeExecDeletedPath(exe string) string { + firstSpace := strings.Index(exe, execDeleted) + if firstSpace != -1 { + return strings.TrimSpace(exe[0:firstSpace]) + } + return strings.TrimSpace(exe) +} + // getNginxInfoFromBuffer - func (n *NginxBinaryType) getNginxInfoFromBuffer(exePath string, buffer *bytes.Buffer) *nginxInfo { info := &nginxInfo{} diff --git a/src/core/nginx_test.go b/src/core/nginx_test.go index 7a260ed6f..bf8b8eee7 100644 --- a/src/core/nginx_test.go +++ b/src/core/nginx_test.go @@ -744,3 +744,30 @@ func buildConfig(rootDirectory string) (*proto.NginxConfig, error) { return nginxConfig, nil } + +// TestNginxBinaryType_sanitizeProcessPath validate correct parsing of the nginx path when nginx binary has been updated. +func TestNginxBinaryType_sanitizeProcessPath(t *testing.T) { + type testDef struct { + desc string + path string + expect string + defaulted bool + } + + // no test case for process lookup, that would require running nginx or proc some where + for _, def := range []testDef{ + {desc: "deleted path", path: "/usr/sbin/nginx (deleted)", expect: "/usr/sbin/nginx"}, + {desc: "no change path", path: "/usr/sbin/nginx", expect: "/usr/sbin/nginx"}, + } { + t.Run(def.desc, func(tt *testing.T) { + p := Process{ + Path: def.path, + } + binary := NginxBinaryType{ + env: &EnvironmentType{}, + } + assert.Equal(tt, def.defaulted, binary.sanitizeProcessPath(&p)) + assert.Equal(tt, def.expect, p.Path) + }) + } +} diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/core/nginx.go b/test/performance/vendor/github.com/nginx/agent/v2/src/core/nginx.go index 93cd0eca4..a1a432f11 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/core/nginx.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/core/nginx.go @@ -132,12 +132,7 @@ func (n *NginxBinaryType) GetChildProcesses() map[string][]*proto.NginxDetails { } func (n *NginxBinaryType) GetNginxIDForProcess(nginxProcess Process) string { - defaulted := false - if nginxProcess.Path == "" { - nginxProcess.Path = defaultToNginxCommandForProcessPath() - defaulted = true - } - + defaulted := n.sanitizeProcessPath(&nginxProcess) info := n.getNginxInfoFrom(nginxProcess.Path) // reset the process path from the default to what NGINX tells us @@ -160,13 +155,21 @@ func (n *NginxBinaryType) GetNginxDetailsByID(nginxID string) *proto.NginxDetail return n.nginxDetailsMap[nginxID] } -func (n *NginxBinaryType) GetNginxDetailsFromProcess(nginxProcess Process) *proto.NginxDetails { +func (n *NginxBinaryType) sanitizeProcessPath(nginxProcess *Process) bool { defaulted := false if nginxProcess.Path == "" { nginxProcess.Path = defaultToNginxCommandForProcessPath() defaulted = true } + if strings.Contains(nginxProcess.Path, execDeleted) { + log.Infof("nginx was upgraded (process), using new info") + nginxProcess.Path = sanitizeExecDeletedPath(nginxProcess.Path) + } + return defaulted +} +func (n *NginxBinaryType) GetNginxDetailsFromProcess(nginxProcess Process) *proto.NginxDetails { + defaulted := n.sanitizeProcessPath(&nginxProcess) info := n.getNginxInfoFrom(nginxProcess.Path) // reset the process path from the default to what NGINX tells us @@ -537,6 +540,10 @@ func (n *NginxBinaryType) getNginxInfoFrom(ngxExe string) *nginxInfo { if ngxExe == "" { return &nginxInfo{} } + if strings.Contains(ngxExe, execDeleted) { + log.Infof("nginx was upgraded, using new info") + ngxExe = sanitizeExecDeletedPath(ngxExe) + } if info, ok := n.nginxInfoMap[ngxExe]; ok { stat, err := os.Stat(ngxExe) if err == nil && stat.ModTime().Equal(info.mtime) { @@ -554,6 +561,18 @@ func (n *NginxBinaryType) getNginxInfoFrom(ngxExe string) *nginxInfo { return info } +const ( + execDeleted = "(deleted)" +) + +func sanitizeExecDeletedPath(exe string) string { + firstSpace := strings.Index(exe, execDeleted) + if firstSpace != -1 { + return strings.TrimSpace(exe[0:firstSpace]) + } + return strings.TrimSpace(exe) +} + // getNginxInfoFromBuffer - func (n *NginxBinaryType) getNginxInfoFromBuffer(exePath string, buffer *bytes.Buffer) *nginxInfo { info := &nginxInfo{} diff --git a/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/nginx.go b/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/nginx.go index 334c9653b..66c36c7a9 100644 --- a/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/nginx.go +++ b/test/performance/vendor/github.com/nginx/agent/v2/src/plugins/nginx.go @@ -326,7 +326,7 @@ func (n *Nginx) applyConfig(cmd *proto.Command, cfg *proto.Command_NginxConfig) status.NginxConfigResponse.Status = newErrStatus(fmt.Sprintf("Config apply failed (preflight): not able to read WAF file in metadata %v", config.GetConfigData())).CmdStatus return status } - if n.wafVersion != napMetaData.NapVersion { + if napMetaData.NapVersion != "" && n.wafVersion != napMetaData.NapVersion { status.NginxConfigResponse.Status = newErrStatus(fmt.Sprintf("Config apply failed (preflight): config metadata mismatch %v", config.GetConfigData())).CmdStatus return status } From ed34cc17bac0ae57323ebd067bd9892cc0c20ae9 Mon Sep 17 00:00:00 2001 From: Nick Chen Date: Mon, 12 Dec 2022 09:46:29 -0800 Subject: [PATCH 2/2] fix: change log entry to debug --- src/core/nginx.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/nginx.go b/src/core/nginx.go index a1a432f11..25d337ec0 100644 --- a/src/core/nginx.go +++ b/src/core/nginx.go @@ -162,7 +162,7 @@ func (n *NginxBinaryType) sanitizeProcessPath(nginxProcess *Process) bool { defaulted = true } if strings.Contains(nginxProcess.Path, execDeleted) { - log.Infof("nginx was upgraded (process), using new info") + log.Debugf("nginx was upgraded (process), using new info") nginxProcess.Path = sanitizeExecDeletedPath(nginxProcess.Path) } return defaulted