Skip to content

Commit 77a7715

Browse files
fix: verify connected signatures with anchored public key snapshots
1 parent 6924dc5 commit 77a7715

10 files changed

Lines changed: 85 additions & 24 deletions

File tree

‎SHA256SUMS‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ eb12ff7678ce4733bedd686ddd9064ca8b89cd1c0d3f5ab84726caf7b0268158 jev_integratio
314314
e58055c1074ee97c45a23e0e8716f436deafcdec848f0bcac29d851faac4c4d8 jev_integration_evaluator/data/threshold-spec.schema.json
315315
aa187d402c316d3e1d92dad6e9148a08f45acc3d9609f2397cf493ecd1b4ddf9 jev_integration_evaluator/data/trace.schema.json
316316
62ae35743633fa26d0ee1e74c79c6cb55d4ee1a59af55ed3790190f0ba224baa jev_integration_evaluator/data/typescript_ast.cjs
317-
e27b8ee9f42d60adb9a7d77ef7625621905df204c71ac53ee03eeb8622eedca1 jev_integration_evaluator/data/use-case-template-matrix-v1.json
317+
c18694f8b315776407f8defd16ee2b7fa8cbac47f50c142b59f1c560916895a0 jev_integration_evaluator/data/use-case-template-matrix-v1.json
318318
6a8fa2ff484e3272cc28768167171fec368ab207c86e546875e41a5e84da4b6e jev_integration_evaluator/data/use-case-template-matrix-v1.schema.json
319319
7b78327dafc6e5f189f5316e7abfa9a81952ea7eb68baa55a9728784a4557ecf jev_integration_evaluator/data/windows-connected-delivery-plan-v1.schema.json
320320
08f9cf041780de811e9d84e2ff817d3d72b439a10e098cf9dbaedd6d03c77d5e jev_integration_evaluator/data/windows-connected-delivery-scope-v1.schema.json
@@ -347,7 +347,7 @@ a39ffb4d794b9c0b7bf8c507d9361e684a4e622e6373c8f9bb92012f423438b6 jev_integratio
347347
02739fd54e223bed2646e46938ecb438b596c4dd269d2920841f87ebb4031a8d jev_integration_evaluator/integrations/adaptation_runtime.py
348348
664bce2d74875579f48348ba817a9ecb2cad34f59e2ded1596f61f592a5a3193 jev_integration_evaluator/integrations/adaptation_shapes.py
349349
80ff31f3f74bc7d2ac8d374aeba5e2d064649d9db3324455b2ebff5b48dca79e jev_integration_evaluator/integrations/composite.py
350-
e3dc9f718a0364a6a55bcf440a44e551f7e4a478a13546baa2c49b17e8b9d4f5 jev_integration_evaluator/integrations/composite_console.py
350+
b44a504c274df612ecd5cd06d44dcc1cd9f56dc882a50c3d4257aa70235a4f75 jev_integration_evaluator/integrations/composite_console.py
351351
44f24d63538a0385b0a66b8283e3db96638c68b9e8da29236c58415f4d6bc1af jev_integration_evaluator/integrations/contracts.py
352352
9e64379f4f9586beb539bad8f5f54be6e856ce79ccdb772d73d175d33e5c2219 jev_integration_evaluator/integrations/errors.py
353353
21aa34d26c10bdc024725d5f60c67d61a34986b9f824371339eea3a9d8a0e5b4 jev_integration_evaluator/integrations/host.py
@@ -433,7 +433,7 @@ cbbd2a92eeb685c0e859746fd8ebc40fd8bfaa9fb2901d6cf79a31f183ed4517 references/arc
433433
349fe248157cd4882e6621939bfc28dc9edecb54e3397d0705dacc5eeea48db4 references/composite-transactions-v1.md
434434
fdd82ced94ade58abbff02589b21a318670711dabb276b544e12726b70554614 references/confidence-and-calibration.md
435435
9fb76e904994c7f8c9fa96e45c37d4c8b4fc67ae9e5996c98ea8e140e850724f references/connected-composite-binding-v1.md
436-
8b06c7b76ec0a4ea5c43b2c2da4a88cc9a816493d505651ff050ed1baae51db1 references/connected-delivery-v1.md
436+
d2f2e07bc361e731f639978ec0259ce9652db93f01ff10551f9778b4824b9870 references/connected-delivery-v1.md
437437
6d0d3a9f92c643123cf3c577a13a94bffe9a011515688db40ddb9f5067a835b5 references/connected-installed-binding-v1.md
438438
313892a92e30412b83466577dcc05e4437e26fd53e735787de3e3c8dcedcefad references/data-contracts.md
439439
20c354b1b84ad6e079a49ce8098f261411cd469ce7176afa0297762a1d5b2b09 references/executable-implementation-prompt.md
@@ -734,7 +734,7 @@ e6c21c61a0652ea348ca1fa72c3e2d2b0df4c29f2d2b31aa101cb2e7b5473a5d tests/independ
734734
0f1663c62c614bb5053fbcc0175760889391326bd56f808f02ecd8babea0ef17 tests/independent_hosts/registered_alpha_connected/pyproject.toml
735735
f3fa3e10a9c233224f399aece5d60bfe4ce2f6aec96043f97b7633c8d44e38a1 tests/independent_hosts/registered_alpha_connected/qualification.py
736736
ee3d08a82f10edefbf1cc563dbffecf18772db62fbd82d4bee5ad8a9425c371a tests/independent_hosts/registered_alpha_connected/src/registered_alpha/__init__.py
737-
eb4b288b46d1f6683b601d2e827a75934afa9b7b3a39919ea22ada765ea2f50e tests/independent_hosts/registered_alpha_connected/src/registered_alpha/connected_authority.py
737+
4fb1808ec5690dd70d742a4302c9466a46bc0b39edf892477e6bb20e2a53f18b tests/independent_hosts/registered_alpha_connected/src/registered_alpha/connected_authority.py
738738
19f152bfa720de7ab3baa9c6db24c000f9058904bec741a3a5f19fc8dd08f7c7 tests/independent_hosts/registered_alpha_connected/src/registered_alpha/console.py
739739
097d23c5ce68b53c59038fb8ac195744d8ab9adafa2bdf1ce1939ed91a67d4e5 tests/independent_hosts/registered_alpha_connected/src/registered_alpha/host.py
740740
21ac598980a951f6b4e0f098bc1756ccfffbbe7e8c12d36a228c8381ca0c013b tests/independent_hosts/registered_alpha_connected/src/registered_alpha/requirements.lock
@@ -760,19 +760,19 @@ ec04a01d497f35f10d51607b636023bc2b1f622e87bc6b7fe99de300adc02d32 tests/independ
760760
0c1f169e847504851b588cac189b805f24b317288411ca9699b16cbf41ea0252 tests/independent_hosts/registered_dual/src/registered_dual/runtime.json
761761
db2a51bd2751a1dcfff052104ccec28c369cba6f59d73f2508ee218c5bc0bf87 tests/independent_hosts/registered_dual/src/registered_dual/work_queue.py
762762
79e112487ac189e9096a336389c0098bad12fb142bf99391aa79e23eef01752b tests/independent_hosts/registered_dual_connected/README.md
763-
37111f13eb3afd1887b0c9b8925fb9b903af7b0de67338e9eea6e893aab250a4 tests/independent_hosts/registered_dual_connected/installed_journey.py
763+
eb972e1f25f67c5adf0d824166a1723a49ab138b50952ab1312e0996d0270cad tests/independent_hosts/registered_dual_connected/installed_journey.py
764764
23570482720c6a32ac0480b678458d2ec96b6419f879b5304cca91696a52c77e tests/independent_hosts/registered_dual_connected/oracle-v1.json
765765
6bae5f8680ae5b2cf054431e177ce22a94c5e13770187497c0df7044db7e574f tests/independent_hosts/registered_dual_connected/pyproject.toml
766766
f9549b9f69acb69d8c7f72fb323131d3218051722e1ee706e406795b86a69f55 tests/independent_hosts/registered_dual_connected/qualification.py
767-
3a3d7375c6cdfc704abe9b2540aba86b688f204f6c3aac4def0d8c266ff41e93 tests/independent_hosts/registered_dual_connected/review-v1.json
767+
6c601061db97483454c86dcadba98c18315fab6f54b7b80a354a70ab6f711980 tests/independent_hosts/registered_dual_connected/review-v1.json
768768
ee3d08a82f10edefbf1cc563dbffecf18772db62fbd82d4bee5ad8a9425c371a tests/independent_hosts/registered_dual_connected/src/registered_dual/__init__.py
769769
ec04a01d497f35f10d51607b636023bc2b1f622e87bc6b7fe99de300adc02d32 tests/independent_hosts/registered_dual_connected/src/registered_dual/alpha.py
770-
43331e54755ac9530c3a233045420268d090f50e274520162f12bb672f029854 tests/independent_hosts/registered_dual_connected/src/registered_dual/connected_authority.py
770+
406cec77bbe986efbada92d1f7385042b43714f2f9fcc1dab88015905be67a68 tests/independent_hosts/registered_dual_connected/src/registered_dual/connected_authority.py
771771
bf3516e197d2ca6cc90514edd663125d0593003c274185d60b0f3e94e47c1dd9 tests/independent_hosts/registered_dual_connected/src/registered_dual/console.py
772772
21ac598980a951f6b4e0f098bc1756ccfffbbe7e8c12d36a228c8381ca0c013b tests/independent_hosts/registered_dual_connected/src/registered_dual/requirements.lock
773773
0c1f169e847504851b588cac189b805f24b317288411ca9699b16cbf41ea0252 tests/independent_hosts/registered_dual_connected/src/registered_dual/runtime.json
774774
db2a51bd2751a1dcfff052104ccec28c369cba6f59d73f2508ee218c5bc0bf87 tests/independent_hosts/registered_dual_connected/src/registered_dual/work_queue.py
775-
f07201aafbda0af0b560cba6ae7fd873a6a2bef6101333bfde77c9b88f52e1af tests/independent_hosts/retrieval_connected/connected_authority.py
775+
aeec52d48062081b56fc632c23433737c8b5a490089b1095520e4a9074d0805e tests/independent_hosts/retrieval_connected/connected_authority.py
776776
6a542d2d11f307325a14f48eaa03fe2a9cb0c6b94dae326bbdf73e132586260e tests/independent_hosts/work_queue/README.md
777777
8b2233fa32fefe9418faa8ba9e1c493b0e59aea7313ef0a56b63a26d990d2e3c tests/independent_hosts/work_queue/installed_journey.py
778778
e38588c30eb9edcc34403b895c89f66303837583f46bd315c62cca0f425ec3ba tests/independent_hosts/work_queue/oracle-v1.json
@@ -830,7 +830,7 @@ f15e9b55163998541e8d762c36f383cba0395bf818d45871da19c26856e1c8e0 tests/test_cod
830830
4845bc21ff445511473bcd900c600f9e747b2a5ab885feb08bf5aaab341c265c tests/test_composite_transaction.py
831831
b93acf12f8ac02c948c571145b116e22c4e6d00cb8153e9fef944b710ae3939f tests/test_connected_composite_binding.py
832832
479d9941524bba37648624ce0f7e8b68ee5578c7a691ba3cc30456d090052aa5 tests/test_connected_installed_binding.py
833-
43dad89dbcefc8073fe9b7f0fa97e220e9a7fe358b544fac132bf3e11d698fbf tests/test_connected_loader_public_keys.py
833+
a2c0298d270a217a1b4d3c0960fd7b3150e7272aace6b953f475031e9464806a tests/test_connected_loader_public_keys.py
834834
973e8f663cc4ae78d4a7424405312b6afa64e83b6b65e15c94771db95c7e42ae tests/test_executable_cli.py
835835
edece8e52e538e46845243ab38c84c36f7b0b2b3938134bf025a1ca872ea2dfa tests/test_executable_command_receipts.py
836836
a466a3c93172360d797b6becbc9f376fc28966fd8fefa3205bf0397af94139ef tests/test_executable_failure_receipts.py

