fix(security): isolate workload database identities
All checks were successful
CD Pipeline / workflow-shape (push) Successful in 1s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 2m25s
CD Pipeline / build-and-deploy (push) Successful in 6m42s
CD Pipeline / post-deploy-checks (push) Successful in 1m50s

This commit is contained in:
ogt
2026-07-11 04:20:08 +08:00
parent eb976bdbd2
commit 262c9c8a7e
11 changed files with 1062 additions and 25 deletions

View File

@@ -2019,6 +2019,13 @@ def test_ai_automation_trust_boundary_requires_db_identity_and_budget_receipt()
assert trust_boundary["runtime_progress"]["controls"][
"workload_db_connection_budget_verified"
] is False
assert "SSH egress policy" not in trust_boundary["problem"]
assert "capability lifecycle 尚未" not in trust_boundary["problem"]
assert "DB identity、Secret projection 與 connection budget" in (
trust_boundary["problem"]
)
assert "representative DB preflight" in trust_boundary["next_action"]
assert "live snapshot rollback" in trust_boundary["next_action"]
assert program["summary"]["next_work_item_id"] == "AIA-P0-011"
assert program["summary"]["done_count"] == 1
assert program["summary"]["completion_percent"] == 5

View File

@@ -25,19 +25,32 @@ def _verified_receipt(source_sha: str = "abc123") -> dict[str, str]:
"worker_ssh_egress_denied": "true",
"broker_ssh_egress_allowlisted": "true",
"legacy_namespace_egress_allow_absent": "true",
"db_identity_verifier": "runtime_role_fingerprint_and_secret_projection_v1",
"db_identity_verifier": (
"runtime_role_fingerprint_secret_projection_and_"
"representative_preflight_v2"
),
"api_database_secret_ref": "awoooi-api-db",
"worker_database_secret_ref": "awoooi-worker-db",
"broker_database_secret_ref": "awoooi-broker-db",
"api_db_role_fingerprint": "a" * 64,
"worker_db_role_fingerprint": "b" * 64,
"broker_db_role_fingerprint": "c" * 64,
"api_db_connection_limit": "2",
"api_db_connection_limit": "4",
"worker_db_connection_limit": "2",
"broker_db_connection_limit": "2",
"api_required_connection_budget": "1",
"worker_required_connection_budget": "1",
"broker_required_connection_budget": "1",
"api_required_connection_budget": "4",
"worker_required_connection_budget": "2",
"broker_required_connection_budget": "2",
"api_representative_db_preflight_passed": "true",
"worker_representative_db_preflight_passed": "true",
"broker_representative_db_preflight_passed": "true",
"api_table_privilege_gap_count": "0",
"worker_table_privilege_gap_count": "0",
"broker_table_privilege_gap_count": "0",
"api_sequence_privilege_gap_count": "0",
"worker_sequence_privilege_gap_count": "0",
"broker_sequence_privilege_gap_count": "0",
"representative_db_preflights_verified": "true",
"api_database_null_pool": "true",
"worker_database_null_pool": "true",
"broker_database_null_pool": "true",
@@ -67,9 +80,12 @@ def test_executor_trust_boundary_requires_live_controls_and_matching_source() ->
assert database_boundary["db_identity_isolated"] is True
assert database_boundary["connection_budget_verified"] is True
assert database_boundary["connection_budget"] == {
"observed_total": 6,
"required_total": 3,
"observed_total": 8,
"required_total": 8,
}
assert database_boundary["controls"][
"representative_db_preflights_verified"
] is True
assert database_boundary["secret_values_read"] is False
assert database_boundary["role_names_exposed"] is False
@@ -126,3 +142,22 @@ def test_executor_trust_boundary_keeps_shared_database_identity_in_progress() ->
assert "database_role_fingerprints_not_distinct" in database_boundary[
"active_blockers"
]
def test_executor_trust_boundary_requires_representative_database_preflight() -> None:
receipt = _verified_receipt()
receipt["worker_representative_db_preflight_passed"] = "false"
receipt["worker_table_privilege_gap_count"] = "1"
receipt["representative_db_preflights_verified"] = "false"
readback = build_executor_trust_boundary_readback(
receipt,
deployed_source_sha="abc123",
)
database_boundary = readback["database_identity_boundary"]
assert database_boundary["db_identity_isolated"] is True
assert database_boundary["connection_budget_verified"] is False
assert "worker_representative_db_preflight_not_verified" in (
database_boundary["active_blockers"]
)

View File

@@ -157,8 +157,14 @@ def test_cd_prunes_and_verifies_api_executor_boundary_in_production() -> None:
assert "awoooi-executor-boundary-verification" in workflow
assert "awoooi_executor_boundary_verification_v3" in workflow
assert "executor_boundary_public_readback=verified_ready" in workflow
assert 'boundary.get("full_workload_boundary_verified") is True' in workflow
assert 'database_boundary.get("db_identity_isolated") is True' in workflow
assert 'database_boundary.get("connection_budget_verified") is True' in workflow
assert "verified_source_sha" in workflow
assert "runtime_role_fingerprint_and_secret_projection_v1" in workflow
assert (
"runtime_role_fingerprint_secret_projection_and_"
"representative_preflight_v2"
) in workflow
assert "db_identity_isolated" in workflow
assert "connection_budget_verified" in workflow
assert "api_monolithic_secret_env_from_absent" in workflow
@@ -166,6 +172,17 @@ def test_cd_prunes_and_verifies_api_executor_boundary_in_production() -> None:
assert "distinct_db_role_fingerprints" in workflow
assert "current_user AS role_name" in workflow
assert "hashlib.sha256" in workflow
assert "representative_db_preflights_verified" in workflow
assert "api_required_connection_budget=4" in workflow
assert "worker_required_connection_budget=2" in workflow
assert "broker_required_connection_budget=2" in workflow
assert "WORKLOAD_DB_ROLLBACK_FILE" in workflow
assert "restore_workload_database_projection" in workflow
assert "awoooi-workload-db-identity-bootstrap.sh" in workflow
assert "secret object pre-existence" in workflow.lower()
assert "get secret '${secret_name}'" in workflow
assert "get secret '${secret_name}' -n awoooi-prod -o jsonpath" not in workflow
assert "get secret awoooi-api-db -n awoooi-prod -o jsonpath" not in workflow
assert "argocd.argoproj.io/sync-options=Prune=false" in workflow
assert "argocd.argoproj.io/compare-options=IgnoreExtraneous" in workflow
assert "github.com/kubernetes-sigs/kustomize" not in workflow

