Skip to content

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

Open
matthyx wants to merge 3 commits into
mainfrom
feat/open-protection-watcher
Open

feat(openprotection): publish active-rule open-protection union as ConfigMap#385
matthyx wants to merge 3 commits into
mainfrom
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 3 commits June 12, 2026 15:10
Modernize the operator's armoapi-go from v0.0.673 to v0.0.719 to pick up the
rule open-protection types (armotypes.OpenMatchers / UnionOpenProtection,
ProfileDataRequired schema). This unblocks a follow-up watcher that resolves
RuntimeRuleAlertBinding selectors against the rule library and publishes the
union of profileDataRequired.opens for the storage apiserver.

The bump is additive: node-agent (v0.3.38) and storage (v0.0.239) compile
unchanged against the newer armoapi, so no coordinated bump is required here.
go build, go vet, and the watcher test suite all pass.

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

@matthyx matthyx moved this to WIP in KS PRs tracking Jun 19, 2026
@matthyx matthyx force-pushed the feat/bump-armoapi-rule-openprotection branch from e953a9e to c5fb1fb Compare June 19, 2026 05:29
Base automatically changed from feat/bump-armoapi-rule-openprotection to main June 19, 2026 06:11
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.

1 participant