Skip to content
19 changes: 6 additions & 13 deletions internal/collector/otel_collector_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -543,17 +543,12 @@ func (oc *Collector) updateExistingNginxOSSReceiver(

func (oc *Collector) updateTcplogReceivers(nginxConfigContext *model.NginxConfigContext) bool {
newTcplogReceiverAdded := false
if nginxConfigContext.NAPSysLogServers != nil {
napLoop:
for _, napSysLogServer := range nginxConfigContext.NAPSysLogServers {
if oc.doesTcplogReceiverAlreadyExist(napSysLogServer) {
continue napLoop
}

if nginxConfigContext.NAPSysLogServer != "" {
if !oc.doesTcplogReceiverAlreadyExist(nginxConfigContext.NAPSysLogServer) {
oc.config.Collector.Receivers.TcplogReceivers = append(
oc.config.Collector.Receivers.TcplogReceivers,
config.TcplogReceiver{
ListenAddress: napSysLogServer,
ListenAddress: nginxConfigContext.NAPSysLogServer,
Operators: []config.Operator{
{
Type: "add",
Expand Down Expand Up @@ -621,12 +616,10 @@ func (oc *Collector) configDeletedNapReceivers(nginxConfigContext *model.NginxCo
elements[tcplogReceiver.ListenAddress] = true
}

if nginxConfigContext.NAPSysLogServers != nil {
if nginxConfigContext.NAPSysLogServer != "" {
addressesToDelete := make(map[string]bool)
for _, napAddress := range nginxConfigContext.NAPSysLogServers {
if !elements[napAddress] {
addressesToDelete[napAddress] = true
}
if !elements[nginxConfigContext.NAPSysLogServer] {
addressesToDelete[nginxConfigContext.NAPSysLogServer] = true
}

return addressesToDelete
Expand Down
9 changes: 3 additions & 6 deletions internal/collector/otel_collector_plugin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -733,9 +733,7 @@ func TestCollector_updateTcplogReceivers(t *testing.T) {
require.NoError(t, err)

nginxConfigContext := &model.NginxConfigContext{
NAPSysLogServers: []string{
"localhost:151",
},
NAPSysLogServer: "localhost:151",
}

assert.Empty(t, conf.Collector.Receivers.TcplogReceivers)
Expand Down Expand Up @@ -766,9 +764,8 @@ func TestCollector_updateTcplogReceivers(t *testing.T) {
})

t.Run("Test 4: New tcplogReceiver added and deleted another", func(tt *testing.T) {
tcplogReceiverDeleted := collector.updateTcplogReceivers(&model.NginxConfigContext{NAPSysLogServers: []string{
"localhost:152",
}})
tcplogReceiverDeleted := collector.
updateTcplogReceivers(&model.NginxConfigContext{NAPSysLogServer: "localhost:152"})
assert.True(t, tcplogReceiverDeleted)
assert.Len(t, conf.Collector.Receivers.TcplogReceivers, 1)
assert.Equal(t, "localhost:152", conf.Collector.Receivers.TcplogReceivers[0].ListenAddress)
Expand Down
79 changes: 64 additions & 15 deletions internal/datasource/config/nginx_config_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ const (

type (
NginxConfigParser struct {
agentConfig *config.Config
agentConfig *config.Config
previousNAPSysLogServer string
}
)

Expand All @@ -65,7 +66,8 @@ type (

func NewNginxConfigParser(agentConfig *config.Config) *NginxConfigParser {
return &NginxConfigParser{
agentConfig: agentConfig,
agentConfig: agentConfig,
previousNAPSysLogServer: "",
}
}

Expand Down Expand Up @@ -107,6 +109,7 @@ func (ncp *NginxConfigParser) createNginxConfigContext(
payload *crossplane.Payload,
) (*model.NginxConfigContext, error) {
napSyslogServersFound := make(map[string]bool)
napEnabled := false

nginxConfigContext := &model.NginxConfigContext{
InstanceID: instance.GetInstanceMeta().GetInstanceId(),
Expand Down Expand Up @@ -173,19 +176,11 @@ func (ncp *NginxConfigParser) createNginxConfigContext(
}
case "app_protect_security_log":
if len(directive.Args) > 1 {
syslogArg := directive.Args[1]
re := regexp.MustCompile(`syslog:server=([\S]+)`)
matches := re.FindStringSubmatch(syslogArg)
if len(matches) > 1 {
syslogServer := matches[1]
if !napSyslogServersFound[syslogServer] {
nginxConfigContext.NAPSysLogServers = append(
nginxConfigContext.NAPSysLogServers,
syslogServer,
)
napSyslogServersFound[syslogServer] = true
slog.DebugContext(ctx, "Found NAP syslog server", "address", syslogServer)
}
napEnabled = true
sysLogServer := ncp.findLocalSysLogServers(directive.Args[1])
if sysLogServer != "" && !napSyslogServersFound[sysLogServer] {
napSyslogServersFound[sysLogServer] = true
slog.DebugContext(ctx, "Found NAP syslog server", "address", sysLogServer)
}
}
}
Expand All @@ -207,6 +202,17 @@ func (ncp *NginxConfigParser) createNginxConfigContext(
nginxConfigContext.PlusAPI = plusAPI
}

if len(napSyslogServersFound) > 0 {
syslogServer := ncp.findAvailableSyslogServers(ctx, napSyslogServersFound)
if syslogServer != "" {
nginxConfigContext.NAPSysLogServer = syslogServer
ncp.previousNAPSysLogServer = syslogServer
}
} else if napEnabled {
slog.WarnContext(ctx, "Could not find available local NGINX App Protect syslog server. "+
"Security violations will not be collected.")
}

fileMeta, err := files.FileMeta(conf.File)
if err != nil {
slog.WarnContext(ctx, "Unable to get file metadata", "file_name", conf.File, "error", err)
Expand All @@ -218,6 +224,49 @@ func (ncp *NginxConfigParser) createNginxConfigContext(
return nginxConfigContext, nil
}

func (ncp *NginxConfigParser) findAvailableSyslogServers(ctx context.Context, napSyslogServers map[string]bool) string {
if ncp.previousNAPSysLogServer != "" {
if _, ok := napSyslogServers[ncp.previousNAPSysLogServer]; ok {
return ncp.previousNAPSysLogServer
}
}

for napSyslogServer := range napSyslogServers {
ln, err := net.Listen("tcp", napSyslogServer)
if err != nil {
slog.DebugContext(ctx, "NAP syslog server is not reachable", "address", napSyslogServer,
"error", err)

continue
}
ln.Close()

slog.DebugContext(ctx, "Found valid NAP syslog server", "address", napSyslogServer)

return napSyslogServer
}

return ""
}

func (ncp *NginxConfigParser) findLocalSysLogServers(sysLogServer string) string {
re := regexp.MustCompile(`syslog:server=([\S]+)`)
matches := re.FindStringSubmatch(sysLogServer)
if len(matches) > 1 {
host, _, err := net.SplitHostPort(matches[1])
if err != nil {
return ""
}

ip := net.ParseIP(host)
if ip.IsLoopback() || strings.EqualFold(host, "localhost") {
return matches[1]
}
}

return ""
}

func (ncp *NginxConfigParser) parseIncludeDirective(directive *crossplane.Directive) string {
var include string
if filepath.IsAbs(directive.Args[0]) {
Expand Down
Loading