‎jev_integration_evaluator/data/use-case-template-matrix-v1.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"root": "tests/independent_hosts/registered_alpha_connected",
1414
"host_sha256": "097d23c5ce68b53c59038fb8ac195744d8ab9adafa2bdf1ce1939ed91a67d4e5",
1515
"console_sha256": "19f152bfa720de7ab3baa9c6db24c000f9058904bec741a3a5f19fc8dd08f7c7",
16-
"loader_sha256": "eb4b288b46d1f6683b601d2e827a75934afa9b7b3a39919ea22ada765ea2f50e",
16+
"loader_sha256": "4fb1808ec5690dd70d742a4302c9466a46bc0b39edf892477e6bb20e2a53f18b",
1717
"project_sha256": "0f1663c62c614bb5053fbcc0175760889391326bd56f808f02ecd8babea0ef17",
1818
"installed_execution": "qualified_offline_connected_shadow_startup_protocol",
1919
"provider": "unobserved",
@@ -30,7 +30,7 @@
3030
"JEV-EDF19BDB65F0": {"file": "src/registered_dual/alpha.py", "sha256": "ec04a01d497f35f10d51607b636023bc2b1f622e87bc6b7fe99de300adc02d32"}
3131
},
3232
"console_sha256": "bf3516e197d2ca6cc90514edd663125d0593003c274185d60b0f3e94e47c1dd9",
33-
"loader_sha256": "43331e54755ac9530c3a233045420268d090f50e274520162f12bb672f029854",
33+
"loader_sha256": "406cec77bbe986efbada92d1f7385042b43714f2f9fcc1dab88015905be67a68",
3434
"project_sha256": "6bae5f8680ae5b2cf054431e177ce22a94c5e13770187497c0df7044db7e574f",
3535
"installed_execution": "qualified_offline_connected_dual_shadow_protocol",
3636
"provider": "unobserved",