View File

@@ -0,0 +1,133 @@
from pathlib import Path
import yaml
REPO_ROOT = Path(__file__).resolve().parents[3]
def _deployment_container(path: str, container_name: str) -> dict:
documents = yaml.safe_load_all((REPO_ROOT / path).read_text())
deployment = next(
document
for document in documents
if document and document.get("kind") == "Deployment"
)
return next(
container
for container in deployment["spec"]["template"]["spec"]["containers"]
if container["name"] == container_name
)
def _env_by_name(container: dict) -> dict[str, dict]:
return {entry["name"]: entry for entry in container.get("env", [])}
def test_runtime_workloads_use_distinct_database_secret_projections() -> None:
workload_specs = {
"api": (
"k8s/awoooi-prod/06-deployment-api.yaml",
"api",
"awoooi-api-db",
),
"worker": (
"k8s/awoooi-prod/08-deployment-worker.yaml",
"worker",
"awoooi-worker-db",
),
"broker": (
"k8s/awoooi-prod/08-deployment-ansible-executor-broker.yaml",
"broker",
"awoooi-broker-db",
),
}
observed_database_secret_refs: set[str] = set()
for workload_id, (path, container_name, expected_secret) in workload_specs.items():
container = _deployment_container(path, container_name)
secret_env_from = [
source
for source in container.get("envFrom", [])
if source.get("secretRef")
]
assert secret_env_from == [], workload_id
env_names = [entry["name"] for entry in container.get("env", [])]
assert len(env_names) == len(set(env_names)), workload_id
env = _env_by_name(container)
database_ref = env["DATABASE_URL"]["valueFrom"]["secretKeyRef"]
assert database_ref == {
"name": expected_secret,
"key": "DATABASE_URL",
}
observed_database_secret_refs.add(database_ref["name"])
assert env["DATABASE_NULL_POOL"]["value"] == "true"
assert observed_database_secret_refs == {
"awoooi-api-db",
"awoooi-worker-db",
"awoooi-broker-db",
}
def test_api_and_worker_project_shared_secrets_explicitly() -> None:
for path, container_name in (
("k8s/awoooi-prod/06-deployment-api.yaml", "api"),
("k8s/awoooi-prod/08-deployment-worker.yaml", "worker"),
):
env = _env_by_name(_deployment_container(path, container_name))
for env_name in (
"REDIS_URL",
"GEMINI_API_KEY",
"OPENCLAW_TG_BOT_TOKEN",
"SRE_GROUP_CHAT_ID",
"WEBHOOK_HMAC_SECRET",
"AWOOOP_OPERATOR_API_KEY",
):
secret_ref = env[env_name]["valueFrom"]["secretKeyRef"]
assert secret_ref["name"] == "awoooi-secrets"
assert secret_ref["key"] == env_name
assert secret_ref["optional"] is True
def test_workload_database_bootstrap_keeps_secret_values_off_output() -> None:
script = (
REPO_ROOT / "scripts/ops/awoooi-workload-db-identity-bootstrap.sh"
).read_text()
assert "set +x" in script
assert "openssl rand -hex 32" in script
assert "--from-file=DATABASE_URL=/dev/stdin" in script
assert "--from-literal=DATABASE_URL" not in script
assert "docker exec -i -u postgres" in script
assert "table_privilege_gap_count" in script
assert "sequence_privilege_gap_count" in script
assert '"incidents"' in script
assert '"knowledge_entries"' in script
assert '"awooop_run_state"' in script
assert "ALTER ROLE %I NOLOGIN" in script
assert "DROP ROLE" not in script.upper()
assert "base64 -d" not in script
assert "GITHUB_RUN_ID" not in script
assert 'check|apply|verify|disable' in script
assert '"secret_value_exposed": False' in script
assert '"secret_value_logged": False' in script
assert "secret_value_read" not in script
def test_cd_uses_live_spec_rollback_and_non_mutating_post_verifier() -> None:
workflow = (REPO_ROOT / ".gitea/workflows/cd.yaml").read_text()
assert "WORKLOAD_DB_ROLLBACK_FILE" in workflow
assert "WORKLOAD_DB_SECRET_PREEXISTENCE_FILE" in workflow
assert "restore_workload_database_projection" in workflow
assert "bash -s -- apply" in workflow
assert "bash -s -- verify" in workflow
assert workflow.index("bash -s -- apply") < workflow.index(
"bash -s -- verify"
)
assert '"spec": item["spec"]' in workflow
assert '"data": item' not in workflow
assert "get secret '${secret_name}' -n awoooi-prod -o jsonpath" not in workflow
assert "get secret awoooi-api-db -n awoooi-prod -o jsonpath" not in workflow
assert "HEAD^" not in workflow