kubescape / kubescape/storage

Aggregate user-managed (ug- prefix) profiles into the consolidated ContainerProfile

Open
#315 6 comments 0 reactions 0 assignees View on GitHub
Dominant language
Go
Stars
4
Forks
22
Avg merge
20h 43m
Merged PRs (30d)
33

Description

## Context

The node-agent's unified `ContainerProfileCache` (see [kubescape/node-agent#788](https://github.com/kubescape/node-agent/pull/788)) is CP-direct: it reads the consolidated `ContainerProfile` at the stable `GetSlug(false)` name as the single source of truth. The storage server already aggregates the per-tick time-series `ContainerProfile` writes (named `-`) into a consolidated CP at the `` name — that part works well.

What it does NOT aggregate is the **user-managed** profiles published at the `"ug-" + workloadSlug` well-known name. These are authored by humans (either directly or via the kubescape UI) and carry the annotation:

```yaml
kubescape.io/managed-by: User
```

The legacy `ApplicationProfileCache.handleUserManagedProfile` auto-discovered these via the annotation + `ug-` prefix and merged them into the workload's cached profile (see [legacy source, deleted in the migration PR](https://github.com/kubescape/node-agent/blob/900e72bd/pkg/objectcache/applicationprofilecache/applicationprofilecache.go#L269-L351)).

## Current state in the new cache

As a short-term fix in PR #788, the node-agent fetches `ug-` AP and NN on every `addContainer` and on every reconciler refresh tick, then projects them on top of the consolidated CP. This works but:

- Adds 2 RPCs per container per refresh tick (on top of the 1 CP GET).
- Duplicates the merge logic between node-agent and (eventually) storage.
- Splits the \"CP-direct\" principle: the CP isn't actually authoritative because the cache still has to go fetch user-managed profiles separately.
- Every agent on every node does the merge independently; server-side aggregation would do it once.

## Proposal

When the storage server consolidates time-series `ContainerProfile` writes into the stable-named CP (via `ContainerProfileProcessor.consolidateKeyTimeSeries`), **also merge the matching user-managed profile** (`ug-` if it exists) into the output.

Matching rules should mirror what `handleUserManagedProfile` did:

- Workload slug: `instanceID.GetSlug(true)` (no container name).
- Per-container: find the matching `ApplicationProfileContainer` / `NetworkNeighborhoodContainer` by `Name` across `.Spec.Containers + .Spec.InitContainers + .Spec.EphemeralContainers` and merge its fields into the consolidated CP's flat spec.
- Completion / Status annotations come from the base CP; user-managed data is additive.

The merge math already exists in node-agent's [projection.go](https://github.com/kubescape/node-agent/blob/cp-cache/pkg/objectcache/containerprofilecache/projection.go) (ported from the legacy `performMerge` / `mergeNetworkNeighbors`) — the same logic needs to live in storage instead.

## Acceptance

- A consolidated `ContainerProfile` at `` reflects data from both the time-series writes AND any user-managed `ug-` AP/NN, merged per-container.
- Re-consolidation fires whenever either source changes (so user edits to `ug-` propagate).
- Once this is in place, node-agent can drop its client-side `ug-` fetch and the corresponding refresh path (see [deviation doc](https://github.com/kubescape/node-agent/blob/cp-cache/.omc/plans/containerprofile-cache-deviations-from-consensus.md) \"Path A.2\").

## Related

- node-agent PR: https://github.com/kubescape/node-agent/pull/788
- Plan doc: `.omc/plans/containerprofile-cache-unification-consensus.md` in the node-agent PR
- Current cache-side implementation: `pkg/objectcache/containerprofilecache/containerprofilecache.go` `tryPopulateEntry` (look for \"user-managed\" comments)

## Non-goals

- User-defined profiles referenced by pod label (`kubescape.io/profile: `). Those stay cache-side because the name is arbitrary and chosen per-pod; they are not \"well-known\".

Contributor guide

Open the contributing guide

Research direction

Start at ContainerProfileProcessor.consolidateKeyTimeSeries and trace how stable-named ContainerProfiles are built from time-series writes. Compare the merge behavior in node-agent's projection.go and the legacy handleUserManagedProfile path, then identify the storage events needed when either source changes. Done means the consolidated profile includes matching ug- data per container and reconsolidates after user-managed edits.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.