Documentation
¶
Index ¶
- Constants
- func AnalyzeEndpoints(endpoints *[]types.HTTPEndpoint, analyzer *PathAnalyzer) []types.HTTPEndpoint
- func AnalyzeOpen(path string, analyzer *PathAnalyzer) (string, error)
- func AnalyzeOpens(opens []types.OpenCalls, analyzer *PathAnalyzer, sbomSet mapset.Set[string]) ([]types.OpenCalls, error)
- func AnalyzeURL(urlString string, analyzer *PathAnalyzer) (string, error)
- func CollapseAdjacentDynamicIdentifiers(p string) string
- func CompareDynamic(dynamicPath, regularPath string) bool
- func CompareExecArgs(profileArgs, runtimeArgs []string) bool
- func MatchExecArgs(profileArgs []string, argsRequired bool, runtimeArgs []string) bool
- func MergeDuplicateEndpoints(endpoints []*types.HTTPEndpoint) []*types.HTTPEndpoint
- func MergeStrings(existing, new []string) []string
- func ProcessEndpoint(endpoint *types.HTTPEndpoint, analyzer *PathAnalyzer, ...) (*types.HTTPEndpoint, error)
- type CollapseConfig
- type PathAnalyzer
- type SegmentNode
Constants ¶
const ( DynamicIdentifier string = "⋯" // U+22EF: ⋯ (one segment / one arg) WildcardIdentifier string = "*" // zero-or-more path segments (opens only) ExecArgsWildcard string = "⋯⋯" // zero-or-more whole exec args )
--- Identifier constants --- DynamicIdentifier matches exactly one path segment (single-segment wildcard), and in exec args matches exactly one whole argument. WildcardIdentifier matches zero-or-more path segments (glob-style **). It is a PATH/OPENS wildcard only — in exec args a "*" is a plain literal character (a process is frequently invoked with a literal "*", e.g. an unexpanded glob). ExecArgsWildcard is the exec-args zero-or-more wildcard: a standalone argv token that absorbs zero or more whole arguments. It is a dedicated sentinel (doubled U+22EF) precisely so it cannot collide with any real argv token — the same collision-avoidance rationale behind DynamicIdentifier. Exec args therefore need no escaping: every other byte, including "*", is literal.
const ( OpenDynamicThreshold = 50 EndpointDynamicThreshold = 100 )
--- Default collapse thresholds --- OpenDynamicThreshold is the fallback threshold used by AnalyzeOpens when no more-specific CollapseConfig matches the walked path prefix. EndpointDynamicThreshold is the counterpart for AnalyzeEndpoints.
Variables ¶
This section is empty.
Functions ¶
func AnalyzeEndpoints ¶
func AnalyzeEndpoints(endpoints *[]types.HTTPEndpoint, analyzer *PathAnalyzer) []types.HTTPEndpoint
func AnalyzeOpen ¶ added in v0.0.118
func AnalyzeOpen(path string, analyzer *PathAnalyzer) (string, error)
func AnalyzeOpens ¶ added in v0.0.118
func AnalyzeURL ¶
func AnalyzeURL(urlString string, analyzer *PathAnalyzer) (string, error)
func CollapseAdjacentDynamicIdentifiers ¶ added in v0.0.275
CollapseAdjacentDynamicIdentifiers replaces runs of adjacent DynamicIdentifier segments (e.g. "/a/⋯/⋯/b") with a single WildcardIdentifier ("/a/*/b"). Static segments between dynamic identifiers prevent collapsing. String wrapper over the internal byte-level collapseAdjacentDynamic, intended for test coverage.
func CompareDynamic ¶ added in v0.0.119
CompareDynamic checks whether `regularPath` is matched by `dynamicPath`. The dynamic path may contain DynamicIdentifier (⋯, exactly-one-segment wildcard) or WildcardIdentifier (*, zero-or-more-segment mid-path / one-or-more-segment trailing wildcard). The node-agent R0002 rule (Files Access Anomalies) uses this at every file-open to decide whether the access is in-profile.
Anchoring contract:
- Anchored patterns (start with `/`): `/etc/*` matches files UNDER /etc but NOT the bare `/etc` directory itself, mirroring shell glob semantics. This avoids R0002 silently allowing access to a profiled directory's parent.
- Unanchored `*` (no leading slash): explicit catch-all that also matches the root path `/`. The only way to whitelist `/` itself is an explicit unanchored `*`.
Trailing-slash insensitivity: `/etc/` is treated as `/etc`, and `/etc/passwd/` as `/etc/passwd`. Trailing empty path components from `strings.Split` are trimmed so `len(regular) > 0` correctly reflects the presence of a real path tail when matching trailing `*`.
The empty regular path (`""`) is treated as "no path" and matches nothing — distinct from the root path `/`, which matches unanchored `*` per the contract above.
func CompareExecArgs ¶ added in v0.0.278
CompareExecArgs reports whether runtimeArgs matches profileArgs, treating an empty profileArgs as "no constraint" (matches anything). Non-empty vectors are matched anchored at both ends by matchExecArgsStrict.
Use MatchExecArgs to express "argv must be empty"; CompareExecArgs is kept for callers that have not migrated to the ArgsRequired-aware API.
func MatchExecArgs ¶ added in v0.0.278
MatchExecArgs reports whether runtimeArgs satisfies a profile entry's argv contract. argsRequired carries the entry's ExecCalls.ArgsRequired flag:
false → no constraint; matches any runtimeArgs.
true → strict anchored match against profileArgs (empty profileArgs
matches only an empty runtimeArgs).
The flag exists because v1beta1.ExecCalls.Args is `json:",omitempty"`: an explicit `args: []` round-trips back as nil, so the stored vector alone cannot distinguish "no constraint" from "must have no args".
func MergeDuplicateEndpoints ¶
func MergeDuplicateEndpoints(endpoints []*types.HTTPEndpoint) []*types.HTTPEndpoint
MergeDuplicateEndpoints folds duplicates and merges same-path specific-port endpoints into a wildcard-port (:0) sibling. Folding is symmetric and is keyed on the same triple HTTPEndpoint.Equal compares — (Endpoint, Direction, Internal). An Internal=false endpoint will therefore NOT merge with an Internal=true sibling even if their path and direction match.
- If a specific-port endpoint is encountered AFTER its :0 sibling, the specific-port methods/headers are merged INTO the wildcard entry.
- If a specific-port endpoint is encountered BEFORE its :0 sibling, it is initially recorded; when the wildcard arrives we sweep `seen` for same-(path, direction, Internal) specific-port siblings, fold them into the wildcard, and remove them from the output.
This contract was tightened on the back of upstream review on kubescape/storage#316 — a single :0 entry must NOT cause unrelated concrete-port endpoints to be wildcarded; only same-path same-Internal siblings fold.
func MergeStrings ¶ added in v0.0.118
func ProcessEndpoint ¶
func ProcessEndpoint(endpoint *types.HTTPEndpoint, analyzer *PathAnalyzer, newEndpoints []*types.HTTPEndpoint) (*types.HTTPEndpoint, error)
Types ¶
type CollapseConfig ¶ added in v0.0.275
--- Collapse configuration --- CollapseConfig controls the threshold at which children of a trie node (under the given path Prefix) are collapsed into a dynamic node (⋯). Longest-prefix wins at analysis time.
func DefaultCollapseConfig ¶ added in v0.0.275
func DefaultCollapseConfig() CollapseConfig
DefaultCollapseConfig returns a value copy of the package-private fallback. Mutating the returned struct does not affect package state. The accessor pattern matches DefaultCollapseConfigs() — both protect the threshold-tuning surface from accidental cross-test or cross-caller corruption.
func DefaultCollapseConfigs ¶ added in v0.0.275
func DefaultCollapseConfigs() []CollapseConfig
DefaultCollapseConfigs returns a defensive copy of the package-level default per-prefix collapse thresholds. Callers that mutate the result will not affect the package state or other callers.
type PathAnalyzer ¶
type PathAnalyzer struct {
RootNodes map[string]*SegmentNode
// contains filtered or unexported fields
}
func NewPathAnalyzer ¶
func NewPathAnalyzer(threshold int) *PathAnalyzer
NewPathAnalyzer builds an analyzer with a single global collapse threshold and no per-prefix overrides — equivalent behaviour to the pre-CollapseConfig world. Retained so existing callers don't need to change.
func NewPathAnalyzerWithConfigs ¶ added in v0.0.275
func NewPathAnalyzerWithConfigs(defaultThreshold int, configs []CollapseConfig) *PathAnalyzer
NewPathAnalyzerWithConfigs builds an analyzer whose collapse threshold can vary per path prefix. defaultThreshold applies when no CollapseConfig in configs matches; configs are checked longest-prefix-wins at walk time.
configs is copied so the caller can reuse or mutate the slice without affecting the analyzer.
func (*PathAnalyzer) AnalyzePath ¶
func (ua *PathAnalyzer) AnalyzePath(p, identifier string) (string, error)
func (*PathAnalyzer) FindConfigForPath ¶ added in v0.0.275
func (ua *PathAnalyzer) FindConfigForPath(path string) CollapseConfig
FindConfigForPath returns a value copy of the CollapseConfig whose Prefix matches `path` with the longest match. Falls back to the analyzer's default config (Prefix:"/") when no per-prefix override applies, so the result is always meaningful — there is no "no match" signal.
Returning by value keeps the analyzer's internal state immutable from callers. NewPathAnalyzerWithConfigs already makes a defensive inbound copy of `configs`; this is its outbound twin. Without it, `cfg := analyzer.FindConfigForPath(p); cfg.Threshold = 1` would silently mutate the analyzer's threshold map for every future call.
type SegmentNode ¶
type SegmentNode struct {
SegmentName string
Count int
Children map[string]*SegmentNode
}
func (*SegmentNode) IsNextDynamic ¶
func (sn *SegmentNode) IsNextDynamic() bool