Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bugfix/dynamic #417

Merged
merged 2 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions pkg/ruleengine/v1/r0006_unexpected_service_account_token_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/kubescape/node-agent/pkg/objectcache"
"github.com/kubescape/node-agent/pkg/ruleengine"
"github.com/kubescape/node-agent/pkg/utils"
"github.com/kubescape/storage/pkg/registry/file/dynamicpathdetector"

apitypes "github.com/armosec/armoapi-go/armotypes"
traceropentype "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/open/types"
Expand Down Expand Up @@ -57,7 +58,7 @@ func getTokenBasePath(path string) string {
}

// normalizeTokenPath removes timestamp directories from the path while maintaining
// the essential structure. Optimized for minimal allocations.
// the essential structure. Handles both timestamp directories and dynamic identifiers.
func normalizeTokenPath(path string) string {
// Get the base path - if not a token path, return original
basePath := getTokenBasePath(path)
Expand All @@ -74,6 +75,12 @@ func normalizeTokenPath(path string) string {
return filepath.Join(basePath, finalComponent)
}

// Check if the path contains a dynamic identifier
if strings.Contains(middle, dynamicpathdetector.DynamicIdentifier) {
// If it has a dynamic identifier, keep the base structure but normalize the variable part
return filepath.Join(basePath, dynamicpathdetector.DynamicIdentifier, finalComponent)
}

// Process middle parts
var normalizedMiddle strings.Builder
parts := strings.Split(middle, "/")
Expand All @@ -83,7 +90,9 @@ func normalizeTokenPath(path string) string {
}
// Skip timestamp directories (starting with ".." and containing "_")
if strings.HasPrefix(part, "..") && strings.Contains(part, "_") {
continue
normalizedMiddle.WriteString("/")
normalizedMiddle.WriteString(dynamicpathdetector.DynamicIdentifier)
break // We only need one dynamic identifier
}
normalizedMiddle.WriteString("/")
normalizedMiddle.WriteString(part)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package ruleengine

import (
"fmt"
"testing"

traceropentype "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/trace/open/types"
eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
"github.com/kubescape/node-agent/pkg/utils"
"github.com/kubescape/storage/pkg/apis/softwarecomposition/v1beta1"
"github.com/kubescape/storage/pkg/registry/file/dynamicpathdetector"
)

func createTestEvent0006(containerName, path string, flags []string) *traceropentype.Event {
Expand Down Expand Up @@ -99,6 +101,18 @@ func TestR0006UnexpectedServiceAccountTokenMount(t *testing.T) {
}}),
expectFailure: false, // Should pass because normalized directory matches
},
// Tests with EKS paths and timestamps
{
name: "whitelisted eks token access with timestamps with compress",
event: createTestEvent0006("test",
"/run/secrets/eks.amazonaws.com/serviceaccount/..2024_11_1111_24_34_58.850095521/token",
[]string{"O_RDONLY"}),
profile: createTestProfile0006("test", []v1beta1.OpenCalls{{
Path: fmt.Sprintf("/run/secrets/eks.amazonaws.com/serviceaccount/%s/token", dynamicpathdetector.DynamicIdentifier),
Flags: []string{"O_RDONLY"},
}}),
expectFailure: false, // Should pass because normalized directory matches
},
// Tests with k8s paths and timestamps
{
name: "non whitelisted k8s token access with timestamps",
Expand Down
71 changes: 71 additions & 0 deletions pkg/ruleengine/v1/r0010_unexpected_sensitive_file_access_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
eventtypes "github.com/inspektor-gadget/inspektor-gadget/pkg/types"
"github.com/kubescape/node-agent/pkg/utils"
"github.com/kubescape/storage/pkg/apis/softwarecomposition/v1beta1"
"github.com/kubescape/storage/pkg/registry/file/dynamicpathdetector"
)

func createTestEvent(path string, flags []string) *traceropentype.Event {
Expand Down Expand Up @@ -113,6 +114,76 @@ func TestR0010UnexpectedSensitiveFileAccess(t *testing.T) {
expectAlert: true,
description: "Should alert for path traversal attempts",
},
// Dynamic path matching tests
{
name: "Dynamic directory match",
event: createTestEvent("/var/log/2024_01_01/app.log", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/var/log/" + dynamicpathdetector.DynamicIdentifier + "/app.log"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when path matches dynamic pattern",
},
{
name: "Dynamic multi-segment match",
event: createTestEvent("/var/log/2024/01/01/app.log", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/var/log/" + dynamicpathdetector.DynamicIdentifier + "/" + dynamicpathdetector.DynamicIdentifier + "/" + dynamicpathdetector.DynamicIdentifier + "/app.log"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when path matches multiple dynamic segments",
},
{
name: "Dynamic prefix match",
event: createTestEvent("/data/customer1/config.json", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/" + dynamicpathdetector.DynamicIdentifier + "/customer1/config.json"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when path matches dynamic prefix",
},
{
name: "Dynamic suffix match",
event: createTestEvent("/etc/config/v1.2.3/settings.yaml", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/etc/config/" + dynamicpathdetector.DynamicIdentifier + "/settings.yaml"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when path matches dynamic suffix",
},
{
name: "Dynamic timestamp directory match",
event: createTestEvent("/var/log/pods/2024_01_01_12_00_00/container.log", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/var/log/pods/" + dynamicpathdetector.DynamicIdentifier + "/container.log"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when timestamp directory matches dynamic pattern",
},
{
name: "Dynamic service account token path",
event: createTestEvent("/run/secrets/kubernetes.io/serviceaccount/..2024_01_01_12_00_00.123456789/token", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/run/secrets/kubernetes.io/serviceaccount/" + dynamicpathdetector.DynamicIdentifier + "/token"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when service account token path matches dynamic pattern",
},
{
name: "Sensitive file with dynamic path not whitelisted",
event: createTestEvent("/etc/kubernetes/..2024_01_01/secret.yaml", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/var/log/" + dynamicpathdetector.DynamicIdentifier + "/app.log"}, []string{"O_RDONLY"}),
additionalPaths: []interface{}{"/etc/kubernetes"},
expectAlert: true,
description: "Should alert when sensitive file with timestamp is not whitelisted",
},
{
name: "Multiple whitelisted dynamic paths",
event: createTestEvent("/var/log/2024_01_01/app.log", []string{"O_RDONLY"}),
profile: createTestProfile("test",
[]string{
"/tmp/" + dynamicpathdetector.DynamicIdentifier + "/test.log",
"/var/log/" + dynamicpathdetector.DynamicIdentifier + "/app.log",
},
[]string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when path matches one of multiple dynamic patterns",
},
{
name: "Mixed static and dynamic segments",
event: createTestEvent("/data/users/john/2024_01_01/profile.json", []string{"O_RDONLY"}),
profile: createTestProfile("test", []string{"/data/users/john/" + dynamicpathdetector.DynamicIdentifier + "/profile.json"}, []string{"O_RDONLY"}),
expectAlert: false,
description: "Should not alert when static segments match and dynamic segment matches timestamp",
},
}

for _, tt := range tests {
Expand Down
Loading