‎jev_integration_evaluator/integrations/composite_console.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def render_composite_console(root: Path, selection: dict, specs: dict) -> tuple[
8686
'bf3516e197d2ca6cc90514edd663125d0593003c274185d60b0f3e94e47c1dd9'
8787
and loader_anchored
8888
and hashlib.sha256(loader.read_bytes()).hexdigest() ==
89-
'43331e54755ac9530c3a233045420268d090f50e274520162f12bb672f029854')
89+
'406cec77bbe986efbada92d1f7385042b43714f2f9fcc1dab88015905be67a68')
9090
entry = _function(tree, first['function'], 0)
9191
_function(tree, 'observe_composite_runtime', 3)
9292
statement = entry.body[-1]

‎references/connected-delivery-v1.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ and child launch environment. The private issuer key never enters the child,
5050
wheel, source or committed fixture. The loader checks owner/mode/link count,
5151
verifies signatures with fixed `/usr/bin/openssl` argv and a clean OpenSSL 3
5252
environment, and recomputes the verifier's binary hash/version and runtime
53-
facts before each route. A changed public key or verifier needs a new reviewed
53+
facts before each route. Signature verification rehashes the exact anchored public PEM snapshot and supplies it through an owned temporary-file descriptor; OpenSSL never reopens the public key pathname after validation. Local replacement-race tests use independently signed foreign keys and retain the original failing outcomes. A changed public key or verifier needs a new reviewed
5454
plan and issuer signature. Secret values and raw prompts do not belong in
5555
plans, scopes or reports.
5656

