From 0809cc740a2e1f5c5d1984cd5ef2217777393a6d Mon Sep 17 00:00:00 2001 From: david Date: Fri, 18 Sep 2026 23:23:20 -0400 Subject: [PATCH] Add fail-closed ACME authority helper injection --- functions/common.py | 141 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 135 insertions(+), 6 deletions(-) diff --git a/functions/common.py b/functions/common.py index 6307b47..6afb058 100644 --- a/functions/common.py +++ b/functions/common.py @@ -11,6 +11,21 @@ import os AUTHORITY_FILE = "/acme_authority/state/acme-authority" +HELPER_MARKER = "const acmeAuthorityFile =" + +AUTHORITY_HELPER = f"""const acmeAuthorityFile = "{AUTHORITY_FILE}"; + +const requireAcmeAuthority = () => {{ + try {{ + fs.accessSync(acmeAuthorityFile, fs.constants.R_OK); + }} catch {{ + throw new error.ValidationError( + "ACME operations are disabled on this cluster node", + ); + }} +}}; +""" + @dataclass(frozen=True) class GateConfig: @@ -65,19 +80,133 @@ def write_source(path: Path, source: str) -> None: path.write_text(source) +def replace_exactly_once( + source: str, + old: str, + new: str, + *, + description: str, +) -> str: + count = source.count(old) + + if count != 1: + raise RuntimeError( + f"{description}: expected anchor exactly once, found {count}" + ) + + return source.replace(old, new, 1) + + +def require_fragment( + source: str, + fragment: str, + *, + description: str, +) -> None: + if fragment not in source: + raise RuntimeError( + f"{description}: required fragment not found" + ) + + def apply_authority_helper(source: str) -> str: """ - Install the common requireAcmeAuthority() helper. + Install the shared requireAcmeAuthority() helper. - Implemented in the next development step. + The helper is inserted immediately after the top-level fs import so the + patch remains close to the dependency it requires. """ - raise NotImplementedError("authority helper mutation not implemented yet") + + expected_declaration = ( + f'const acmeAuthorityFile = "{AUTHORITY_FILE}";' + ) + + if expected_declaration in source: + require_fragment( + source, + "const requireAcmeAuthority = () => {", + description="existing authority helper", + ) + require_fragment( + source, + "fs.accessSync(acmeAuthorityFile, fs.constants.R_OK);", + description="existing authority helper", + ) + + log("authority_helper=already-present") + return source + + if HELPER_MARKER in source: + raise RuntimeError( + "authority helper already exists but does not match " + f"configured authority file {AUTHORITY_FILE}" + ) + + # Prefer the end of the known ESM import block used by current NPM. + # Older CommonJS releases fall back to their fs import. + supported_anchors = ( + 'import internalNginx from "./nginx.js";\n', + 'const fs = require("fs");\n', + 'const fs = require("node:fs");\n', + ) + + matches = [ + anchor + for anchor in supported_anchors + if anchor in source + ] + + if len(matches) != 1: + raise RuntimeError( + "authority helper: expected exactly one supported insertion " + f"anchor, found {len(matches)}" + ) + + anchor = matches[0] + replacement = anchor + "\n" + AUTHORITY_HELPER + + source = replace_exactly_once( + source, + anchor, + replacement, + description="authority helper", + ) + + log(f"authority_helper=added anchor={anchor.strip()!r}") + return source def verify(source: str, config: GateConfig) -> None: """ - Verify every requested mutation before certificate.js is written. + Verify shared patch state. - Implemented after the individual mutation modules. + Individual mutation modules will add their own verification markers as + they are implemented. """ - raise NotImplementedError("patch verification not implemented yet") + + if config.any_enabled: + require_fragment( + source, + f'const acmeAuthorityFile = "{AUTHORITY_FILE}";', + description="authority helper verification", + ) + + require_fragment( + source, + "const requireAcmeAuthority = () => {", + description="authority helper verification", + ) + + require_fragment( + source, + "fs.accessSync(acmeAuthorityFile, fs.constants.R_OK);", + description="authority helper verification", + ) + + require_fragment( + source, + "ACME operations are disabled on this cluster node", + description="authority helper verification", + ) + + log("verification=passed")