Commit 9f33b47
authored
[security] Reserve
* tasks.
Signed-off-by: Volkan Özçelik <volkan.ozcelik@broadcom.com>
* fix(nexus): reserve spike/system/* from substring policy matches
This commit has two independent parts. They are unrelated to each other
and are together only because the integration suite had been sitting
uncommitted in the working tree since 2026-07-18; folding it in now
avoids stranding it further behind an unrelated branch.
Part 1 is the substantive change. Part 2 is previously written work,
committed here unmodified apart from being verified to still build,
vet, and lint under its build tag.
================================================================
Part 1: reserved system namespaces (Spec: policy-pattern-anchoring)
================================================================
Policy patterns are regular expressions matched with MatchString, so an
unanchored pattern is a substring test. That is intended behavior for
ordinary paths and stays unchanged. It was not acceptable for the three
paths through which SPIKE authorizes its own privileged operations.
Policy management is gated by CheckPolicyAccess against the literal path
spike/system/acl. A policy whose PathPattern was "spike", "system", or
"acl" therefore matched that gate by substring and authorized the
workload to create and modify any policy, including one granting itself
super on every path. PathPattern "spike" is plausible for an operator
whose own secrets live under a spike/ namespace. The same reached
spike/system/secret and spike/system/cipher/exec. Nothing reserved those
namespaces.
A policy may now reach a reserved path only when it describes that path
rather than merely containing it: its full-match form, ^(?:pattern)$,
must still match. So ^spike/system/acl$, spike/system/acl,
^spike/system/.*$ and .* all qualify, while acl, system and spike do
not. The SPIFFE ID pattern must be anchored or an unambiguous catch-all,
so a delegation written for spiffe://example.org/admin cannot be claimed
by spiffe://example.org/admin-attacker.
Enforcement sits at two points. UpsertPolicy rejects a violating policy
so the operator learns at authoring time, and CheckPolicyAccess declines
to honor one independently, covering policies stored before the rule
existed. The second point is load-bearing rather than redundant: the
SQLite backend recompiles both patterns from the stored strings on every
access check, so a guard placed only at creation would hold for the
in-memory backend and do nothing in production.
A purely syntactic "must start with ^ and end with $" rule was
implemented first and rejected. .* and ^.*$ are the same regular
expression, so accepting one and refusing the other polices spelling
without changing what is granted, and it broke deliberate wildcard
policies already under test.
Documentation is corrected throughout. The reference page carried a
"Path Pattern Examples" block of ^-only prefixes, one annotated "Only
the specific creds resource" for a pattern that also matches
secrets/database/credsXYZ, and a "Common Errors" section that offered
unanchored patterns as the remediation. CLAUDE.md framed the only
correctness axis as regex-versus-glob and marked two unanchored patterns
correct. Also fixes a shipped glob in the federation example and the
non-existent YAML keys in sample-policy.yaml, which could never have
loaded.
The rendered site is rebuilt. That picks up the Recipes section and the
multi-tenancy page, neither of which had ever been rendered, and drops
ten orphaned pages under docs/getting-started/ that had no source in
docs-src; one of them was still serving the superseded policy guidance
at a live URL. This accounts for most of the file count here.
Reported by kanywst. The substring behavior they reported is documented
and intended; the escalation path underneath it was not, and was found
while assessing the report.
================================================================
Part 2: live Pilot integration suite, Slice B (Spec: integration-tests)
================================================================
Written 2026-07-18 and left uncommitted. Adds
app/spike/internal/cmd/integration, which drives the built spike binary
end to end against a running `make start` environment rather than
importing command internals, so it exercises the seams an operator does.
Double-gated so it never runs in the normal suite: the `integration`
build tag keeps it out of ordinary builds, and TestMain exits early
unless SPIKE_INTEGRATION_TEST=1 confirms a live environment may be
probed.
Three cases. TestPilotSmokePass covers secret put/get/delete, policy
create/get by name, and a cipher round trip, asserting data lands on
stdout. TestPilotWarnsWhenNexusUnreachable points one invocation at a
closed port, leaving the running Nexus untouched, and asserts the Pilot
warns without hanging or panicking; the no-hang assertion doubles as a
guard on the open SVID-acquisition-timeout task. Both are
non-destructive and clean up after themselves.
TestPilotDeniesWhenNexusUninitialized is destructive and gated behind a
second flag, SPIKE_INTEGRATION_DESTRUCTIVE=1: reaching a
reachable-but-uninitialized Nexus means killing Nexus and every Keeper,
losing the in-memory shards, then restarting Nexus alone. It kills the
Nexus it spawned, since that process is outside `make start`'s process
table and would otherwise hold the port past a Ctrl+C.
Both error paths funnel through stdout.HandleAPIError and exit 0 (the
subcommands use cobra Run, not RunE), so the assertions key on the
stderr message and the no-hang property, not the exit code.
Adds `make integration-test` and `make integration-test-destructive`,
marks the TASKS.md Phase 3 item done, and records the spec's two open
questions as resolved: land in-repo now behind the opt-in gate, and stay
complementary to the recovery drill rather than subsuming it.
Spec: specs/policy-pattern-anchoring.md
Spec: specs/integration-tests.md
Signed-off-by: Volkan Özçelik <volkan.ozcelik@broadcom.com>
---------
Signed-off-by: Volkan Özçelik <volkan.ozcelik@broadcom.com>
Signed-off-by: Volkan Özçelik <volkan.ozcelik@broadcom.com>spike/system/* from substring policy matches (#301)1 parent 01954f8 commit 9f33b47
123 files changed
Lines changed: 12147 additions & 18968 deletions
File tree
- .context
- app
- nexus/internal
- route/acl/policy
- state/base
- spike/internal/cmd
- integration
- policy
- diagrams
- docs-src/content
- architecture/adrs
- recipes
- usage/commands
- docs
- about
- intro
- project-status
- architecture
- adrs
- adr-0001
- adr-0002
- adr-0003
- adr-0004
- adr-0005
- adr-0006
- adr-0007
- adr-0008
- adr-0009
- adr-0010
- adr-0011
- adr-0012
- adr-0013
- adr-0014
- adr-0015
- adr-0016
- adr-0017
- adr-0018
- adr-0019
- adr-0020
- adr-0021
- adr-0022
- adr-0023
- adr-0024
- adr-0025
- adr-0026
- adr-0027
- adr-0028
- adr-0029
- adr-0030
- adr-0031
- adr-0032
- adr-0033
- architectural-decision-records
- security-model
- system-overview
- community
- contact
- hello
- presentations
- resources
- development
- api-docs
- bare-metal
- local-deployment
- sdk-integration
- getting-started
- about
- bare-metal
- cli
- commands
- policy
- secret
- configuration
- local-deployment
- project-status
- quickstart
- operations
- backup
- build
- multi-tenancy
- production
- recovery
- release
- recipes
- backup-and-restore
- bootstrapping-spike
- break-the-glass-recovery
- choosing-a-backend-store
- deploying-spike
- encryption-as-a-service
- go-sdk-integration
- granting-a-workload-access
- production-hardening
- root-key-keepers-recovery
- storing-and-reading-secrets
- troubleshooting
- upgrading-spike
- writing-access-policies
- tracking
- changelog
- snapshots
- usage
- cli
- commands
- cipher
- operator
- policy
- secret
- configuration
- examples
- federation
- policies
- makefiles
- specs
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
54 | 96 | | |
55 | 97 | | |
56 | 98 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
25 | 65 | | |
26 | 66 | | |
27 | 67 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
| 43 | + | |
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
| 52 | + | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
177 | 177 | | |
178 | 178 | | |
179 | 179 | | |
180 | | - | |
181 | | - | |
182 | | - | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
183 | 205 | | |
184 | 206 | | |
185 | 207 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
50 | | - | |
| 49 | + | |
| 50 | + | |
51 | 51 | | |
52 | 52 | | |
53 | 53 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
45 | 45 | | |
46 | 46 | | |
47 | 47 | | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
48 | 58 | | |
49 | 59 | | |
50 | 60 | | |
| |||
67 | 77 | | |
68 | 78 | | |
69 | 79 | | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
70 | 95 | | |
71 | 96 | | |
72 | 97 | | |
| |||
90 | 115 | | |
91 | 116 | | |
92 | 117 | | |
93 | | - | |
94 | | - | |
95 | | - | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
96 | 122 | | |
97 | 123 | | |
98 | 124 | | |
| 125 | + | |
| 126 | + | |
99 | 127 | | |
100 | 128 | | |
101 | 129 | | |
| |||
133 | 161 | | |
134 | 162 | | |
135 | 163 | | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
136 | 170 | | |
137 | 171 | | |
138 | 172 | | |
| |||
0 commit comments