Skip to content

Commit 1ef98f7

Browse files
committed
feat: Add syslog log processor for nap
1 parent 504a66a commit 1ef98f7

File tree

13 files changed

+813
-5
lines changed

13 files changed

+813
-5
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ require (
1616
github.com/google/uuid v1.6.0
1717
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
1818
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.1
19+
github.com/leodido/go-syslog/v4 v4.2.0
1920
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
2021
github.com/nginxinc/nginx-plus-go-client/v2 v2.0.1
2122
github.com/nginxinc/nginx-prometheus-exporter v1.3.0
@@ -150,7 +151,6 @@ require (
150151
github.com/knadh/koanf/maps v0.1.2 // indirect
151152
github.com/knadh/koanf/providers/confmap v0.1.0 // indirect
152153
github.com/knadh/koanf/v2 v2.1.2 // indirect
153-
github.com/leodido/go-syslog/v4 v4.2.0 // indirect
154154
github.com/leodido/go-urn v1.4.0 // indirect
155155
github.com/leodido/ragel-machinery v0.0.0-20190525184631-5f46317e436b // indirect
156156
github.com/lightstep/go-expohisto v1.0.0 // indirect

internal/collector/factories.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/nginx/agent/v3/internal/collector/logsgzipprocessor"
1111
nginxreceiver "github.com/nginx/agent/v3/internal/collector/nginxossreceiver"
1212
"github.com/nginx/agent/v3/internal/collector/nginxplusreceiver"
13+
"github.com/nginx/agent/v3/internal/collector/syslogprocessor"
1314

1415
"github.com/open-telemetry/opentelemetry-collector-contrib/exporter/prometheusexporter"
1516
"github.com/open-telemetry/opentelemetry-collector-contrib/extension/headerssetterextension"
@@ -104,6 +105,7 @@ func createProcessorFactories() map[component.Type]processor.Factory {
104105
memorylimiterprocessor.NewFactory(),
105106
redactionprocessor.NewFactory(),
106107
resourceprocessor.NewFactory(),
108+
syslogprocessor.NewFactory(),
107109
transformprocessor.NewFactory(),
108110
logsgzipprocessor.NewFactory(),
109111
}

internal/collector/otel_collector_plugin_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,7 @@ func TestCollector_ProcessResourceUpdateTopicFails(t *testing.T) {
410410
conf.Collector.Processors.Attribute = nil
411411
conf.Collector.Processors.Resource = nil
412412
conf.Collector.Processors.LogsGzip = nil
413+
conf.Collector.Processors.Syslog = nil
413414
conf.Collector.Exporters.OtlpExporters = nil
414415
conf.Collector.Exporters.PrometheusExporter = &config.PrometheusExporter{
415416
Server: &config.ServerConfig{
@@ -735,6 +736,7 @@ func TestCollector_updateNginxAppProtectTcplogReceivers(t *testing.T) {
735736
conf.Collector.Processors.Attribute = nil
736737
conf.Collector.Processors.Resource = nil
737738
conf.Collector.Processors.LogsGzip = nil
739+
conf.Collector.Processors.Syslog = nil
738740
collector, err := NewCollector(conf)
739741
require.NoError(t, err)
740742

@@ -790,6 +792,7 @@ func TestCollector_findAvailableSyslogServers(t *testing.T) {
790792
conf.Collector.Processors.Attribute = nil
791793
conf.Collector.Processors.Resource = nil
792794
conf.Collector.Processors.LogsGzip = nil
795+
conf.Collector.Processors.Syslog = nil
793796
collector, err := NewCollector(conf)
794797
require.NoError(t, err)
795798

internal/collector/otelcol.tmpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ processors:
156156
send_batch_max_size: {{ $batch.SendBatchMaxSize }}
157157
{{- end }}
158158
{{- end }}
159+
{{- if ne .Processors.Syslog nil }}
160+
{{- range $key, $value := .Processors.Syslog }}
161+
syslog/{{$key}}: {}
162+
{{- end }}
163+
{{- end }}
159164
{{- if ne .Processors.LogsGzip nil }}
160165
{{ range $key, $value := .Processors.LogsGzip }}
161166
logsgzip/{{$key}}: {}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Syslog Processor
2+
3+
Internal component of the NGINX Agent that processes syslog messages. Parses RFC3164 formatted syslog entries from log records and extracts structured attributes. Successfully parsed messages have their body replaced with the clean message content.
4+
5+
Part of the NGINX Agent's log collection pipeline.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) F5, Inc.
2+
//
3+
// This source code is licensed under the Apache License, Version 2.0 license found in the
4+
// LICENSE file in the root directory of this source tree.
5+
6+
package syslogprocessor
7+
8+
import (
9+
"context"
10+
11+
"go.opentelemetry.io/collector/component"
12+
"go.opentelemetry.io/collector/consumer"
13+
"go.opentelemetry.io/collector/processor"
14+
)
15+
16+
const typeStr = "syslog"
17+
18+
// NewFactory creates a factory for the syslog processor.
19+
// nolint: ireturn
20+
func NewFactory() processor.Factory {
21+
return processor.NewFactory(
22+
component.MustNewType(typeStr),
23+
func() component.Config { return &struct{}{} },
24+
processor.WithLogs(createSyslogProcessor, component.StabilityLevelAlpha),
25+
)
26+
}
27+
28+
// createSyslogProcessor instantiates the logs processor.
29+
// nolint: ireturn
30+
func createSyslogProcessor(
31+
_ context.Context,
32+
settings processor.Settings,
33+
_ component.Config,
34+
next consumer.Logs,
35+
) (processor.Logs, error) {
36+
settings.Logger.Info("Creating syslog processor")
37+
38+
return newSyslogProcessor(next, settings), nil
39+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) F5, Inc.
2+
//
3+
// This source code is licensed under the Apache License, Version 2.0 license found in the
4+
// LICENSE file in the root directory of this source tree.
5+
6+
package syslogprocessor
7+
8+
// SecurityViolationEvent represents the structured NGINX App Protect security violation data
9+
type SecurityViolationEvent struct {
10+
PolicyName string `json:"policy_name"`
11+
SupportID string `json:"support_id"`
12+
Outcome string `json:"outcome"`
13+
OutcomeReason string `json:"outcome_reason"`
14+
BlockingExceptionReason string `json:"blocking_exception_reason"`
15+
Method string `json:"method"`
16+
Protocol string `json:"protocol"`
17+
XForwardedForHeaderValue string `json:"xff_header_value"`
18+
URI string `json:"uri"`
19+
Request string `json:"request"`
20+
IsTruncated string `json:"is_truncated"`
21+
RequestStatus string `json:"request_status"`
22+
ResponseCode string `json:"response_code"`
23+
ServerAddr string `json:"server_addr"`
24+
VSName string `json:"vs_name"`
25+
RemoteAddr string `json:"remote_addr"`
26+
RemotePort string `json:"destination_port"`
27+
ServerPort string `json:"server_port"`
28+
Violations string `json:"violations"`
29+
SubViolations string `json:"sub_violations"`
30+
ViolationRating string `json:"violation_rating"`
31+
SigSetNames string `json:"sig_set_names"`
32+
SigCVEs string `json:"sig_cves"`
33+
ClientClass string `json:"client_class"`
34+
ClientApplication string `json:"client_application"`
35+
ClientApplicationVersion string `json:"client_application_version"`
36+
Severity string `json:"severity"`
37+
ThreatCampaignNames string `json:"threat_campaign_names"`
38+
BotAnomalies string `json:"bot_anomalies"`
39+
BotCategory string `json:"bot_category"`
40+
EnforcedBotAnomalies string `json:"enforced_bot_anomalies"`
41+
BotSignatureName string `json:"bot_signature_name"`
42+
SystemID string `json:"system_id"`
43+
InstanceTags string `json:"instance_tags"`
44+
InstanceGroup string `json:"instance_group"`
45+
ParentHostname string `json:"parent_hostname"`
46+
DisplayName string `json:"display_name"`
47+
ViolationsData []ViolationData `json:"violations_data"`
48+
}
49+
50+
type ViolationData struct {
51+
Name string `json:"violation_data_name"`
52+
Context string `json:"violation_data_context"`
53+
ContextData ContextData `json:"violation_data_context_data"`
54+
Signatures []SignatureData `json:"violation_data_signatures"`
55+
}
56+
57+
// SignatureData represents signature data contained within each violation
58+
type SignatureData struct {
59+
ID string `json:"sig_data_id"`
60+
BlockingMask string `json:"sig_data_blocking_mask"`
61+
Buffer string `json:"sig_data_buffer"`
62+
Offset string `json:"sig_data_offset"`
63+
Length string `json:"sig_data_length"`
64+
}
65+
66+
// ContextData represents the context data of the violation
67+
type ContextData struct {
68+
Name string `json:"parameter_data_name"`
69+
Value string `json:"parameter_data_value"`
70+
}

0 commit comments

Comments
 (0)