Skip to content

Commit 8a918e5

Browse files
Added NAP V5 support: Lookup for docker0 interface IP, if configured
1 parent ef3e4c1 commit 8a918e5

File tree

2 files changed

+120
-10
lines changed

2 files changed

+120
-10
lines changed

internal/datasource/config/nginx_config_parser.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ var globFunction = func(path string) ([]string, error) {
7373
type (
7474
NginxConfigParser struct {
7575
agentConfig *config.Config
76+
docker0IP string
7677
}
7778
)
7879

@@ -102,9 +103,35 @@ type createAPIDetailsParams struct {
102103
func NewNginxConfigParser(agentConfig *config.Config) *NginxConfigParser {
103104
return &NginxConfigParser{
104105
agentConfig: agentConfig,
106+
docker0IP: getDocker0IP(),
105107
}
106108
}
107109

110+
// getDocker0IP discovers the docker0 interface IP address
111+
// Returns empty string if docker0 interface is not found
112+
func getDocker0IP() string {
113+
ifaces, err := net.Interfaces()
114+
if err != nil {
115+
return ""
116+
}
117+
118+
for _, iface := range ifaces {
119+
if iface.Name == "docker0" {
120+
addrs, err := iface.Addrs()
121+
if err != nil {
122+
continue
123+
}
124+
for _, addr := range addrs {
125+
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil {
126+
return ipnet.IP.String()
127+
}
128+
}
129+
}
130+
}
131+
132+
return ""
133+
}
134+
108135
func (ncp *NginxConfigParser) Parse(ctx context.Context, instance *mpi.Instance) (*model.NginxConfigContext, error) {
109136
configPath, _ := filepath.Abs(instance.GetInstanceRuntime().GetConfigPath())
110137

@@ -324,6 +351,10 @@ func (ncp *NginxConfigParser) findLocalSysLogServers(sysLogServer string) string
324351
if ip.IsLoopback() || strings.EqualFold(host, "localhost") {
325352
return matches[1]
326353
}
354+
355+
if ncp.docker0IP != "" && strings.EqualFold(host, ncp.docker0IP) {
356+
return matches[1]
357+
}
327358
}
328359

329360
return ""

internal/datasource/config/nginx_config_parser_test.go

Lines changed: 89 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"bytes"
1010
"context"
1111
"fmt"
12+
"net"
1213
"net/http"
1314
"net/http/httptest"
1415
"os"
@@ -575,6 +576,21 @@ func TestNginxConfigParser_Parse(t *testing.T) {
575576
allowedDirectories: []string{dir},
576577
expectedLog: "Found NAP syslog server",
577578
},
579+
{
580+
name: "Test 10a: NAP V5 syslog server without docker0 interface",
581+
instance: protos.NginxPlusInstance([]string{}),
582+
content: testconfig.NginxConfigWithMultipleSysLogs(errorLog.Name(), accessLog.Name(),
583+
"192.168.12.34:1517", "my.domain.com:1517", "192.0.10.1:1514"),
584+
expectedConfigContext: modelHelpers.ConfigContextWithSysLog(
585+
accessLog.Name(),
586+
errorLog.Name(),
587+
protos.NginxPlusInstance([]string{}).GetInstanceMeta().GetInstanceId(),
588+
"", // Empty because docker0 interface not found and 192.0.10.1 is not localhost
589+
),
590+
allowedDirectories: []string{dir},
591+
expectedLog: "Could not find available local NGINX App Protect syslog server " +
592+
"configured on port 1514. Security violations will not be collected.",
593+
},
578594
{
579595
name: "Test 11: Unavailable NAP syslog server",
580596
instance: protos.NginxPlusInstance([]string{}),
@@ -732,18 +748,64 @@ func TestNginxConfigParser_SyslogServerParse(t *testing.T) {
732748
}
733749

734750
func TestNginxConfigParser_findValidSysLogServers(t *testing.T) {
735-
servers := []string{
736-
"syslog:server=192.168.12.34:1517", "syslog:server=my.domain.com:1517", "syslog:server=127.0.0.1:1514",
737-
"syslog:server=localhost:1516", "syslog:server=localhost:1514", "syslog:server=127.255.255.255:1517",
738-
}
739-
expected := []string{"", "", "127.0.0.1:1514", "", "localhost:1514", ""}
740-
ncp := NewNginxConfigParser(types.AgentConfig())
751+
// Test with no docker0 interface (empty docker0IP)
752+
t.Run("without docker0 interface", func(t *testing.T) {
753+
servers := []string{
754+
"syslog:server=192.168.12.34:1517", "syslog:server=my.domain.com:1517", "syslog:server=127.0.0.1:1514",
755+
"syslog:server=localhost:1516", "syslog:server=localhost:1514", "syslog:server=127.255.255.255:1517",
756+
"syslog:server=192.0.10.1:1514",
757+
}
758+
// When docker0IP is empty, only localhost and loopback addresses should match
759+
expected := []string{"", "", "127.0.0.1:1514", "", "localhost:1514", "", ""}
760+
ncp := NewNginxConfigParser(types.AgentConfig())
761+
ncp.docker0IP = "" // Simulate no docker0 interface
741762

742-
for i, server := range servers {
743-
result := ncp.findLocalSysLogServers(server)
763+
for i, server := range servers {
764+
result := ncp.findLocalSysLogServers(server)
744765

745-
assert.Equal(t, expected[i], result)
746-
}
766+
assert.Equal(t, expected[i], result)
767+
}
768+
})
769+
770+
// Test with custom docker0 IP
771+
t.Run("with custom docker0 IP", func(t *testing.T) {
772+
ncp := NewNginxConfigParser(types.AgentConfig())
773+
// Override the docker0IP with a custom value for testing
774+
ncp.docker0IP = "172.17.0.1"
775+
776+
servers := []string{
777+
"syslog:server=172.17.0.1:1514", // should match custom docker0 IP
778+
"syslog:server=192.0.10.1:1514", // should NOT match (old default)
779+
"syslog:server=127.0.0.1:1514", // should match localhost
780+
"syslog:server=172.17.0.1:1515", // wrong port
781+
"syslog:server=172.17.0.2:1514", // wrong IP
782+
}
783+
expected := []string{"172.17.0.1:1514", "", "127.0.0.1:1514", "", ""}
784+
785+
for i, server := range servers {
786+
result := ncp.findLocalSysLogServers(server)
787+
788+
assert.Equal(t, expected[i], result, "server: %s", server)
789+
}
790+
})
791+
792+
// Test with another docker0 IP variation
793+
t.Run("with docker0 IP 172.18.0.1", func(t *testing.T) {
794+
ncp := NewNginxConfigParser(types.AgentConfig())
795+
ncp.docker0IP = "172.18.0.1"
796+
797+
servers := []string{
798+
"syslog:server=172.18.0.1:1514",
799+
"syslog:server=localhost:1514",
800+
}
801+
expected := []string{"172.18.0.1:1514", "localhost:1514"}
802+
803+
for i, server := range servers {
804+
result := ncp.findLocalSysLogServers(server)
805+
806+
assert.Equal(t, expected[i], result)
807+
}
808+
})
747809
}
748810

749811
func TestNginxConfigParser_checkLog(t *testing.T) {
@@ -1522,6 +1584,23 @@ func TestNginxConfigParser_checkDuplicate(t *testing.T) {
15221584
}
15231585
}
15241586

1587+
func TestGetDocker0IP(t *testing.T) {
1588+
t.Run("getDocker0IP returns valid IP or empty string", func(t *testing.T) {
1589+
ip := getDocker0IP()
1590+
1591+
// The function should return either:
1592+
// 1. A valid IP address if docker0 interface exists
1593+
// 2. Empty string if docker0 doesn't exist
1594+
if ip != "" {
1595+
// If an IP is returned, validate it's a proper IPv4 address
1596+
parsedIP := net.ParseIP(ip)
1597+
assert.NotNil(t, parsedIP, "should return a valid IP address")
1598+
assert.NotNil(t, parsedIP.To4(), "should be an IPv4 address")
1599+
}
1600+
// Empty string is also valid when docker0 doesn't exist
1601+
})
1602+
}
1603+
15251604
func TestNginxConfigParser_parseIncludeDirective(t *testing.T) {
15261605
parser := NewNginxConfigParser(types.AgentConfig())
15271606

0 commit comments

Comments
 (0)