{"id":7,"date":"2026-04-20T09:35:56","date_gmt":"2026-04-20T08:35:56","guid":{"rendered":"http:\/\/ganesh.ltm.publicvm.com\/index.php\/2026\/04\/20\/how-i-fixed-nap-v5-security-monitoring-in-nim-on-aks\/"},"modified":"2026-04-20T09:35:56","modified_gmt":"2026-04-20T08:35:56","slug":"how-i-fixed-nap-v5-security-monitoring-in-nim-on-aks","status":"publish","type":"post","link":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/2026\/04\/20\/how-i-fixed-nap-v5-security-monitoring-in-nim-on-aks\/","title":{"rendered":"How I Fixed NAP v5 Security Monitoring in NIM on AKS"},"content":{"rendered":"<h2>Background<\/h2>\n<p>I was tasked with integrating NGINX App Protect (NAP) v5 with NGINX Instance Manager (NIM) 2.21 Security Monitoring on an AKS cluster. The goal: WAF security events from NAP should appear in the NIM Security Monitoring dashboard in real time.<\/p>\n<h2>The Architecture<\/h2>\n<p>The setup involved three main components running as a 3-container pod in Kubernetes:<\/p>\n<ul>\n<li><strong>nginx-plus<\/strong> &#8211; NGINX Plus R36-P3 with App Protect module<\/li>\n<li><strong>waf-enforcer<\/strong> &#8211; NAP v5 enforcement engine<\/li>\n<li><strong>waf-config-mgr<\/strong> &#8211; Policy configuration manager<\/li>\n<\/ul>\n<p>NIM 2.21 runs separately with ClickHouse as the backend for security event storage, and nginx-agent v2.46.1 is supposed to forward events from NAP to NIM via a syslog listener on port 5514.<\/p>\n<h2>The Problem<\/h2>\n<p>WAF attacks were being blocked by NAP, but zero events appeared in NIM Security Monitoring. The nginx-agent was running but the syslog listener on port 5514 was never starting.<\/p>\n<h2>Root Cause Investigation<\/h2>\n<p>After deep investigation including analyzing the DPM dqlite database, I found the root cause: the NIM license was a null placeholder with current_report_type=initial and no JWT token. This caused DPM entitlement check to fail, which blocked the nginx-app-protect feature from being granted to nginx-agent, which meant the syslog listener on port 5514 never started.<\/p>\n<h2>The Fix<\/h2>\n<p>Since fixing the license required vendor involvement, I implemented a Python-based NAP event forwarder as a workaround:<\/p>\n<ol>\n<li>Changed NAP security log from syslog to file-based logging<\/li>\n<li>Wrote a Python script nap_forwarder.py that tails the security log file<\/li>\n<li>The script parses NAP key=value log format and maps fields to ClickHouse schema<\/li>\n<li>Events are inserted directly into ClickHouse nms.v4_security_events via HTTP API<\/li>\n<li>Deployed via ConfigMap mounted into the nginx-plus container<\/li>\n<\/ol>\n<h2>Result<\/h2>\n<p>Within minutes, WAF security events started appearing in NIM Security Monitoring dashboard. The solution bypassed the broken DPM license chain entirely while maintaining full event visibility for security operations.<\/p>\n<h2>Key Takeaways<\/h2>\n<ul>\n<li>Always verify DPM license entitlements when nginx-agent features are missing<\/li>\n<li>NAP v5 syslog forwarding depends on DPM granting the nginx-app-protect feature<\/li>\n<li>Direct ClickHouse insertion is a viable workaround for broken agent pipelines<\/li>\n<li>Understanding the full data flow is essential for troubleshooting complex multi-component systems<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Background I was tasked with integrating NGINX App Protect (NAP) v5 with NGINX Instance Manager (NIM) 2.21 Security Monitoring on an AKS cluster. The goal: WAF security events from NAP should appear in the NIM Security Monitoring dashboard in real time. The Architecture The setup involved three main components running as a 3-container pod in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-7","post","type-post","status-publish","format-standard","hentry","category-uncategorised"],"_links":{"self":[{"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/posts\/7","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/comments?post=7"}],"version-history":[{"count":0,"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/posts\/7\/revisions"}],"wp:attachment":[{"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/media?parent=7"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/categories?post=7"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ganesh.ltm.publicvm.com\/index.php\/wp-json\/wp\/v2\/tags?post=7"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}