feat(trustedImages): support multiple trust groups
Summary
Reworks console.trustedImages to support multiple trust groups managed by the chart, bound to a single rule. Replaces the previous single-group fields (name, registryMatches, defaultEffect) with groups[], extraGroups[], and rule. New defaults produce the same Twistlock state as before (one BigBang-Trusted group covering ironbank, rule with effect=alert), so chart-default consumers see no behavioral change. extraGroups lets downstream consumers layering values on top of the chart (kustomize SMP on a HelmRelease, subchart values, Argo CD valueFiles stacks) append entries without replacing the base list.
Closes #255 (closed).
Schema
console:
trustedImages:
enabled: true
groups:
- name: BigBang-Trusted
registryMatches: ["registry1.dso.mil/ironbank/*"]
- name: tenant-trusted
registryMatches:
- "registry1.dso.mil/<tenant>/<image-a>:*"
- "registry1.dso.mil/<tenant>/<image-b>:*"
extraGroups: [] # appended to `groups` at template time; for overlay-driven additions
rule:
name: BigBang-Trusted
effect: alert # ignore | alert | block
collections: ["All"]
deniedGroups: [] # optionalThe chart's rule auto-derives allowedGroups from groups[].name plus extraGroups[].name. Chart deletes-and-recreates managed entries by name; unmanaged groups and rules on the console are preserved.
Why extraGroups
Helm and kustomize both replace lists on merge rather than appending. A consumer that wants to add one tenant-specific group on top of a base set declared in groups would today have to redeclare every base entry. Splitting overrides under a separate map key sidesteps that: base sets groups, overlay sets extraGroups, the chart concatenates them at template time. Single-chart deployments leave extraGroups empty and put everything in groups. The pattern matches Bitnami's extraEnvVars / extraVolumes convention.
What changed
chart/values.yaml-- replacesname/registryMatches/defaultEffectwithgroups,extraGroups, andrule. Documents trustedImages as an allowlist evaluation policy with three common postures (default-alert / default-deny / audit + explicit deny) and the deniedGroups-precedence trap.groupsdefaults to oneBigBang-Trustedentry covering ironbank, matching prior chart behavior.chart/templates/init/secret-console.yaml-- rendersTWISTLOCK_TRUST_POLICY_JSONfrom the mergedgroups + extraGroupsplusrule. Adds template-time guards that abort rendering if (a) any group in the merged set has emptyregistryMatches(Twistlock/trust/datarejects empty groups with HTTP 400), (b) any groupnamecollides acrossgroups+extraGroups, (c)groupsandextraGroupsare both empty, or (d) any of the removed keys (name,registryMatches,defaultEffect) is still set in values, with a fail message pointing at the new shape.chart/scripts/twistlock-trusted-images.sh-- consumesTWISTLOCK_TRUST_POLICY_JSON. Uses jq to GET the existing policy, strip chart-managed entries by name, append new groups + prepend new rule with auto-derivedallowedGroups, PUT. Preserves unmanaged entries.- Fixes script's directory resolution to use
BASH_SOURCE[0]instead of$0so the script is testable when sourced from a context whose$0is not its sibling. chart/unittests/trustedImages_test.yaml-- 13 cases covering the new rendering path, theextraGroupsoverlay/merge paths, the empty-group and duplicate-name failure assertions, the empty-groups-and-extraGroups failure, and a removed-key rejection case for each of the three removed fields. Picked up by thehelm unit testsjob inbigbang-package-v2.yaml.chart/tests/twistlock-trusted-images.bats-- 10 cases against the script pipeline (group/rule replacement, preservation, prepending, allowedGroups derivation, deniedGroups, collections defaulting). Uses bats-support / bats-assert / bats-file. Not currently wired into the package pipeline; follow-up MR to bb-pipeline-templates can include thebats-testcomponent.
Default behavior
Chart-default consumers (no override of trustedImages.*) see no behavioral change. The new defaults render the same Twistlock state the previous defaults rendered: one group named BigBang-Trusted containing registry1.dso.mil/ironbank/*, one rule named BigBang-Trusted allowing that group with effect=alert.
Consumers who previously overrode name, registryMatches, or defaultEffect need to translate their overlay to the new shape on upgrade. The chart fails template rendering with a migration message if any of the removed keys is still set in values.
Relevant logs/screenshots
helm-unittest (cd chart && helm unittest . -f "unittests/**/*_test.yaml", same invocation as the pipeline helm unit tests job)
PASS test console deployment extraEnv unittests/console_deployment_test.yaml
PASS console.trustedImages renders the right env vars unittests/trustedImages_test.yaml
Charts: 1 passed, 1 total
Test Suites: 2 passed, 2 total
Tests: 16 passed, 16 totalbats (BATS_LIB_PATH=/opt/lib bats chart/tests/twistlock-trusted-images.bats)
1..10
ok 1 trusted-images script exists and is sourceable
ok 2 multi-group: builds valid policy from empty existing state
ok 3 multi-group: preserves unrelated existing groups and rules
ok 4 multi-group: same-named existing group is replaced not duplicated
ok 5 multi-group: same-named existing rule is replaced not duplicated
ok 6 multi-group: chart rule is prepended to position 0
ok 7 multi-group: rule allowedGroups derived from groups in YAML order
ok 8 multi-group: deniedGroups passed through
ok 9 multi-group: collections default to All when omitted
ok 10 multi-group: registryMatches becomes images in API bodyEnd-to-end deployment validation
Deployed to a representative cluster with five chart-managed groups (ironbank-trusted, aws-eks, external-bootstrap, <tenant>-trusted, <tenant>-trusted-test-images) and one rule.
Init job completed successfully (94s). Trust policy verified via the Twistlock API:
{
"rules": [
{"name": "<deployment>-trusted", "allowedGroups": ["ironbank-trusted","aws-eks","external-bootstrap","<tenant>-trusted","<tenant>-trusted-test-images"], "effect": "alert"},
{"name": "Default - alert all", "allowedGroups": null, "effect": "alert"}
],
"groups": [
{"_id": "ironbank-trusted", "image_count": 1},
{"_id": "aws-eks", "image_count": 3},
{"_id": "external-bootstrap", "image_count": 10},
{"_id": "<tenant>-trusted", "image_count": 9},
{"_id": "<tenant>-trusted-test-images", "image_count": 1}
]
}Untrusted-image audit events under the new rule: 0 since deploy.
Empty-group guard
Verified failure at helm template time when a group has no registryMatches:
Error: execution error at (twistlock/templates/init/secret-console.yaml:60:6):
console.trustedImages: merged groups[1] (name="empty") has no registryMatches.
Twistlock /trust/data rejects groups with empty images (HTTP 400). Either
add patterns or remove the group.Duplicate-name guard
Verified failure at helm template time when a group name collides across groups and extraGroups:
Error: execution error at (twistlock/templates/init/secret-console.yaml:64:6):
console.trustedImages: duplicate group name "ironbank" across groups+extraGroups.
Each group name must be unique across the merged set.Removed-key guard
Verified failure at helm template time when a removed key is still set in values:
Error: execution error at (twistlock/templates/init/secret-console.yaml:50:6):
console.trustedImages.name was removed. Use console.trustedImages.groups[]
and console.trustedImages.rule instead. See the trustedImages section of
values.yaml for the new shape.Linked Issue
Upgrade Notices
0.28.0-bb.0 is a breaking change to the console.trustedImages values schema. The single-group fields console.trustedImages.name, .registryMatches, and .defaultEffect are removed. Default behavior is unchanged for consumers who did not override these fields: the chart still produces a BigBang-Trusted group covering registry1.dso.mil/ironbank/* and a BigBang-Trusted rule allowing it with effect=alert.
Consumers who overrode any of the removed fields must translate their overlay to the new shape on upgrade. The chart fails template rendering with a clear migration message if any removed key is still set.
Before:
console:
trustedImages:
name: "MyOrg-Trusted"
registryMatches:
- "registry1.dso.mil/ironbank/*"
- "registry.example.com/my-org/*"
defaultEffect: "block"After:
console:
trustedImages:
groups:
- name: "MyOrg-Trusted"
registryMatches:
- "registry1.dso.mil/ironbank/*"
- "registry.example.com/my-org/*"
rule:
name: "MyOrg-Trusted"
effect: "block"