feat(rules): symmetric R0011 egress / R0012 ingress, port-aware, no IP-class gate - #94
Open
entlein wants to merge 5 commits into
Open
feat(rules): symmetric R0011 egress / R0012 ingress, port-aware, no IP-class gate#94entlein wants to merge 5 commits into
entlein wants to merge 5 commits into
Conversation
R0011 keeps its external-only scope (!is_private_ip); internal traffic gets its own rule instead of widening R0011 — rewriting R0011's scope broke Test_21/28 (kube-dns FPs) when tried in the fork CT. R0012 alerts on OUTGOING to private addresses (loopback excluded — is_private_ip counts 127.0.0.1/::1 as private) not allowlisted by the profile's egress addresses, which includes serviceRef/serviceSelector-resolved entries. Uses the port-aware matcher; behaves address-only until the port projection lands, then becomes port-sensitive with no rules change. A selector clause (was_selector_in_egress) is added one-line when the peer-selector fields merge. Same defaults as R0011; uniqueId keyed on addr_port_proto; bound in the default binding (new rule names are inert until bound). Signed-off-by: tanzee <einentlein@gmail.com>
Per design review: R0011 (egress) and R0012 (ingress, new) are symmetric twins. Neither uses is_private_ip — internal and external peers are treated alike, so lateral movement to unlisted internal peers alerts; only loopback is excluded. Allowlisting internal traffic is the profile's job (addresses, resolved serviceRef/serviceSelector entries), not the rule's. Both use the port-aware matcher (address-only until port projection lands). On HOST (incoming) events the gadget's dstAddr/dstPort carry the remote peer and local port. R0011's scope widens to internal egress: component tests whose profiles do not list kube-dns et al. will alert until their profiles do — that pressure is the feature. Signed-off-by: tanzee <einentlein@gmail.com>
…eset Deployable over any kubescape install to replace the stock rules; namespace templated. A drift test pins the chart copy to the CI-validated test-chart copy so the shipped semantics are always the tested ones. Signed-off-by: tanzee <einentlein@gmail.com>
…ntegration branch) Signed-off-by: tanzee <einentlein@gmail.com>
charts/kubescape-rules was a third copy of the ruleset: a verbatim duplicate of tests/chart/templates/node-agent/default-rules.yaml, kept in step by a drift test that existed only to guard the copy. No workflow published it, so nothing consumed it as a chart. The rules belong in kubescape/rulelibrary, which already ships R0011 and R0012 with per-rule tests and is the direction this repo already syncs FROM (see "rules: sync severity + MITRE mapping from rulelibrary main"). node-agent keeps its test-chart copy because CI has to pin the semantics it validates; it does not need a distributable one as well. The drift test goes with it — it asserted nothing once the file it compared against is gone. Neither path exists on main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rules-only PR: the single place the R0011/R0012 semantics land, consuming the engines from #85 (ports), #90 (peer selectors), #93 (serviceRef resolution).
!is_private_ip, gains the port-aware matcher. Internal + external symmetric, loopback excluded.pktType == 'HOST'viawas_address_port_protocol_in_ingress. Bound in the default binding (unbound rule names are inert).was_selector_in_*) is a one-line addition once cel(network): peer-selector matching for egress/ingress (rebase of #62) #90 merges.Expected CT fallout: tests whose profiles omit kube-dns/apiserver internal egress will alert — the allowlist pressure is the feature; fixes belong in profiles/fixtures, not rule scope.
🤖 Generated with Claude Code
https://claude.ai/code/session_01A8UV2B7b6dpDJQci31aC6c