Skip to content

Conversation

slashben
Copy link
Contributor

This pull request introduces a major new feature: integration of the Linux Audit subsystem into the Kubescape node-agent, alongside supporting documentation, code changes, and dependency updates. The audit subsystem provides kernel-level event filtering and real-time audit event streaming, operating independently from the existing eBPF-based runtime detection. The implementation includes new architecture, configuration, event processing, and testing strategies.

Linux Audit Subsystem Integration

  • Added a comprehensive design overview (AUDIT_DESIGN_OVERVIEW.md) detailing the architecture, rule processing pipeline, event flow, security, testing, and future enhancements for Linux Audit subsystem integration.
  • Implemented a new interface AuditManagerClient in pkg/auditmanager/audit_manager_interface.go, supporting real audit event management and a mock manager for disabled/testing states.
  • Integrated the audit manager into cmd/main.go: creates and starts the audit manager with dedicated configuration and exporters, supports independent operation from runtime detection, and ensures proper lifecycle management. [1] [2] [3] [4]

Testing & Documentation

  • Added a detailed testing guide (README_AUDIT_TESTING.md) covering unit, integration, and end-to-end tests, troubleshooting, configuration examples, and validation steps for the audit subsystem.

Dependency Updates

  • Updated go.mod to add dependencies for the audit subsystem and testing, including github.com/elastic/go-libaudit/v2 for kernel audit integration and github.com/golang/mock for mocking. [1] [2] [3]

@slashben slashben requested a review from matthyx September 15, 2025 14:52
Copy link

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: failure
  • Unit test: success
  • Go linting: failure

