Merge remote-tracking branch 'origin/main' into sec-deps-dos-bumps
# Conflicts: # internal/provision/testdata/plan14-root-reads-chain.tsv
6 files changed,
+98
−2
docs/superpowers/notes/census-proposal-sec-deps-dos-bumps.md+1 −1docs/superpowers/notes/census-proposal-sec-host-imdsv2-module.md+28 −0infra/modules/region-host/main.tf+13 −0infra/modules/region-host/tests/instance_metadata.tftest.hcl+49 −0internal/provision/testdata/plan14-root-reads-chain.tsv+2 −1internal/provision/testdata/plan14-root-reads-sec-host-imdsv2-module.tsv+5 −0
CI passed — run details
CI log
=== gate ===
.amadan/test-gate.sh
go: downloading golang.org/x/net v0.60.0
go: downloading golang.org/x/crypto v0.57.0
go: downloading github.com/pion/stun/v3 v3.1.5
go: downloading golang.org/x/sys v0.48.0
go: downloading github.com/pion/transport/v4 v4.0.2
go: downloading golang.org/x/sync v0.23.0
go: downloading github.com/pion/dtls/v3 v3.1.4
go: downloading golang.org/x/text v0.42.0
go: downloading github.com/pion/dtls/v3 v3.1.4
go: downloading golang.org/x/text v0.42.0
=== launchctx (0 s)
ok amadan.net/carlos/platform.git/launchctx 0.011s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
=== vet (24 s)
go: downloading golang.org/x/tools v0.49.0
go: downloading github.com/pion/dtls/v3 v3.1.4
go: downloading golang.org/x/text v0.42.0
go: downloading golang.org/x/mod v0.41.0
=== gofmt (0 s)
gofmt -l .: clean
=== rest (179 s)
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.779s
ok github.com/carlosframework/platform/cmd/moveprobe 12.132s
ok github.com/carlosframework/platform/cmd/zddprobe 0.813s
ok github.com/carlosframework/platform/internal/activator 58.091s
ok github.com/carlosframework/platform/internal/agentsock 0.031s
ok github.com/carlosframework/platform/internal/alerting 0.008s
ok github.com/carlosframework/platform/internal/analytics 0.041s
ok github.com/carlosframework/platform/internal/appconfig 2.727s
ok github.com/carlosframework/platform/internal/apperr 0.141s
ok github.com/carlosframework/platform/internal/applog 0.304s
ok github.com/carlosframework/platform/internal/awsinv 0.009s
ok github.com/carlosframework/platform/internal/boxchoice 0.007s
ok github.com/carlosframework/platform/internal/boxid 1.101s
? github.com/carlosframework/platform/internal/boxid/boxidtest [no test files]
? github.com/carlosframework/platform/internal/boxid/internal/signtest [no test files]
ok github.com/carlosframework/platform/internal/boxvolumes 0.015s
ok github.com/carlosframework/platform/internal/caps 0.016s
ok github.com/carlosframework/platform/internal/certwarm 0.005s
ok github.com/carlosframework/platform/internal/cgroup 0.840s
ok github.com/carlosframework/platform/internal/changelog 0.650s
ok github.com/carlosframework/platform/internal/claimactivation 1.264s
ok github.com/carlosframework/platform/internal/clamd 0.061s
? github.com/carlosframework/platform/internal/cliflag [no test files]
? github.com/carlosframework/platform/internal/controlname [no test files]
? github.com/carlosframework/platform/internal/controlsock [no test files]
ok github.com/carlosframework/platform/internal/dbdoor 7.822s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.011s
ok github.com/carlosframework/platform/internal/dbquery 0.010s
ok github.com/carlosframework/platform/internal/dbreads 2.097s
? github.com/carlosframework/platform/internal/dbreads/dbreadstest [no test files]
ok github.com/carlosframework/platform/internal/dbverify 0.005s
ok github.com/carlosframework/platform/internal/dnsrec 0.005s
ok github.com/carlosframework/platform/internal/docsite 0.019s
ok github.com/carlosframework/platform/internal/domains 2.995s
ok github.com/carlosframework/platform/internal/doorkey 0.009s
ok github.com/carlosframework/platform/internal/economics 0.009s
ok github.com/carlosframework/platform/internal/edge 46.066s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.018s
ok github.com/carlosframework/platform/internal/fleetapi 0.187s
ok github.com/carlosframework/platform/internal/gate 1.680s
ok github.com/carlosframework/platform/internal/genselect 0.028s
ok github.com/carlosframework/platform/internal/geo 0.028s
ok github.com/carlosframework/platform/internal/geoip 0.072s
ok github.com/carlosframework/platform/internal/historyreadback 0.217s
ok github.com/carlosframework/platform/internal/host 142.886s
ok github.com/carlosframework/platform/internal/hostactors 6.187s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.012s
ok github.com/carlosframework/platform/internal/hostbox 3.007s
ok github.com/carlosframework/platform/internal/hostclaim 0.763s
ok github.com/carlosframework/platform/internal/hostenv 0.012s
ok github.com/carlosframework/platform/internal/hostevidence 0.012s
ok github.com/carlosframework/platform/internal/hostexec 5.366s
ok github.com/carlosframework/platform/internal/hostfence 0.043s
ok github.com/carlosframework/platform/internal/hostfiles 10.328s
ok github.com/carlosframework/platform/internal/hostfloor 0.027s
ok github.com/carlosframework/platform/internal/hostguard 1.091s
ok github.com/carlosframework/platform/internal/hostops 1.985s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.012s
ok github.com/carlosframework/platform/internal/hostquarantine 0.012s
ok github.com/carlosframework/platform/internal/hostrelocate 0.679s
ok github.com/carlosframework/platform/internal/hostresolve 0.203s
ok github.com/carlosframework/platform/internal/hostwrite 0.011s
ok github.com/carlosframework/platform/internal/infraview 0.015s
ok github.com/carlosframework/platform/internal/instancectl 5.270s
ok github.com/carlosframework/platform/internal/instanceexec 2.816s
ok github.com/carlosframework/platform/internal/instancefs 0.012s
ok github.com/carlosframework/platform/internal/instancekey 0.016s
ok github.com/carlosframework/platform/internal/instanceupdates 0.024s
ok github.com/carlosframework/platform/internal/layout 1.761s
ok github.com/carlosframework/platform/internal/lbhealth 0.005s
ok github.com/carlosframework/platform/internal/lease 10.218s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.605s
ok github.com/carlosframework/platform/internal/ledger 0.020s
ok github.com/carlosframework/platform/internal/mail 0.251s
ok github.com/carlosframework/platform/internal/maintenance 0.125s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.589s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.132s
ok github.com/carlosframework/platform/internal/metrics 0.005s
ok github.com/carlosframework/platform/internal/moves 22.529s
ok github.com/carlosframework/platform/internal/moves/archive 0.994s
ok github.com/carlosframework/platform/internal/objstore 0.350s
ok github.com/carlosframework/platform/internal/ops 0.209s
ok github.com/carlosframework/platform/internal/park 0.250s
ok github.com/carlosframework/platform/internal/plans 0.007s
ok github.com/carlosframework/platform/internal/privatefile 0.012s
ok github.com/carlosframework/platform/internal/provision 30.425s
ok github.com/carlosframework/platform/internal/publicrelease 0.010s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 5.623s
ok github.com/carlosframework/platform/internal/relay 7.232s
ok github.com/carlosframework/platform/internal/release 26.144s
ok github.com/carlosframework/platform/internal/rollout 3.823s
ok github.com/carlosframework/platform/internal/rolloutwords 0.006s
ok github.com/carlosframework/platform/internal/rootaws 0.009s
ok github.com/carlosframework/platform/internal/rootparticipation 0.058s
ok github.com/carlosframework/platform/internal/rootstate 0.028s
ok github.com/carlosframework/platform/internal/runs 0.608s
ok github.com/carlosframework/platform/internal/s3compat 0.006s
ok github.com/carlosframework/platform/internal/safefile 0.004s
ok github.com/carlosframework/platform/internal/schedule 2.692s
ok github.com/carlosframework/platform/internal/seeds 0.011s
ok github.com/carlosframework/platform/internal/sim/engines 2.619s
ok github.com/carlosframework/platform/internal/sim/hostlife 11.148s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.044s
ok github.com/carlosframework/platform/internal/status 0.082s
ok github.com/carlosframework/platform/internal/steering 0.006s
ok github.com/carlosframework/platform/internal/stopevidence 0.316s
ok github.com/carlosframework/platform/internal/svcrole 0.006s
ok github.com/carlosframework/platform/internal/telemetry 0.007s
ok github.com/carlosframework/platform/internal/termfence 0.004s
ok github.com/carlosframework/platform/internal/tunnelclient 0.006s
ok github.com/carlosframework/platform/internal/unixdial 0.002s
ok github.com/carlosframework/platform/internal/updatewords 0.005s
ok github.com/carlosframework/platform/internal/usage 0.005s
ok github.com/carlosframework/platform/internal/version 0.002s
ok github.com/carlosframework/platform/internal/vet 1.720s
=== internal_console@0 (81 s)
ok github.com/carlosframework/platform/internal/console 80.279s
=== internal_console@1 (43 s)
ok github.com/carlosframework/platform/internal/console 42.129s
=== internal_console@2 (41 s)
ok github.com/carlosframework/platform/internal/console 39.859s
=== internal_console@3 (40 s)
ok github.com/carlosframework/platform/internal/console 39.176s
=== internal_console@4 (42 s)
ok github.com/carlosframework/platform/internal/console 40.771s
=== internal_console@5 (41 s)
ok github.com/carlosframework/platform/internal/console 40.005s
=== internal_console@6 (37 s)
ok github.com/carlosframework/platform/internal/console 36.099s
=== internal_console@7 (46 s)
ok github.com/carlosframework/platform/internal/console 44.578s
=== root@0 (110 s)
ok github.com/carlosframework/platform 108.666s
=== root@1 (84 s)
ok github.com/carlosframework/platform 83.188s
=== root@2 (92 s)
ok github.com/carlosframework/platform 90.591s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
linux/arm64 carlos binary: 50659490 bytes (ceiling 52000000)
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
minio: downloading https://github.com/minio/minio/releases/download/RELEASE.2025-09-07T16-13-09Z/minio.linux-arm64.RELEASE.2025-09-07T16-13-09Z
minio: downloaded, digest verified
mc: downloading https://github.com/minio/mc/releases/download/RELEASE.2025-08-13T08-35-41Z/mc.linux-arm64.RELEASE.2025-08-13T08-35-41Z
mc: downloaded, digest verified
minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
buckets and scoped user ready
=== RUN TestDeliveredContractMinio
=== RUN TestDeliveredContractMinio/put
=== RUN TestDeliveredContractMinio/get_round-trips_the_body
=== RUN TestDeliveredContractMinio/list_shows_the_key
=== RUN TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN TestDeliveredContractMinio/delete_removes_it
=== RUN TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
--- PASS: TestDeliveredContractMinio/put (0.00s)
--- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
--- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
--- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
--- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok github.com/carlosframework/platform/internal/objstore 0.023s
=== RUN TestT4StorageProbeMinio
2026/10/24 19:27:09 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E18DCADEA647D8, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok github.com/carlosframework/platform/internal/host 0.024s
=== RUN TestS3StoreMinioContract
=== RUN TestS3StoreMinioContract/conditional_get_and_etag_listing
=== RUN TestS3StoreMinioContract/bump_through_every_mutation_path
--- PASS: TestS3StoreMinioContract (0.03s)
--- PASS: TestS3StoreMinioContract/conditional_get_and_etag_listing (0.01s)
--- PASS: TestS3StoreMinioContract/bump_through_every_mutation_path (0.02s)
PASS
ok github.com/carlosframework/platform/internal/release 0.031s
Bucket created successfully `local/dbf-deploy`.
Bucket created successfully `local/dbf-data-ie`.
Bucket created successfully `local/dbf-data-uk`.
local/dbf-deploy versioning is enabled
Created policy `dbf-console` successfully.
Created policy `dbf-ukbox` successfully.
Added user `dbfconsole` successfully.
Added user `dbfukbox` successfully.
Attached Policies: [dbf-console]
To User: dbfconsole
Attached Policies: [dbf-ukbox]
To User: dbfukbox
=== RUN TestDBForwardMinio
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/24 19:27:11 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000002
2026/10/24 19:27:11 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000002 maxTXID=0000000000000002 size=370
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000002
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000003
2026/10/24 19:27:11 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000003 maxTXID=0000000000000003 size=454
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000003 txid.db=0000000000000003
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/24 19:27:11 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/24 19:27:11 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/24 19:27:11 console: CARLOS_SECRETS_PUBKEY is unset, so no region outside the home can be chosen automatically
2026/10/24 19:27:11 console: could not notify member@example.com of a CLI token issue: keymail: lookup member@example.com: keymail: GET /api/federation/lookup?addr=member%40example.com&from=console%40127.0.0.1%3A42369: could not determine target mailbox
agent.go:135: dbreads: dbr_cryfba2e4goij2hqb5s5j7d3oy: planned 3 files (1544 bytes) and restored to 3 in 10ms
agent.go:135: dbreads: dbr_cryfba2e4goij2hqb5s5j7d3oy: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/24 19:27:12 console: db read dbr_cryfba2e4goij2hqb5s5j7d3oy: relayed 1 chunks (102 bytes) in 1.004s, ended done
agent.go:135: dbreads: dbr_yixcvsrseagmny7llci2lk66qa: planned 1 files (720 bytes) and restored to 1 in 8ms
agent.go:135: dbreads: dbr_yixcvsrseagmny7llci2lk66qa: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/24 19:27:13 console: db read dbr_yixcvsrseagmny7llci2lk66qa: relayed 1 chunks (102 bytes) in 1.004s, ended done
agent.go:135: dbreads: dbr_tjfnghktcvjgnvutrn7t3a22ma: planned 3 files (1544 bytes) and held through 3 in 9ms
agent.go:135: dbreads: dbr_tjfnghktcvjgnvutrn7t3a22ma: output 1544 bytes in 1 confirmed chunks in 1ms
2026/10/24 19:27:14 console: db read dbr_tjfnghktcvjgnvutrn7t3a22ma: relayed 1 chunks (1641 bytes) in 1.004s, ended done
=== RUN TestDBForwardMinio/by_disconnect
=== NAME TestDBForwardMinio
agent.go:135: dbreads: dbr_cajfkotdzhcv346pxvhksz6vqi: planned 3 files (1544 bytes) and restored to 3 in 9ms
2026/10/24 19:27:14 console: db read dbr_cajfkotdzhcv346pxvhksz6vqi: relayed 0 chunks (0 bytes) in 32ms, ended client gone
agent.go:135: dbreads: dbr_cajfkotdzhcv346pxvhksz6vqi: output 5 bytes in 1 confirmed chunks in 18ms
=== RUN TestDBForwardMinio/by_timeout
=== NAME TestDBForwardMinio
agent.go:135: dbreads: dbr_bvif6nx7iy4tuwidvuixtlys6u: planned 3 files (1544 bytes) and restored to 3 in 9ms
2026/10/24 19:27:34 console: db read dbr_bvif6nx7iy4tuwidvuixtlys6u: relayed 0 chunks (0 bytes) in 19.214s, ended no-result
agent.go:135: dbreads: dbr_bvif6nx7iy4tuwidvuixtlys6u: output 5 bytes in 1 confirmed chunks in 19.189s
--- PASS: TestDBForwardMinio (22.57s)
--- PASS: TestDBForwardMinio/by_disconnect (0.16s)
--- PASS: TestDBForwardMinio/by_timeout (19.32s)
PASS
ok github.com/carlosframework/platform/internal/console 22.589s
minio contract: PASS
diff --git a/docs/superpowers/notes/census-proposal-sec-deps-dos-bumps.md b/docs/superpowers/notes/census-proposal-sec-deps-dos-bumps.md| index 09e71ba31..97d2e1f04 100644 |
| --- a/docs/superpowers/notes/census-proposal-sec-deps-dos-bumps.md |
| +++ b/docs/superpowers/notes/census-proposal-sec-deps-dos-bumps.md |
| @@ -4,7 +4,7 @@ Ruling `census-ruling-sec-deps-dos-bumps`. Every change below keeps the disposit |
| Envelopes re-pinned: `.`. |
| -Seal: `09e20ea4bbc534710334e632e903878656dabfb5817d4d96c6e7c56508172148` → `09e20ea4bbc534710334e632e903878656dabfb5817d4d96c6e7c56508172148`. |
| +Seal: `945934f5978ace14dc5a9bae0ed69dfabf29b994504fc843c03d4a633ecd6c6a` → `945934f5978ace14dc5a9bae0ed69dfabf29b994504fc843c03d4a633ecd6c6a` (unchanged; loaded after sec-host-imdsv2-module, re-chained 2026-10-24 when that merged as ef156d3). |
| Overlay: `internal/provision/testdata/plan14-root-reads-sec-deps-dos-bumps.tsv`, appended to `internal/provision/testdata/plan14-root-reads-chain.tsv`. |
diff --git a/docs/superpowers/notes/census-proposal-sec-host-imdsv2-module.md b/docs/superpowers/notes/census-proposal-sec-host-imdsv2-module.md| new file mode 100644 |
| index 000000000..37512514f |
| --- /dev/null |
| +++ b/docs/superpowers/notes/census-proposal-sec-host-imdsv2-module.md |
| @@ -0,0 +1,28 @@ |
| +# Census approval: sec-host-imdsv2-module |
| + |
| +Ruling `census-ruling-sec-host-imdsv2-module`. Every change below keeps the disposition it already has, so it needs an approval, not a decision. |
| + |
| +| unit | change | read sites | what changed | |
| +|---|---|---|---| |
| +| `infra/modules/region-host/main.tf` `external` | body | unchanged (1) | aws_instance.host gains metadata_options (IMDSv2 required, hop limit 1, endpoint enabled), matching scanner-host; tofu configuration only, run on an operator's machine; no read, file or record write is added; applies in place on a running instance with no restart | |
| + |
| +Envelopes re-pinned: `infra/modules/region-host`. |
| + |
| +Seal: `09e20ea4bbc534710334e632e903878656dabfb5817d4d96c6e7c56508172148` → `945934f5978ace14dc5a9bae0ed69dfabf29b994504fc843c03d4a633ecd6c6a`. |
| + |
| +Overlay: `internal/provision/testdata/plan14-root-reads-sec-host-imdsv2-module.tsv`, appended to `internal/provision/testdata/plan14-root-reads-chain.tsv`. |
| + |
| +## Branch context |
| + |
| +The branch `sec-host-imdsv2-module` adds a `metadata_options` block to |
| +`aws_instance.host` in `infra/modules/region-host/main.tf` (IMDSv2 required, |
| +hop limit 1, endpoint enabled), matching scanner-host, and a plan-time tofu |
| +test under `infra/modules/region-host/tests/`. The record-write census does |
| +not change: no record write is added or moved. |
| + |
| +The new `tests/instance_metadata.tftest.hcl` is outside the census: the scan's |
| +extension list excludes `.tftest.hcl`, and envelopes group by immediate |
| +directory, so the module hash covers only the `.tf` files. |
| + |
| +Executing identity: tofu on an operator's machine with the operator's AWS |
| +credentials; no box unit runs the file and no binary embeds it. |
diff --git a/infra/modules/region-host/main.tf b/infra/modules/region-host/main.tf| index b35ecc196..11fca1987 100644 |
| --- a/infra/modules/region-host/main.tf |
| +++ b/infra/modules/region-host/main.tf |
| @@ -490,6 +490,19 @@ resource "aws_instance" "host" { |
| iam_instance_profile = aws_iam_instance_profile.host.name |
| user_data = var.user_data |
| user_data_replace_on_change = false |
| + # IMDSv2 only, one hop. With the block absent EC2 leaves IMDSv1 on, and a |
| + # plain GET from any request-forgery bug in a tenant app reads this |
| + # role's credentials; v2 needs a PUT with a header first, which those |
| + # bugs rarely give an attacker. Hop limit 1 keeps the token from leaving |
| + # the box. Changing these on a running instance is in place, no restart. |
| + # The flagship boxes were switched by hand on 2026-10-23; this keeps a |
| + # replaced box from coming back on v1. The scanner host has done the same |
| + # since it was written. |
| + metadata_options { |
| + http_endpoint = "enabled" |
| + http_tokens = "required" |
| + http_put_response_hop_limit = 1 |
| + } |
| root_block_device { |
| volume_size = var.root_volume_size |
| volume_type = "gp3" |
diff --git a/infra/modules/region-host/tests/instance_metadata.tftest.hcl b/infra/modules/region-host/tests/instance_metadata.tftest.hcl| new file mode 100644 |
| index 000000000..a2c60aa2e |
| --- /dev/null |
| +++ b/infra/modules/region-host/tests/instance_metadata.tftest.hcl |
| @@ -0,0 +1,49 @@ |
| +# Plan-time tests for the host instance's metadata service settings. |
| +# mock_provider means no AWS account and no credentials. |
| +mock_provider "aws" {} |
| + |
| +override_data { |
| + target = data.aws_vpcs.default |
| + values = { ids = ["vpc-0aaaaaaaaaaaaaaaa"] } |
| +} |
| + |
| +override_data { |
| + target = data.aws_caller_identity.current |
| + values = { account_id = "123456789012" } |
| +} |
| + |
| +# The termination queue's ARN feeds an EventBridge target, which the provider |
| +# validates as an ARN; the mock's random string is not one. |
| +override_resource { |
| + target = aws_sqs_queue.terminations |
| + values = { arn = "arn:aws:sqs:eu-west-1:123456789012:carlos-test-host-terminations" } |
| +} |
| + |
| +variables { |
| + name = "carlos-test-ie" |
| + sg_description = "carlos test host" |
| + iam_name = "carlos-test-host" |
| + instance_type = "t4g.small" |
| + root_volume_size = 20 |
| + user_data = "#!/bin/sh\n" |
| + deployment_bucket_arn = "arn:aws:s3:::carlos-test-platform" |
| + data_bucket_arn = "arn:aws:s3:::carlos-test-ie" |
| + ssm_parameter_arn = "arn:aws:ssm:eu-west-1:123456789012:parameter/carlos/*" |
| +} |
| + |
| + |
| +run "imdsv2_only" { |
| + command = plan |
| + assert { |
| + condition = aws_instance.host.metadata_options[0].http_tokens == "required" |
| + error_message = "the host requires IMDSv2 tokens" |
| + } |
| + assert { |
| + condition = aws_instance.host.metadata_options[0].http_put_response_hop_limit == 1 |
| + error_message = "the IMDS token must not leave the box (hop limit 1)" |
| + } |
| + assert { |
| + condition = aws_instance.host.metadata_options[0].http_endpoint == "enabled" |
| + error_message = "the endpoint stays on: the box role is how the host reaches AWS" |
| + } |
| +} |
diff --git a/internal/provision/testdata/plan14-root-reads-chain.tsv b/internal/provision/testdata/plan14-root-reads-chain.tsv| index e0f1b1240..a67ca45fd 100644 |
| --- a/internal/provision/testdata/plan14-root-reads-chain.tsv |
| +++ b/internal/provision/testdata/plan14-root-reads-chain.tsv |
| @@ -1,4 +1,5 @@ |
| # Census chain manifest: overlays loaded after rootReadChain's own, in order. |
| # One per line: <overlay file name under testdata>\t<the seal it leaves>. |
| # make census-propose appends here; nothing else edits this file. |
| -plan14-root-reads-sec-deps-dos-bumps.tsv 09e20ea4bbc534710334e632e903878656dabfb5817d4d96c6e7c56508172148 |
| +plan14-root-reads-sec-host-imdsv2-module.tsv 945934f5978ace14dc5a9bae0ed69dfabf29b994504fc843c03d4a633ecd6c6a |
| +plan14-root-reads-sec-deps-dos-bumps.tsv 945934f5978ace14dc5a9bae0ed69dfabf29b994504fc843c03d4a633ecd6c6a |
diff --git a/internal/provision/testdata/plan14-root-reads-sec-host-imdsv2-module.tsv b/internal/provision/testdata/plan14-root-reads-sec-host-imdsv2-module.tsv| new file mode 100644 |
| index 000000000..c4ac824f6 |
| --- /dev/null |
| +++ b/internal/provision/testdata/plan14-root-reads-sec-host-imdsv2-module.tsv |
| @@ -0,0 +1,5 @@ |
| +# Census overlay sec-host-imdsv2-module, written by census-propose (#369). census-ruling-sec-host-imdsv2-module, approved by the census owner before the merge; the approval card is docs/superpowers/notes/census-proposal-sec-host-imdsv2-module.md. |
| +# 1 body, 0 sites, 1 envelope: each changed unit re-frozen at its existing disposition with its claim appended. |
| +@legacy bf41de79166910448a12a9ba5e5568bc7365193b909d5ebbe942facce8ecb95c infra/modules/region-host/main.tf external legacy accepted-legacy accepted-legacy;rev3=census-ruling-console-invite-delivery;basis=tofu on an operator's machine with the operator's AWS credentials (no box unit; no binary embeds the file): main's module with one optional aws_iam_role_policy, host_console_mail, count 0 unless console_mail_from is set; it grants the host role ses:SendEmail on the one sending identity, the carlos-bab configuration set and its tenants, conditioned on ses:FromAddress equal to console_mail_from; no read is added and nothing on a box reads the file;rev3=census-ruling-sec-host-imdsv2-module;basis=aws_instance.host gains metadata_options (IMDSv2 required, hop limit 1, endpoint enabled), matching scanner-host; tofu configuration only, run on an operator's machine; no read, file or record write is added; applies in place on a running instance with no restart file:external@0 8ec89e75ca0a0d2ddde74bffe226adb5a5935249fd41590bcce1623c5201ab47 |
| +infra/modules/region-host/main.tf external legacy accepted-legacy accepted-legacy;rev3=census-ruling-console-invite-delivery;basis=tofu on an operator's machine with the operator's AWS credentials (no box unit; no binary embeds the file): main's module with one optional aws_iam_role_policy, host_console_mail, count 0 unless console_mail_from is set; it grants the host role ses:SendEmail on the one sending identity, the carlos-bab configuration set and its tenants, conditioned on ses:FromAddress equal to console_mail_from; no read is added and nothing on a box reads the file;rev3=census-ruling-sec-host-imdsv2-module;basis=aws_instance.host gains metadata_options (IMDSv2 required, hop limit 1, endpoint enabled), matching scanner-host; tofu configuration only, run on an operator's machine; no read, file or record write is added; applies in place on a running instance with no restart file:external@0 8ec89e75ca0a0d2ddde74bffe226adb5a5935249fd41590bcce1623c5201ab47 |
| +@coverage infra/modules/region-host 5f1b1bbc02603a54e136ff004e2495bef2b0f22054e058b5930a539749b1b558 |