Skip to content

Commit 41fb90f

Browse files
authored
refactor(release): remove duplicate runtime validation (#540)
Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
1 parent 14d06ea commit 41fb90f

2 files changed

Lines changed: 21 additions & 114 deletions

File tree

‎release/scripts/first-country-release-form.py‎

Lines changed: 12 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@
5959
RELAY_LISTENER = "127.0.0.1:4242"
6060
NOTARY_LISTENER = "127.0.0.1:4255"
6161
RECORDS_PURPOSE = "public-works-case-management"
62-
CANONICAL_WORKBOOK_PROJECT_FILE = "data/public_works_projects.xlsx"
63-
CANONICAL_WORKBOOK_RUNTIME_PATH = "/data/public_works_projects.xlsx"
6462
MATCH_KEY_ENV = "REGISTRYCTL_LOCAL_RELAY_MATCH_KEY_RAW"
6563
NO_MATCH_KEY_ENV = "REGISTRYCTL_LOCAL_RELAY_NO_MATCH_KEY_RAW"
6664
MATCH_FIELDS = {"project_id", "district_code", "sector", "status"}
@@ -104,41 +102,6 @@
104102
for name, status in {**RELAY_SMOKE_OUTCOMES, **NOTARY_SMOKE_OUTCOMES}.items()
105103
],
106104
}
107-
NOTARY_MANIFEST_DIGEST_PATHS = {
108-
"consultation_relay_config_digest": (
109-
".registry-stack/build/local/private/relay/config/relay-consultation.yaml"
110-
),
111-
"runtime_consultation_relay_config_digest": (
112-
".registry-stack/runtime/local/private/relay/config/relay-consultation.yaml"
113-
),
114-
"compiled_notary_config_digest": (
115-
".registry-stack/build/local/private/notary/config/notary.yaml"
116-
),
117-
"runtime_notary_config_digest": (
118-
".registry-stack/runtime/local/private/notary/config/notary.yaml"
119-
),
120-
"postgres_ca_digest": (
121-
".registry-stack/runtime/local/private/relay/config/state-plane-ca.pem"
122-
),
123-
"database_init_digest": ".registry-stack/runtime/local/private/db/init.sh",
124-
"workload_jwks_digest": (
125-
".registry-stack/runtime/local/private/workload/jwks.json"
126-
),
127-
"consultation_relay_env_digest": (
128-
".registry-stack/runtime/local/secrets/relay-consultation.env"
129-
),
130-
"relay_bootstrap_env_digest": (
131-
".registry-stack/runtime/local/secrets/relay-bootstrap.env"
132-
),
133-
"notary_env_digest": ".registry-stack/runtime/local/secrets/notary.env",
134-
"postgres_env_digest": ".registry-stack/runtime/local/secrets/postgres.env",
135-
"workload_token_digest": (
136-
".registry-stack/runtime/local/secrets/relay-workload-token"
137-
),
138-
"workload_private_jwk_digest": (
139-
".registry-stack/runtime/local/secrets/workload-private.jwk"
140-
),
141-
}
142105
SECRET_FILES = {
143106
"local_env": "local.env",
144107
"relay_env": "relay.env",
@@ -622,17 +585,6 @@ def digest_uri(path: Path) -> str:
622585
return f"sha256:{sha256(path)}"
623586

624587

625-
def require_manifest_digest(
626-
manifest: dict[str, Any],
627-
field: str,
628-
path: Path,
629-
) -> None:
630-
if manifest.get(field) != digest_uri(path):
631-
raise ReleaseFormError(
632-
f"canonical runtime manifest does not bind {field}"
633-
)
634-
635-
636588
def read_runtime_inspection(
637589
project: Path,
638590
*,
@@ -659,90 +611,49 @@ def read_runtime_inspection(
659611
expected_topology = (
660612
"combined_notary" if expected_notary_image is not None else "relay_only"
661613
)
662-
expected_keys = {
614+
# registryctl start and smoke validate the internal runtime contract. Keep
615+
# this release-form check limited to the identity recorded as evidence.
616+
required_keys = {
663617
"schema_version",
664618
"environment",
665619
"relay_image",
666-
"compose_digest",
667-
"artifact_manifest_digest",
668-
"relay_config_digest",
669-
"workbook_digest",
670620
"workbook_classification",
671-
"workbook_project_file",
672-
"workbook_runtime_path",
673-
"match_principal",
674-
"runtime_uid",
675-
"runtime_gid",
676-
"runtime_files",
677621
"topology",
678622
}
679623
if expected_notary_image is not None:
680-
expected_keys.add("notary")
681-
if not isinstance(runtime_manifest, dict) or set(runtime_manifest) != expected_keys:
682-
raise ReleaseFormError("canonical runtime manifest fields are not closed")
624+
required_keys.add("notary")
625+
if (
626+
not isinstance(runtime_manifest, dict)
627+
or not required_keys.issubset(runtime_manifest)
628+
):
629+
raise ReleaseFormError(
630+
"canonical runtime manifest is missing required evidence fields"
631+
)
683632
if (
684633
runtime_manifest.get("schema_version") != "registryctl.local_runtime.v2"
685634
or runtime_manifest.get("environment") != "local"
686635
or runtime_manifest.get("relay_image") != expected_relay_image
687636
or runtime_manifest.get("workbook_classification")
688637
!= "operator_owned_source_data"
689-
or not isinstance(runtime_manifest.get("match_principal"), str)
690-
or not runtime_manifest["match_principal"]
691-
or not isinstance(runtime_manifest.get("runtime_uid"), str)
692-
or not runtime_manifest["runtime_uid"].isdigit()
693-
or runtime_manifest.get("runtime_uid") == "0"
694-
or not isinstance(runtime_manifest.get("runtime_gid"), str)
695-
or not runtime_manifest["runtime_gid"].isdigit()
696-
or runtime_manifest.get("runtime_gid") == "0"
697-
or not isinstance(runtime_manifest.get("runtime_files"), dict)
698-
or not runtime_manifest["runtime_files"]
699638
or runtime_manifest.get("topology") != expected_topology
700639
):
701640
raise ReleaseFormError(
702-
"canonical runtime identity, topology, or workbook classification is invalid"
641+
"canonical runtime release identity, topology, or workbook classification is invalid"
703642
)
704-
require_manifest_digest(runtime_manifest, "relay_config_digest", relay_config)
705-
require_manifest_digest(runtime_manifest, "compose_digest", compose)
706-
artifact_manifest = project / ".registry-stack/build/local/artifact-manifest.json"
707-
require_manifest_digest(
708-
runtime_manifest, "artifact_manifest_digest", artifact_manifest
709-
)
710-
workbook_project_file = runtime_manifest.get("workbook_project_file")
711-
workbook_runtime_path = runtime_manifest.get("workbook_runtime_path")
712-
if (
713-
workbook_project_file != CANONICAL_WORKBOOK_PROJECT_FILE
714-
or workbook_runtime_path != CANONICAL_WORKBOOK_RUNTIME_PATH
715-
):
716-
raise ReleaseFormError(
717-
"canonical runtime does not bind the maintained spreadsheet starter"
718-
)
719-
require_manifest_digest(
720-
runtime_manifest,
721-
"workbook_digest",
722-
project / workbook_project_file,
723-
)
724643
notary = runtime_manifest.get("notary")
725644
if expected_notary_image is None:
726645
if notary is not None or expected_postgresql_image is not None:
727646
raise ReleaseFormError("Relay-only canonical runtime contains Notary state")
728647
else:
729-
expected_notary_keys = {
730-
"notary_image",
731-
"postgresql_image",
732-
*NOTARY_MANIFEST_DIGEST_PATHS,
733-
}
734648
if (
735649
expected_postgresql_image is None
736650
or not isinstance(notary, dict)
737-
or set(notary) != expected_notary_keys
738651
or notary.get("notary_image") != expected_notary_image
739652
or notary.get("postgresql_image") != expected_postgresql_image
740653
):
741654
raise ReleaseFormError(
742655
"combined canonical runtime Notary manifest is incomplete"
743656
)
744-
for field, relative in NOTARY_MANIFEST_DIGEST_PATHS.items():
745-
require_manifest_digest(notary, field, project / relative)
746657
return {
747658
"relay_config_sha256": sha256(relay_config),
748659
"runtime_manifest_sha256": sha256(manifest),

‎release/scripts/test_first_country_release_form.py‎

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -176,16 +176,14 @@ def write_smoke_report(self, topology: str) -> Path:
176176
def write_combined_runtime(self) -> Path:
177177
files = {
178178
".registry-stack/build/local/private/relay/config/relay.yaml": "relay\n",
179+
".registry-stack/build/local/private/notary/config/notary.yaml": (
180+
"notary\n"
181+
),
179182
".registry-stack/build/local/artifact-manifest.json": "artifacts\n",
180183
"data/public_works_projects.xlsx": "workbook\n",
181184
".registry-stack/runtime/local/compose.yaml": "services: {}\n",
185+
".registry-stack/runtime/local/secrets/local.env": "secret\n",
182186
}
183-
files.update(
184-
{
185-
relative: f"{field}\n"
186-
for field, relative in self.module.NOTARY_MANIFEST_DIGEST_PATHS.items()
187-
}
188-
)
189187
for relative, contents in files.items():
190188
path = self.root / relative
191189
path.parent.mkdir(parents=True, exist_ok=True)
@@ -222,10 +220,6 @@ def write_combined_runtime(self) -> Path:
222220
"notary": {
223221
"notary_image": self.notary,
224222
"postgresql_image": self.postgresql,
225-
**{
226-
field: self.module.digest_uri(self.root / relative)
227-
for field, relative in self.module.NOTARY_MANIFEST_DIGEST_PATHS.items()
228-
},
229223
},
230224
}
231225
path = self.root / ".registry-stack/runtime/local/manifest.json"
@@ -517,15 +511,17 @@ def test_runtime_inspection_rejects_missing_notary_manifest(self) -> None:
517511
expected_postgresql_image=self.postgresql,
518512
)
519513

520-
def test_runtime_inspection_rejects_unbound_notary_config(self) -> None:
514+
def test_runtime_inspection_rejects_wrong_notary_image(self) -> None:
521515
path = self.write_combined_runtime()
522516
manifest = json.loads(path.read_text(encoding="utf-8"))
523-
manifest["notary"]["runtime_notary_config_digest"] = "sha256:" + "0" * 64
517+
manifest["notary"]["notary_image"] = (
518+
"ghcr.io/registrystack/registry-notary@sha256:" + "0" * 64
519+
)
524520
path.write_text(json.dumps(manifest), encoding="utf-8")
525521

526522
with self.assertRaisesRegex(
527523
self.module.ReleaseFormError,
528-
"does not bind runtime_notary_config_digest",
524+
"Notary manifest is incomplete",
529525
):
530526
self.module.read_runtime_inspection(
531527
self.root,

0 commit comments

Comments
 (0)