@matthyx matthyx moved this to WIP in KS PRs tracking Sep 16, 2025
@slashben slashben marked this pull request as ready for review September 29, 2025 20:54
@matthyx matthyx force-pushed the feature/linux-audit branch from d690cb5 to 8d3f908 Compare October 1, 2025 12:01
containerID, err := am.processTreeManager.GetContainerIDForPid(event.PID)
if err != nil {
logger.L().Debug("failed to get container ID from process tree manager",
helpers.Int("pid", int(event.PID)),

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an unsigned 32-bit integer from
strconv.ParseUint
to a lower bit size type int without an upper bound check.

Copilot Autofix

AI 4 days ago

To fix the incorrect integer conversion, we should ensure that when converting uint32(pid) (parsed from untrusted string input) to int (for logging), an explicit upper bound check for math.MaxInt32 is present. If the value exceeds math.MaxInt32, it should either be capped/truncated, or a fallback value used. This prevents potentially negative or unexpected values from being logged.
Specifically, in file pkg/auditmanager/v1/audit_manager.go, in the method enrichWithKubernetesContext, just before logging with helpers.Int("pid", int(event.PID)), we should check if event.PID (which is of type uint32) is <= math.MaxInt32 before casting. If not, log or handle the fact appropriately (e.g., log max value, or add a warning).
To implement the fix, we need to import "math", and replace the single call helpers.Int("pid", int(event.PID)) with something like:

helpers.Int("pid", safePidToInt(event.PID))

and define a helper function safePidToInt(pid uint32) int that performs the bound check.


Suggested changeset 1
pkg/auditmanager/v1/audit_manager.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/auditmanager/v1/audit_manager.go b/pkg/auditmanager/v1/audit_manager.go
--- a/pkg/auditmanager/v1/audit_manager.go
+++ b/pkg/auditmanager/v1/audit_manager.go
@@ -20,6 +20,7 @@
 	"github.com/kubescape/go-logger"
 	"github.com/kubescape/go-logger/helpers"
 	"github.com/kubescape/node-agent/pkg/auditmanager"
+	"math"
 	"github.com/kubescape/node-agent/pkg/auditmanager/crd"
 	"github.com/kubescape/node-agent/pkg/config"
 	"github.com/kubescape/node-agent/pkg/exporters"
@@ -1158,7 +1159,7 @@
 	containerID, err := am.processTreeManager.GetContainerIDForPid(event.PID)
 	if err != nil {
 		logger.L().Debug("failed to get container ID from process tree manager",
-			helpers.Int("pid", int(event.PID)),
+			helpers.Int("pid", safePidToInt(event.PID)),
 			helpers.Error(err))
 		return
 	}
EOF
@@ -20,6 +20,7 @@
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/node-agent/pkg/auditmanager"
"math"
"github.com/kubescape/node-agent/pkg/auditmanager/crd"
"github.com/kubescape/node-agent/pkg/config"
"github.com/kubescape/node-agent/pkg/exporters"
@@ -1158,7 +1159,7 @@
containerID, err := am.processTreeManager.GetContainerIDForPid(event.PID)
if err != nil {
logger.L().Debug("failed to get container ID from process tree manager",
helpers.Int("pid", int(event.PID)),
helpers.Int("pid", safePidToInt(event.PID)),
helpers.Error(err))
return
}
Copilot is powered by AI and may make mistakes. Always verify output.
if event.PID == 0 || containerID == "" {
logger.L().Debug("skipping Kubernetes enrichment",
helpers.String("reason", "no PID or no container ID"),
helpers.Int("pid", int(event.PID)),

Check failure

Code scanning / CodeQL

Incorrect conversion between integer types High

Incorrect conversion of an unsigned 32-bit integer from
strconv.ParseUint
to a lower bit size type int without an upper bound check.

Copilot Autofix

AI 4 days ago

To fix the issue, we need to ensure that before converting a uint32 PID (from parsed input) to int, we check that its value does not exceed the maximum value for int (i.e., math.MaxInt32), and ideally is not negative (which can't occur for uint32, but input may wrap around if unchecked). We should update the code at line 1170 to check if event.PID is less than or equal to math.MaxInt32 before performing the cast, and use a safe default (such as -1) if it's not in range. This requires importing the math package if it is not already imported. The same check should be performed anywhere the conversion from uint32 (from parsed data) to int is made. In this file, the conversion of interest is on line 1170. The rest of the code shown already parses the PID from a string as a uint32, which is correct.

Suggested changeset 1
pkg/auditmanager/v1/audit_manager.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/pkg/auditmanager/v1/audit_manager.go b/pkg/auditmanager/v1/audit_manager.go
--- a/pkg/auditmanager/v1/audit_manager.go
+++ b/pkg/auditmanager/v1/audit_manager.go
@@ -9,6 +9,7 @@
 	"strings"
 	"sync"
 	"time"
+	"math"
 
 	"github.com/elastic/go-libaudit/v2"
 	"github.com/elastic/go-libaudit/v2/auparse"
@@ -1167,7 +1168,12 @@
 	if event.PID == 0 || containerID == "" {
 		logger.L().Debug("skipping Kubernetes enrichment",
 			helpers.String("reason", "no PID or no container ID"),
-			helpers.Int("pid", int(event.PID)),
+			helpers.Int("pid", func() int {
+				if event.PID <= math.MaxInt32 {
+					return int(event.PID)
+				}
+				return -1
+			}()),
 			helpers.String("containerID", containerID))
 		return
 	}
EOF
@@ -9,6 +9,7 @@
"strings"
"sync"
"time"
"math"

"github.com/elastic/go-libaudit/v2"
"github.com/elastic/go-libaudit/v2/auparse"
@@ -1167,7 +1168,12 @@
if event.PID == 0 || containerID == "" {
logger.L().Debug("skipping Kubernetes enrichment",
helpers.String("reason", "no PID or no container ID"),
helpers.Int("pid", int(event.PID)),
helpers.Int("pid", func() int {
if event.PID <= math.MaxInt32 {
return int(event.PID)
}
return -1
}()),
helpers.String("containerID", containerID))
return
}
Copilot is powered by AI and may make mistakes. Always verify output.
Copy link

github-actions bot commented Oct 1, 2025

Summary:

  • License scan: success
  • Credentials scan: failure
  • Vulnerabilities scan: failure
  • Unit test: success
  • Go linting: failure

Copy link
Contributor

@matthyx matthyx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you check the few comments?
I've also rebased on main and fixed the tests...

err = auditManager.Start(ctx)
if err != nil {
logger.L().Ctx(ctx).Error("error starting the audit manager", helpers.Error(err))
// For POC, we'll continue even if audit manager fails to start
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a FIXME at the beginning of this comment to fix it later

"description": fmt.Sprintf("Audit event of type '%s' detected", auditEvent.Type.String()),
},
Alert: models.Alert{
GeneratorURL: strfmt.URI("https://armosec.github.io/kubecop/alertviewer/"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm


// AuditbeatEvent represents a metricbeat-compatible event structure
// This mimics the mb.Event structure from metricbeat
type AuditbeatEvent struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it OK to exclude with json:"-"?

if exit, err := strconv.ParseInt(data["exit"], 10, 32); err == nil {
event.Exit = int32(exit)
} else {
event.Exit = -1 // FIXME: in case of non-numeric exit codes, such as "EACCES" or "EPERM" should we map them to numeric values?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@slashben check, this is important

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: WIP
Development

Successfully merging this pull request may close these issues.

2 participants