Skip to content

feat(openprotection): publish active-rule open-protection union as ConfigMap#385

Open
matthyx wants to merge 2 commits into
feat/bump-armoapi-rule-openprotectionfrom
feat/open-protection-watcher
Open

feat(openprotection): publish active-rule open-protection union as ConfigMap#385
matthyx wants to merge 2 commits into
feat/bump-armoapi-rule-openprotectionfrom
feat/open-protection-watcher

Conversation

@matthyx

@matthyx matthyx commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

What

Adds an open-protection watcher — the in-cluster producer side of rule-aware collapse protection (design B: active-CRD union). Stacked on #384.

The operator watches RuntimeRuleAlertBinding, resolves the rules each binding activates (by id/name/tags) against the versioned rule library (armosec/rulelibrary), computes the union of those rules' profileDataRequired.opens (armotypes.OpenMatchers), and publishes it as a single ConfigMap (key openProtection). The storage apiserver polls that ConfigMap and pins the matched sensitive prefixes to literal during profile collapse, so anomaly rules such as R0010 ("unexpected /etc/shadow access") keep working through profile generalisation.

Reader side (consumer): kubescape/storage PR #335.

Design

  • Independent of the admission controller — runs its own dynamic watcher so protection works regardless of admission config. Gated by the new openProtectionConfigMapName config (empty = disabled).
  • Debounced + idempotent — coalesces the initial LIST burst; canonical sorted/de-duplicated JSON; skips the write when unchanged (both in the watcher and the publisher, so no needless resourceVersion churn).
  • Scoped, no over-pinning — no bindings ⇒ empty union; deleting the last binding that pinned a prefix drops it on the next reconcile.
  • Resolving selectors in the library (not node-agent's rule engine) keeps the protected set scoped to actually-active rules.

Commits

  1. chore(deps): pull in rulelibrary + bump node-agent/storage — MVS pulls node-agent v0.3.38→v0.3.98 and storage v0.0.239→v0.0.268 (rulelibrary's direct requires). Only API drift: a constant rename in k8s-interface's instanceidhandler helpers ({Kind,Name,Namespace}MetadataKeyRelated{…}MetadataKey, same label strings).
  2. feat(openprotection): publish active-rule open-protection union as ConfigMap — the openprotection package + main wiring + config gate.

Verification

  • go build ./... — clean
  • go vet ./... — clean
  • go test ./openprotection/... ./config/... ./watcher/... — pass (selector extraction; union end-to-end against the embedded library R0010 → /etc/shadow; idempotence; empty/delete transitions; ConfigMap publisher create/update/skip-unchanged via fake clientset)

⚠️ Landing dependency

Depends on rulelibrary pkg/rules (armosec/rulelibrary#93), pinned here to its branch commit c246d47. Merge blocker: #93 must be merged and rulelibrary tagged with a release that contains pkg/rules, then this PR repins to that tag. Until then go mod tidy resolves rulelibrary to the older release tag (v0.0.71) that lacks the package — CI tidy will fail. Also merge #384 first (this is stacked on it).

🤖 Generated with Claude Code

matthyx and others added 2 commits June 15, 2026 07:16
…rotection

Add github.com/armosec/rulelibrary (open-protection union helper) and let MVS
pull its direct requirements forward:
- node-agent v0.3.38 -> v0.3.98-...
- storage   v0.0.239 -> v0.0.268

The only API drift is a constant rename in k8s-interface's instanceidhandler
helpers (same label strings): {Kind,Name,Namespace}MetadataKey ->
Related{Kind,Name,Namespace}MetadataKey. Updated containerprofilewatcher and its
test accordingly.

This is the dependency groundwork for the open-protection watcher (next commit),
which resolves RuntimeRuleAlertBinding selectors against the rule library and
publishes the union of profileDataRequired.opens as a ConfigMap.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
…nfigMap

Add a watcher that keeps the storage apiserver's collapse-protection in sync
with the cluster's active runtime rules (design B: active-CRD union).

The operator watches RuntimeRuleAlertBinding, resolves the rules each binding
activates (by id/name/tags) against the versioned rule library
(armosec/rulelibrary), computes the union of those rules'
profileDataRequired.opens (armotypes.OpenMatchers), and publishes it as a single
ConfigMap (key "openProtection"). The storage apiserver polls that ConfigMap and
pins the matched sensitive prefixes to literal during profile collapse so
anomaly rules such as R0010 ("unexpected /etc/shadow access") keep working. This
is the producer side of "operator writes one object, storage refreshes
periodically"; the reader lives in kubescape/storage.

Design notes:
- Independent of the admission controller: runs its own dynamic watcher so
  protection works regardless of admission config. Gated by the new
  openProtectionConfigMapName config (empty = disabled).
- Reconciles are debounced (coalesce the initial LIST burst) and idempotent
  (canonical, sorted/de-duplicated JSON; skip the write when unchanged, both in
  the watcher and the publisher).
- No bindings -> empty union (no over-pinning). Deleting the last binding that
  pinned a prefix drops it on the next reconcile.

Resolving selectors in the library (not node-agent's rule engine) keeps the set
scoped to actually-active rules. Unit tests cover selector extraction, the
union end-to-end against the embedded library (R0010 -> /etc/shadow),
idempotence, empty/delete transitions, and the ConfigMap publisher
(create/update/skip-unchanged) via a fake clientset.

NOTE: depends on rulelibrary pkg/rules (PR #93), pinned here to its branch
commit. Landing requires #93 merged and rulelibrary tagged with a release that
contains pkg/rules; until then `go mod tidy` will try to resolve rulelibrary to
the older release tag that lacks the package.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Matthias Bertschy <matthias.bertschy@gmail.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: aac589cf-2e30-4790-b6ee-0be2ae3d72eb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/open-protection-watcher

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant