diff --git a/tests/unit/test_clean_room_automation_contract.sh b/tests/unit/test_clean_room_automation_contract.sh index 58ad052..a92bc4f 100755 --- a/tests/unit/test_clean_room_automation_contract.sh +++ b/tests/unit/test_clean_room_automation_contract.sh @@ -125,6 +125,20 @@ def main() -> None: raise SystemExit("readiness must not treat generic python3 as the Ansible interpreter") print("PASS: readiness requires python3.12") + if "clean_room_has_angle_placeholders" not in lib: + raise SystemExit("shared placeholder detector is missing from the helper") + if re.search(r"grep -Eq '<|>'", lib): + raise SystemExit("placeholder detector must not scan comment-only angle brackets") + if "clean_room_has_angle_placeholders" not in deploy: + raise SystemExit("deploy must use the shared placeholder detector") + if "clean_room_has_angle_placeholders" not in verify: + raise SystemExit("verify must use the shared placeholder detector") + if "clean_room_has_angle_placeholders" not in readiness: + raise SystemExit("readiness must use the shared placeholder detector") + if re.search(r"grep -Eq '<|>'", readiness): + raise SystemExit("readiness must not duplicate whole-file angle-bracket grep") + print("PASS: placeholder detection ignores comment-only angle brackets") + if "-auto-approve" in deploy: raise SystemExit("deploy-clean-room must not use -auto-approve") if not re.search(r"-e\s+scratch_storage_allow_format=true", deploy): @@ -266,6 +280,83 @@ else fi TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/clean-room-automation.XXXXXX")" +PH_DIR="${TMP_ROOT}/placeholders" +mkdir -p "$PH_DIR" + +cat >"${PH_DIR}/active.hcl" <<'EOF' +oci_region = "" +EOF +if clean_room_has_angle_placeholders "${PH_DIR}/active.hcl"; then + pass "active HCL placeholder is rejected" +else + fail "active HCL placeholder is rejected" +fi + +cat >"${PH_DIR}/active.yml" <<'EOF' +private_runtime_config_vault_id: "" +EOF +if clean_room_has_angle_placeholders "${PH_DIR}/active.yml"; then + pass "active YAML placeholder is rejected" +else + fail "active YAML placeholder is rejected" +fi + +cat >"${PH_DIR}/comment-only.tfvars" <<'EOF' +# curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//' +ssh_ingress_cidr = "203.0.113.10/32" +EOF +if clean_room_has_angle_placeholders "${PH_DIR}/comment-only.tfvars"; then + fail "comment-only angle bracket is accepted" +else + pass "comment-only angle bracket is accepted" +fi + +cat >"${PH_DIR}/ws-comment.tfvars" <<'EOF' + # curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//' +ssh_ingress_cidr = "203.0.113.10/32" +EOF +if clean_room_has_angle_placeholders "${PH_DIR}/ws-comment.tfvars"; then + fail "leading-whitespace comment-only angle bracket is accepted" +else + pass "leading-whitespace comment-only angle bracket is accepted" +fi + +python3 - "${ROOT}/terraform/terraform.tfvars.example" "${PH_DIR}/populated.tfvars" <<'PY' +from pathlib import Path +import sys + +src = Path(sys.argv[1]).read_text(encoding="utf-8") +replacements = { + "": "eu-frankfurt-1", + "": "ocid1.compartment.oc1..example", + "": "ocid1.tenancy.oc1..example", + "": "ocid1.vault.oc1..example", + "": "ocid1.compartment.oc1..vault-example", + "": "203.0.113.10/32", + "": ( + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA " + "contract-test@example.invalid" + ), +} +for old, new in replacements.items(): + src = src.replace(old, new) +Path(sys.argv[2]).write_text(src, encoding="utf-8") +PY +if grep -Fq "s/<.*\$//" "${PH_DIR}/populated.tfvars" \ + && ! clean_room_has_angle_placeholders "${PH_DIR}/populated.tfvars"; then + pass "populated terraform.tfvars-style fixture with curl/sed comment is accepted" +else + fail "populated terraform.tfvars-style fixture with curl/sed comment is accepted" +fi + +if clean_room_has_angle_placeholders "${ROOT}/terraform/terraform.tfvars.example" \ + && clean_room_has_angle_placeholders "${ROOT}/terraform/backend.hcl.example" \ + && clean_room_has_angle_placeholders "${ROOT}/ansible/extra-vars/private-runtime.yml.example"; then + pass "committed example files still fail placeholder checks" +else + fail "committed example files still fail placeholder checks" +fi + HELPER_DIR="${TMP_ROOT}/helper" mkdir -p "$HELPER_DIR" @@ -585,6 +676,9 @@ oci_compartment_id = "ocid1.compartment.oc1..example" oci_tenancy_id = "ocid1.tenancy.oc1..example" oci_vault_id = "ocid1.vault.oc1..example" oci_vault_compartment_id = "ocid1.compartment.oc1..vault-example" +# Cloud Shell public egress IP is dynamic across sessions. +# Example discovery (Cloud Shell docs): +# curl -s checkip.dyndns.org | sed -e 's/.*Current IP Address: //' -e 's/<.*$//' ssh_ingress_cidr = "203.0.113.10/32" ssh_public_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA contract-test@example.invalid" EOF diff --git a/tests/unit/test_cloud_shell_execution_contracts.sh b/tests/unit/test_cloud_shell_execution_contracts.sh index d8187ea..3daaf40 100755 --- a/tests/unit/test_cloud_shell_execution_contracts.sh +++ b/tests/unit/test_cloud_shell_execution_contracts.sh @@ -85,6 +85,8 @@ def main() -> None: content = content.replace(old, new) if ssh_public_key_uses_function(content): raise SystemExit("sanitized temp tfvars unexpectedly contains functions") + if "s/<.*$//" not in content: + raise SystemExit("sanitized tfvars must retain the documented curl/sed comment") sanitized.write_text(content, encoding="utf-8") print("PASS: sanitized temp var-file keeps literal ssh_public_key") diff --git a/tools/check-cloud-shell-readiness b/tools/check-cloud-shell-readiness index 43fede5..d090e9c 100755 --- a/tools/check-cloud-shell-readiness +++ b/tools/check-cloud-shell-readiness @@ -1,9 +1,15 @@ #!/usr/bin/env bash +# shellcheck shell=bash # Local/static Cloud Shell execution-readiness checks. # Does not create buckets, mutate IAM, terraform init/plan/apply, SSH, or Ansible. set -euo pipefail -ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +# shellcheck source=lib/clean-room-common.sh +# Dynamic SCRIPT_DIR path is not followed without shellcheck -x; the helper is linted separately. +# shellcheck disable=SC1091 +source "${SCRIPT_DIR}/lib/clean-room-common.sh" STRICT=0 failures=0 @@ -176,7 +182,7 @@ check_file "${ROOT}/docs/V2_CLEAN_ROOM_DEPLOYMENT.md" "clean-room runbook" if [[ -f "${ROOT}/terraform/backend.hcl" ]]; then pass "operator backend.hcl present" - if grep -Eq '<|>' "${ROOT}/terraform/backend.hcl"; then + if clean_room_has_angle_placeholders "${ROOT}/terraform/backend.hcl"; then placeholder_issue "terraform/backend.hcl" else pass "terraform/backend.hcl has no angle-bracket placeholders" @@ -201,7 +207,7 @@ fi if [[ -f "${ROOT}/terraform/terraform.tfvars" ]]; then pass "operator terraform.tfvars present" - if grep -Eq '<|>' "${ROOT}/terraform/terraform.tfvars"; then + if clean_room_has_angle_placeholders "${ROOT}/terraform/terraform.tfvars"; then placeholder_issue "terraform/terraform.tfvars" else pass "terraform.tfvars has no angle-bracket placeholders" @@ -221,7 +227,7 @@ fi if [[ -f "${ROOT}/ansible/extra-vars/private-runtime.yml" ]]; then pass "operator private-runtime.yml present" - if grep -Eq '<|>' "${ROOT}/ansible/extra-vars/private-runtime.yml"; then + if clean_room_has_angle_placeholders "${ROOT}/ansible/extra-vars/private-runtime.yml"; then placeholder_issue "ansible/extra-vars/private-runtime.yml" else pass "private-runtime.yml has no angle-bracket placeholders" diff --git a/tools/lib/clean-room-common.sh b/tools/lib/clean-room-common.sh index f5e4a37..43c24bf 100755 --- a/tools/lib/clean-room-common.sh +++ b/tools/lib/clean-room-common.sh @@ -89,9 +89,11 @@ sys.exit(0 if ok else 1) PY } +# True when an active (non-comment, non-blank) line contains < or >. +# Full-line comments such as sed 's/<.*$//' are documentation, not placeholders. clean_room_has_angle_placeholders() { local path="$1" - grep -Eq '<|>' "$path" + grep -Eq '^[[:space:]]*[^#[:space:]].*[<>]' "$path" } clean_room_require_exact_input() {