Skip to content

Commit e4ddcb1

Browse files
committed
Report NGINX App Protect instances
1 parent 850e0da commit e4ddcb1

14 files changed

+446
-351
lines changed

api/grpc/mpi/v1/command.pb.go

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/grpc/mpi/v1/command.pb.validate.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/grpc/mpi/v1/command.proto

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,8 @@ message NGINXAppProtectRuntimeInfo {
362362
string attack_signature_version = 2;
363363
// Threat campaign version
364364
string threat_campaign_version = 3;
365+
// Enforcer engine version
366+
string enforcer_engine_version = 4;
365367
}
366368

367369
// A set of actions that can be performed on an instance

docs/proto/protos.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,7 @@ A set of runtime NGINX App Protect settings
10531053
| release | [string](#string) | | NGINX App Protect Release |
10541054
| attack_signature_version | [string](#string) | | Attack signature version |
10551055
| threat_campaign_version | [string](#string) | | Threat campaign version |
1056+
| enforcer_engine_version | [string](#string) | | Enforcer engine version |
10561057

10571058

10581059

internal/watcher/instance/instance_watcher_service.go

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,25 +32,30 @@ const defaultAgentPath = "/run/nginx-agent"
3232

3333
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6@v6.8.1 -generate
3434
//counterfeiter:generate . processParser
35+
//counterfeiter:generate . instanceFinder
3536

3637
type (
3738
processParser interface {
3839
Parse(ctx context.Context, processes []*nginxprocess.Process) map[string]*mpi.Instance
3940
}
4041

42+
instanceFinder interface {
43+
Find(ctx context.Context) *mpi.Instance
44+
}
45+
4146
InstanceWatcherService struct {
42-
processOperator process.ProcessOperatorInterface
43-
nginxConfigParser parser.ConfigParser
44-
executer exec.ExecInterface
45-
enabled *atomic.Bool
46-
agentConfig *config.Config
47-
instanceCache map[string]*mpi.Instance
48-
nginxConfigCache map[string]*model.NginxConfigContext
49-
instancesChannel chan<- InstanceUpdatesMessage
50-
nginxConfigContextChannel chan<- NginxConfigContextMessage
51-
nginxParser processParser
52-
nginxAppProtectProcessParser processParser
53-
cacheMutex sync.Mutex
47+
processOperator process.ProcessOperatorInterface
48+
nginxConfigParser parser.ConfigParser
49+
executer exec.ExecInterface
50+
enabled *atomic.Bool
51+
agentConfig *config.Config
52+
instanceCache map[string]*mpi.Instance
53+
nginxConfigCache map[string]*model.NginxConfigContext
54+
instancesChannel chan<- InstanceUpdatesMessage
55+
nginxConfigContextChannel chan<- NginxConfigContextMessage
56+
nginxParser processParser
57+
nginxAppProtectInstanceFinder instanceFinder
58+
cacheMutex sync.Mutex
5459
}
5560

5661
InstanceUpdates struct {
@@ -75,16 +80,16 @@ func NewInstanceWatcherService(agentConfig *config.Config) *InstanceWatcherServi
7580
enabled.Store(true)
7681

7782
return &InstanceWatcherService{
78-
agentConfig: agentConfig,
79-
processOperator: process.NewProcessOperator(),
80-
nginxParser: NewNginxProcessParser(),
81-
nginxAppProtectProcessParser: NewNginxAppProtectProcessParser(),
82-
nginxConfigParser: parser.NewNginxConfigParser(agentConfig),
83-
instanceCache: make(map[string]*mpi.Instance),
84-
cacheMutex: sync.Mutex{},
85-
nginxConfigCache: make(map[string]*model.NginxConfigContext),
86-
executer: &exec.Exec{},
87-
enabled: enabled,
83+
agentConfig: agentConfig,
84+
processOperator: process.NewProcessOperator(),
85+
nginxParser: NewNginxProcessParser(),
86+
nginxAppProtectInstanceFinder: NewNginxAppProtectInstanceFinder(),
87+
nginxConfigParser: parser.NewNginxConfigParser(agentConfig),
88+
instanceCache: make(map[string]*mpi.Instance),
89+
cacheMutex: sync.Mutex{},
90+
nginxConfigCache: make(map[string]*model.NginxConfigContext),
91+
executer: &exec.Exec{},
92+
enabled: enabled,
8893
}
8994
}
9095

@@ -265,7 +270,7 @@ func (iw *InstanceWatcherService) instanceUpdates(ctx context.Context) (
265270
) {
266271
iw.cacheMutex.Lock()
267272
defer iw.cacheMutex.Unlock()
268-
nginxProcesses, nginxAppProtectProcesses, err := iw.processOperator.Processes(ctx)
273+
nginxProcesses, err := iw.processOperator.Processes(ctx)
269274
if err != nil {
270275
return instanceUpdates, err
271276
}
@@ -280,10 +285,11 @@ func (iw *InstanceWatcherService) instanceUpdates(ctx context.Context) (
280285
instancesFound[instance.GetInstanceMeta().GetInstanceId()] = instance
281286
}
282287

283-
nginxAppProtectInstances := iw.nginxAppProtectProcessParser.Parse(ctx, nginxAppProtectProcesses)
284-
for _, instance := range nginxAppProtectInstances {
285-
instancesFound[instance.GetInstanceMeta().GetInstanceId()] = instance
288+
nginxAppProtectInstance := iw.nginxAppProtectInstanceFinder.Find(ctx)
289+
if nginxAppProtectInstance != nil {
290+
instancesFound[nginxAppProtectInstance.GetInstanceMeta().GetInstanceId()] = nginxAppProtectInstance
286291
}
292+
287293
newInstances, updatedInstances, deletedInstances := compareInstances(iw.instanceCache, instancesFound)
288294

289295
instanceUpdates.NewInstances = newInstances

internal/watcher/instance/instance_watcher_service_test.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,17 @@ func TestInstanceWatcherService_checkForUpdates(t *testing.T) {
2828
nginxConfigContext := testModel.ConfigContext()
2929

3030
fakeProcessWatcher := &processfakes.FakeProcessOperatorInterface{}
31-
fakeProcessWatcher.ProcessesReturns(nil, nil, nil)
31+
fakeProcessWatcher.ProcessesReturns(nil, nil)
3232

3333
fakeProcessParser := &instancefakes.FakeProcessParser{}
3434
fakeProcessParser.ParseReturns(map[string]*mpi.Instance{
3535
protos.NginxOssInstance([]string{}).GetInstanceMeta().GetInstanceId(): protos.
3636
NginxOssInstance([]string{}),
3737
})
3838

39+
fakeNginxAppProtectInstanceFinder := &instancefakes.FakeInstanceFinder{}
40+
fakeNginxAppProtectInstanceFinder.FindReturns(protos.NginxAppProtectInstance())
41+
3942
fakeNginxConfigParser := &instancefakes.FakeNginxConfigParser{}
4043
fakeNginxConfigParser.ParseReturns(nginxConfigContext, nil)
4144
instanceUpdatesChannel := make(chan InstanceUpdatesMessage, 1)
@@ -44,15 +47,15 @@ func TestInstanceWatcherService_checkForUpdates(t *testing.T) {
4447
instanceWatcherService := NewInstanceWatcherService(types.AgentConfig())
4548
instanceWatcherService.processOperator = fakeProcessWatcher
4649
instanceWatcherService.nginxParser = fakeProcessParser
47-
instanceWatcherService.nginxAppProtectProcessParser = fakeProcessParser
50+
instanceWatcherService.nginxAppProtectInstanceFinder = fakeNginxAppProtectInstanceFinder
4851
instanceWatcherService.nginxConfigParser = fakeNginxConfigParser
4952
instanceWatcherService.instancesChannel = instanceUpdatesChannel
5053
instanceWatcherService.nginxConfigContextChannel = nginxConfigContextChannel
5154

5255
instanceWatcherService.checkForUpdates(ctx)
5356

5457
instanceUpdatesMessage := <-instanceUpdatesChannel
55-
assert.Len(t, instanceUpdatesMessage.InstanceUpdates.NewInstances, 2)
58+
assert.Len(t, instanceUpdatesMessage.InstanceUpdates.NewInstances, 3)
5659
assert.Empty(t, instanceUpdatesMessage.InstanceUpdates.DeletedInstances)
5760

5861
nginxConfigContextMessage := <-nginxConfigContextChannel
@@ -67,6 +70,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
6770
nginxInstance := protos.NginxOssInstance([]string{})
6871
nginxInstanceWithDifferentPID := protos.NginxOssInstance([]string{})
6972
nginxInstanceWithDifferentPID.GetInstanceRuntime().ProcessId = 3526
73+
napInstance := protos.NginxAppProtectInstance()
7074

7175
tests := []struct {
7276
name string
@@ -78,6 +82,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
7882
name: "Test 1: No updates",
7983
oldInstances: map[string]*mpi.Instance{
8084
agentInstance.GetInstanceMeta().GetInstanceId(): agentInstance,
85+
napInstance.GetInstanceMeta().GetInstanceId(): napInstance,
8186
},
8287
parsedInstances: make(map[string]*mpi.Instance),
8388
expectedInstanceUpdates: InstanceUpdates{},
@@ -94,6 +99,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
9499
expectedInstanceUpdates: InstanceUpdates{
95100
NewInstances: []*mpi.Instance{
96101
nginxInstance,
102+
napInstance,
97103
},
98104
},
99105
},
@@ -102,6 +108,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
102108
oldInstances: map[string]*mpi.Instance{
103109
agentInstance.GetInstanceMeta().GetInstanceId(): agentInstance,
104110
nginxInstanceWithDifferentPID.GetInstanceMeta().GetInstanceId(): nginxInstanceWithDifferentPID,
111+
napInstance.GetInstanceMeta().GetInstanceId(): napInstance,
105112
},
106113
parsedInstances: map[string]*mpi.Instance{
107114
agentInstance.GetInstanceMeta().GetInstanceId(): agentInstance,
@@ -119,6 +126,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
119126
agentInstance.GetInstanceMeta().GetInstanceId(): agentInstance,
120127
protos.NginxOssInstance([]string{}).GetInstanceMeta().
121128
GetInstanceId(): protos.NginxOssInstance([]string{}),
129+
napInstance.GetInstanceMeta().GetInstanceId(): napInstance,
122130
},
123131
parsedInstances: make(map[string]*mpi.Instance),
124132
expectedInstanceUpdates: InstanceUpdates{
@@ -132,7 +140,7 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
132140
for _, test := range tests {
133141
t.Run(test.name, func(tt *testing.T) {
134142
fakeProcessWatcher := &processfakes.FakeProcessOperatorInterface{}
135-
fakeProcessWatcher.ProcessesReturns(nil, nil, nil)
143+
fakeProcessWatcher.ProcessesReturns(nil, nil)
136144

137145
fakeProcessParser := &instancefakes.FakeProcessParser{}
138146
fakeProcessParser.ParseReturns(test.parsedInstances)
@@ -141,10 +149,13 @@ func TestInstanceWatcherService_instanceUpdates(t *testing.T) {
141149
fakeExec.ExecutableReturns(defaultAgentPath, nil)
142150
fakeExec.ProcessIDReturns(processID)
143151

152+
fakeNginxAppProtectInstanceFinder := &instancefakes.FakeInstanceFinder{}
153+
fakeNginxAppProtectInstanceFinder.FindReturns(napInstance)
154+
144155
instanceWatcherService := NewInstanceWatcherService(types.AgentConfig())
145156
instanceWatcherService.processOperator = fakeProcessWatcher
146157
instanceWatcherService.nginxParser = fakeProcessParser
147-
instanceWatcherService.nginxAppProtectProcessParser = fakeProcessParser
158+
instanceWatcherService.nginxAppProtectInstanceFinder = fakeNginxAppProtectInstanceFinder
148159
instanceWatcherService.instanceCache = test.oldInstances
149160
instanceWatcherService.executer = fakeExec
150161

internal/watcher/instance/instancefakes/fake_instance_finder.go

Lines changed: 110 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)