‎tests/independent_hosts/registered_alpha_connected/src/registered_alpha/connected_authority.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,22 @@ def verify_authority(kind: str, exact_digest: str) -> bool:
151151
try:
152152
if (_public_key() != key_file or _openssl_identity() != verifier_identity):
153153
return False
154+
public_pem = key_file.read_bytes()
155+
if hashlib.sha256(public_pem).hexdigest() != os.environ.get('REGISTERED_ALPHA_AUTH_PUBKEY_SHA256'):
156+
return False
154157
raw = base64.b64decode(signature, validate=True)
155-
with tempfile.TemporaryFile(mode='w+b') as signature_file:
158+
with (tempfile.TemporaryFile(mode='w+b') as signature_file,
159+
tempfile.TemporaryFile(mode='w+b') as public_file):
156160
signature_file.write(raw)
157161
signature_file.flush()
162+
public_file.write(public_pem)
163+
public_file.flush()
158164
verification = subprocess.run(
159-
[str(OPENSSL), 'dgst', '-sha256', '-verify', str(key_file),
165+
[str(OPENSSL), 'dgst', '-sha256', '-verify', f'/proc/self/fd/{public_file.fileno()}',
160166
'-signature', f'/proc/self/fd/{signature_file.fileno()}'],
161167
input=(kind + ':' + exact_digest).encode('ascii'),
162168
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
163-
pass_fds=(signature_file.fileno(),), timeout=2,
169+
pass_fds=(signature_file.fileno(), public_file.fileno()), timeout=2,
164170
env=OPENSSL_ENV, check=False)
165171
return verification.returncode == 0
166172
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired):

