Skip to content

Commit 8192dfe

Browse files
feat: integrate custom detection rules with Armour
- Added support for custom detection rules in the Armour integration. - Introduced new functions to submit process, file, and network events to the detection manager. - Updated the DNS proxy to submit DNS events when custom detection rules are enabled. - Refactored the agent's DNS handling to ensure proper execution flow when Docker is uninstalled.
1 parent 378ef52 commit 8192dfe

6 files changed

Lines changed: 155 additions & 13 deletions

File tree

agent.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,18 @@ func Run(ctx context.Context, configFilePath string, hostDNSServer DNSServer,
167167
WriteLog("\n")
168168
WriteLog("updated resolved")
169169

170-
// Change DNS for docker, causes process in containers to use agent's DNS proxy
171-
if err := dnsConfig.SetDockerDNSServer(cmd, dockerDaemonConfigPath, tempDir); err != nil {
172-
WriteLog(fmt.Sprintf("Error setting DNS server for docker %v", err))
173-
RevertChanges(iptables, nflog, cmd, resolvdConfigPath, dockerDaemonConfigPath, dnsConfig, sudo)
174-
return err
175-
}
170+
// we uninstall docker using go routine, handle case where that routine finishes before we come here
171+
if !config.DisableSudoAndContainers {
172+
// Change DNS for docker, causes process in containers to use agent's DNS proxy
173+
if err := dnsConfig.SetDockerDNSServer(cmd, dockerDaemonConfigPath, tempDir); err != nil {
174+
WriteLog(fmt.Sprintf("Error setting DNS server for docker %v", err))
175+
RevertChanges(iptables, nflog, cmd, resolvdConfigPath, dockerDaemonConfigPath, dnsConfig, sudo)
176+
return err
177+
}
176178

177-
WriteLog("\n")
178-
WriteLog("set docker config\n")
179+
WriteLog("\n")
180+
WriteLog("set docker config\n")
181+
}
179182

180183
if config.EgressPolicy == EgressPolicyAudit {
181184
netMonitor := NetworkMonitor{
@@ -242,13 +245,17 @@ func Run(ctx context.Context, configFilePath string, hostDNSServer DNSServer,
242245

243246
conf.Files = append(conf.Files, getFilesOfInterest()...)
244247

245-
mArmour := armour.NewArmour(ctx, conf)
246-
err := mArmour.Attach()
248+
err := InitArmour(ctx, conf)
247249
if err != nil {
248250
WriteLog("Armour attachment failed")
249251
} else {
250-
defer mArmour.Detach()
252+
if GlobalArmour != nil {
253+
defer GlobalArmour.Detach()
254+
}
251255
WriteLog("Armour attached")
256+
if IsCustomDetectionRulesEnabled() {
257+
WriteLog("[armour] Custom detection rules enabled")
258+
}
252259
}
253260
}
254261

armour_manager.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/step-security/armour/armour"
8+
)
9+
10+
// NOTE: before usage, make sure to nil check
11+
var GlobalArmour *armour.Armour = nil
12+
13+
func InitArmour(ctx context.Context, conf *armour.Config) error {
14+
15+
GlobalArmour = armour.NewArmour(ctx, conf)
16+
err := GlobalArmour.Init()
17+
if err != nil {
18+
GlobalArmour = nil
19+
return err
20+
}
21+
22+
runnerWorkerPID, err := getRunnerWorkerPID()
23+
if err != nil {
24+
WriteLog(fmt.Sprintf("[armour] Error getting Runner.Worker PID: %v", err))
25+
return nil
26+
}
27+
GlobalArmour.SetRunnerWorkerPID(runnerWorkerPID)
28+
WriteLog(fmt.Sprintf("[armour] Runner.Worker PID: %d", runnerWorkerPID))
29+
30+
return nil
31+
}

common.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,7 @@ func getProcMemFiles(pid uint64) []string {
9191

9292
return out
9393
}
94+
95+
func getRunnerWorkerPID() (uint64, error) {
96+
return pidOf("Runner.Worker")
97+
}

dnsproxy.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/miekg/dns"
1313
"github.com/pkg/errors"
14+
"github.com/step-security/armour/armour"
1415
)
1516

1617
type DNSProxy struct {
@@ -239,6 +240,8 @@ func (proxy *DNSProxy) getIPByDomain(domain string) (string, error) {
239240

240241
go proxy.ApiClient.sendDNSRecord(proxy.CorrelationId, proxy.Repo, domain, answer.Data)
241242

243+
go proxy.submitDNSEvent(answer.Data)
244+
242245
return answer.Data, nil
243246

244247
}
@@ -296,6 +299,23 @@ func (proxy *DNSProxy) processTypeA(q *dns.Question, requestMsg *dns.Msg) (*dns.
296299
return &rr, nil
297300
}
298301

302+
// submitDNSEvent submits a DNS event to the detection manager.
303+
func (proxy *DNSProxy) submitDNSEvent(dest string) {
304+
if !IsCustomDetectionRulesEnabled() {
305+
return
306+
}
307+
if GlobalArmour == nil {
308+
return
309+
}
310+
dm := GlobalArmour.DetectionManager()
311+
if dm == nil {
312+
return
313+
}
314+
dm.SubmitNetwork(&armour.NetworkDetectionEvent{
315+
Dest: dest,
316+
})
317+
}
318+
299319
func startDNSServer(dnsProxy *DNSProxy, server DNSServer, errc chan error) {
300320
dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
301321
switch r.Opcode {

eventhandler.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/docker/docker/api/types"
1717
"github.com/docker/docker/client"
18+
"github.com/step-security/armour/armour"
1819
)
1920

2021
type EventHandler struct {
@@ -89,6 +90,8 @@ func (eventHandler *EventHandler) handleFileEvent(event *Event) {
8990
}
9091
}
9192

93+
eventHandler.submitFileEvent(event)
94+
9295
eventHandler.fileMutex.Unlock()
9396
}
9497

@@ -123,6 +126,8 @@ func (eventHandler *EventHandler) handleProcessEvent(event *Event) {
123126
} else {
124127
eventHandler.procMutex.Unlock()
125128
}
129+
130+
eventHandler.submitProcessEvent(event)
126131
}
127132

128133
/*
@@ -199,6 +204,10 @@ func (eventHandler *EventHandler) handleNetworkEvent(event *Event) {
199204
}
200205

201206
eventHandler.netMutex.Unlock()
207+
208+
eventHandler.submitDNSEvent(reverseLookUp)
209+
210+
eventHandler.submitNetworkEvent(event)
202211
}
203212

204213
func (eventHandler *EventHandler) HandleEvent(event *Event) {
@@ -440,3 +449,68 @@ func isPrivateIPAddress(ipAddress string) bool {
440449
func isIPv6(ip string) bool {
441450
return strings.Contains(ip, ":")
442451
}
452+
453+
func (eventHandler *EventHandler) submitProcessEvent(event *Event) {
454+
if !IsCustomDetectionRulesEnabled() {
455+
return
456+
}
457+
if GlobalArmour == nil {
458+
return
459+
}
460+
dm := GlobalArmour.DetectionManager()
461+
if dm == nil {
462+
return
463+
}
464+
dm.SubmitProcess(&armour.ProcessDetectionEvent{
465+
Pid: event.Pid,
466+
PPid: event.PPid,
467+
Exe: event.Exe,
468+
Arguments: event.ProcessArguments,
469+
Cwd: event.Path,
470+
Timestamp: event.Timestamp,
471+
})
472+
}
473+
474+
// submitFileEvent submits a file event to the detection manager.
475+
func (eventHandler *EventHandler) submitFileEvent(event *Event) {
476+
if !IsCustomDetectionRulesEnabled() {
477+
return
478+
}
479+
if GlobalArmour == nil {
480+
return
481+
}
482+
dm := GlobalArmour.DetectionManager()
483+
if dm == nil {
484+
return
485+
}
486+
dm.SubmitFile(&armour.FileDetectionEvent{
487+
Syscall: event.Syscall,
488+
FileName: filepath.Base(event.FileName),
489+
Path: event.FileName,
490+
Exe: event.Exe,
491+
Pid: event.Pid,
492+
PPid: event.PPid,
493+
Timestamp: event.Timestamp,
494+
})
495+
}
496+
497+
// submitNetworkEvent submits a network event to the detection manager.
498+
func (eventHandler *EventHandler) submitNetworkEvent(event *Event) {
499+
if GlobalArmour == nil {
500+
return
501+
}
502+
dm := GlobalArmour.DetectionManager()
503+
if dm == nil {
504+
return
505+
}
506+
507+
dm.SubmitNetwork(&armour.NetworkDetectionEvent{
508+
Pid: event.Pid,
509+
PPid: event.PPid,
510+
Exe: event.Exe,
511+
Dest: event.IPAddress,
512+
DestIP: event.IPAddress,
513+
DestPort: event.Port,
514+
Timestamp: event.Timestamp,
515+
})
516+
}

global_feature_flags.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ const (
1111
)
1212

1313
type GlobalFeatureFlags struct {
14-
AgentType string `json:"agent_type"`
15-
EnableArmour bool `json:"enable_armour"`
14+
AgentType string `json:"agent_type"`
15+
EnableArmour bool `json:"enable_armour"`
16+
EnableCustomDetectionRules bool `json:"enable_custom_detection_rules"`
1617
}
1718

1819
// GlobalFeatureFlagManager manages fetching and caching of global feature flags.
@@ -79,3 +80,8 @@ func IsArmourEnabled() bool {
7980
flags := GetGlobalFeatureFlags()
8081
return flags.EnableArmour
8182
}
83+
84+
func IsCustomDetectionRulesEnabled() bool {
85+
flags := GetGlobalFeatureFlags()
86+
return flags.EnableCustomDetectionRules
87+
}

0 commit comments

Comments
 (0)