‎tests/independent_hosts/registered_dual_connected/installed_journey.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
_qualification = importlib.util.module_from_spec(_spec)
3434
_spec.loader.exec_module(_qualification)
3535
ROOT = _qualification.ROOT
36-
FROZEN_REVIEW_SHA256 = '3a3d7375c6cdfc704abe9b2540aba86b688f204f6c3aac4def0d8c266ff41e93'
36+
FROZEN_REVIEW_SHA256 = '6c601061db97483454c86dcadba98c18315fab6f54b7b80a354a70ab6f711980'
3737
FROZEN_ORACLE_SHA256 = '23570482720c6a32ac0480b678458d2ec96b6419f879b5304cca91696a52c77e'
3838

3939

‎tests/independent_hosts/registered_dual_connected/review-v1.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"pyproject.toml": "6bae5f8680ae5b2cf054431e177ce22a94c5e13770187497c0df7044db7e574f",
2020
"src/registered_dual/__init__.py": "ee3d08a82f10edefbf1cc563dbffecf18772db62fbd82d4bee5ad8a9425c371a",
2121
"src/registered_dual/alpha.py": "ec04a01d497f35f10d51607b636023bc2b1f622e87bc6b7fe99de300adc02d32",
22-
"src/registered_dual/connected_authority.py": "43331e54755ac9530c3a233045420268d090f50e274520162f12bb672f029854",
22+
"src/registered_dual/connected_authority.py": "406cec77bbe986efbada92d1f7385042b43714f2f9fcc1dab88015905be67a68",
2323
"src/registered_dual/console.py": "bf3516e197d2ca6cc90514edd663125d0593003c274185d60b0f3e94e47c1dd9",
2424
"src/registered_dual/requirements.lock": "21ac598980a951f6b4e0f098bc1756ccfffbbe7e8c12d36a228c8381ca0c013b",
2525
"src/registered_dual/runtime.json": "0c1f169e847504851b588cac189b805f24b317288411ca9699b16cbf41ea0252",

‎tests/independent_hosts/registered_dual_connected/src/registered_dual/connected_authority.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,22 @@ def verify_authority(kind: str, exact_digest: str) -> bool:
151151
try:
152152
if (_public_key() != key_file or _openssl_identity() != verifier_identity):
153153
return False
154+
public_pem = key_file.read_bytes()
155+
if hashlib.sha256(public_pem).hexdigest() != os.environ.get('REGISTERED_DUAL_AUTH_PUBKEY_SHA256'):
156+
return False
154157
raw = base64.b64decode(signature, validate=True)
155-
with tempfile.TemporaryFile(mode='w+b') as signature_file:
158+
with (tempfile.TemporaryFile(mode='w+b') as signature_file,
159+
tempfile.TemporaryFile(mode='w+b') as public_file):
156160
signature_file.write(raw)
157161
signature_file.flush()
162+
public_file.write(public_pem)
163+
public_file.flush()
158164
verification = subprocess.run(
159-
[str(OPENSSL), 'dgst', '-sha256', '-verify', str(key_file),
165+
[str(OPENSSL), 'dgst', '-sha256', '-verify', f'/proc/self/fd/{public_file.fileno()}',
160166
'-signature', f'/proc/self/fd/{signature_file.fileno()}'],
161167
input=(kind + ':' + exact_digest).encode('ascii'),
162168
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
163-
pass_fds=(signature_file.fileno(),), timeout=2,
169+
pass_fds=(signature_file.fileno(), public_file.fileno()), timeout=2,
164170
env=OPENSSL_ENV, check=False)
165171
return verification.returncode == 0
166172
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired):

‎tests/independent_hosts/retrieval_connected/connected_authority.py‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,16 +151,22 @@ def verify_authority(kind: str, exact_digest: str) -> bool:
151151
try:
152152
if (_public_key() != key_file or _openssl_identity() != verifier_identity):
153153
return False
154+
public_pem = key_file.read_bytes()
155+
if hashlib.sha256(public_pem).hexdigest() != os.environ.get('D_AUTH_PUBKEY_SHA256'):
156+
return False
154157
raw = base64.b64decode(signature, validate=True)
155-
with tempfile.TemporaryFile(mode='w+b') as signature_file:
158+
with (tempfile.TemporaryFile(mode='w+b') as signature_file,
159+
tempfile.TemporaryFile(mode='w+b') as public_file):
156160
signature_file.write(raw)
157161
signature_file.flush()
162+
public_file.write(public_pem)
163+
public_file.flush()
158164
verification = subprocess.run(
159-
[str(OPENSSL), 'dgst', '-sha256', '-verify', str(key_file),
165+
[str(OPENSSL), 'dgst', '-sha256', '-verify', f'/proc/self/fd/{public_file.fileno()}',
160166
'-signature', f'/proc/self/fd/{signature_file.fileno()}'],
161167
input=(kind + ':' + exact_digest).encode('ascii'),
162168
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
163-
pass_fds=(signature_file.fileno(),), timeout=2,
169+
pass_fds=(signature_file.fileno(), public_file.fileno()), timeout=2,
164170
env=OPENSSL_ENV, check=False)
165171
return verification.returncode == 0
166172
except (OSError, ValueError, RuntimeError, subprocess.TimeoutExpired):

‎tests/test_connected_loader_public_keys.py‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
import hashlib
55
import importlib.util
6+
import base64
7+
import json
68
from pathlib import Path
79
import subprocess
810
import sys
@@ -72,3 +74,44 @@ def test_reviewed_loader_requires_anchored_public_p256(monkeypatch, issued_keys,
7274
else:
7375
with pytest.raises(RuntimeError, match='^connected_public_key_invalid$'):
7476
loader._public_key()
77+
78+
79+
@pytest.mark.parametrize('name,relative,prefix', LOADERS, ids=[row[0] for row in LOADERS])
80+
def test_signature_verification_uses_anchored_pem_snapshot(tmp_path, monkeypatch, issued_keys,
81+
name, relative, prefix):
82+
"""An independently valid foreign signature cannot win a key-path race."""
83+
tmp_path.chmod(0o700)
84+
key = tmp_path / 'trusted-public.pem'
85+
key.write_bytes(issued_keys['p256'].read_bytes())
86+
key.chmod(0o600)
87+
real_run = subprocess.run
88+
exact = '0' * 64
89+
signature = real_run(['/usr/bin/openssl', 'dgst', '-sha256', '-sign',
90+
str(issued_keys['rsa'].with_name('rsa-issuer.pem'))],
91+
input=('egress_grant:' + exact).encode('ascii'),
92+
capture_output=True, check=True, timeout=2).stdout
93+
manifest = {'schema_version': '1.0', 'mode': 'shadow', 'connected_config': {},
94+
'authority': {}, 'ledger_path': str(tmp_path / 'ledger'),
95+
'signatures': {'egress_grant': base64.b64encode(signature).decode('ascii')}}
96+
reference = tmp_path / 'reference.json'
97+
reference.write_text(json.dumps(manifest), encoding='utf-8')
98+
reference.chmod(0o600)
99+
monkeypatch.setenv(prefix + '_AUTH_PUBKEY_FILE', str(key))
100+
monkeypatch.setenv(prefix + '_AUTH_PUBKEY_SHA256', hashlib.sha256(key.read_bytes()).hexdigest())
101+
monkeypatch.setenv(prefix + '_CONNECTED_REF', str(reference))
102+
monkeypatch.setenv(prefix + '_CONNECTED_REF_SHA256', hashlib.sha256(reference.read_bytes()).hexdigest())
103+
spec = importlib.util.spec_from_file_location('reviewed_snapshot_loader_' + name, ROOT / relative)
104+
loader = importlib.util.module_from_spec(spec)
105+
spec.loader.exec_module(loader)
106+
options = loader.options()
107+
swapped = []
108+
109+
def replace_key_before_crypto(args, **kwargs):
110+
if len(args) > 1 and args[1] == 'dgst':
111+
key.write_bytes(issued_keys['rsa'].read_bytes())
112+
swapped.append(True)
113+
return real_run(args, **kwargs)
114+
115+
monkeypatch.setattr(loader.subprocess, 'run', replace_key_before_crypto)
116+
assert options['verify_authority']('egress_grant', exact) is False
117+
assert swapped == [True]

0 commit comments

Comments
 (0)