Publish curated ITWorx-ModelForge source from 990401737f96c8d46a9f7b0d84994516cadcb6a0
This commit is contained in:
1 parent
7082ab955a
commit
848f0d8f8a
434 files changed
+67298
-4315
No files matched your search
@@ -9,21 +9,29 @@ from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
from types import ModuleType, SimpleNamespace
|
||||
from typing import Any, cast
|
||||
from unittest.mock import Mock
|
||||
from typing import Any, Self, cast
|
||||
|
||||
import psycopg
|
||||
import pytest
|
||||
from pydantic import SecretStr
|
||||
from sqlalchemy import create_engine, func, select
|
||||
from sqlalchemy.engine import Engine
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from modelforge_api.persistence.audit_postgres import (
|
||||
AUDIT_APPEND_BODY_SHA256,
|
||||
AUDIT_GUARD_BODY_SHA256,
|
||||
)
|
||||
from modelforge_api.persistence.models import _textual_audit_dml_targets
|
||||
from modelforge_api.persistence.models import (
|
||||
AuditChainHead,
|
||||
AuditEvent,
|
||||
_textual_audit_dml_targets,
|
||||
)
|
||||
from modelforge_api.services.audit import AuditWriter
|
||||
from modelforge_api.services.startup_validation import (
|
||||
AUDIT_RUNTIME_BOUNDARY_SQL,
|
||||
StartupFailureCode,
|
||||
@@ -150,22 +158,20 @@ def test_generated_sql_is_executed_as_driver_safe_complete_statements() -> None:
|
||||
assert append_function.rstrip().endswith("$append$")
|
||||
assert all(statement.strip() and not statement.rstrip().endswith(";") for statement in statements)
|
||||
|
||||
class DriverConnection:
|
||||
dialect = SimpleNamespace(name="postgresql", paramstyle="pyformat")
|
||||
|
||||
def test_postgres_percent_syntax_is_escaped_only_at_the_dbapi_boundary() -> None:
|
||||
module = _migration()
|
||||
connection = SimpleNamespace(
|
||||
dialect=SimpleNamespace(name="postgresql", paramstyle="pyformat"),
|
||||
exec_driver_sql=Mock(),
|
||||
)
|
||||
def __init__(self) -> None:
|
||||
self.statements: list[str] = []
|
||||
|
||||
module._exec_postgres_sql(
|
||||
connection,
|
||||
"declare value public.audit_events%rowtype; select format('%I', 'value')",
|
||||
)
|
||||
def exec_driver_sql(self, statement: str) -> None:
|
||||
self.statements.append(statement)
|
||||
|
||||
connection.exec_driver_sql.assert_called_once_with(
|
||||
"declare value public.audit_events%%rowtype; select format('%%I', 'value')"
|
||||
)
|
||||
driver = DriverConnection()
|
||||
module._install_postgres_audit_boundary(driver)
|
||||
assert driver.statements
|
||||
assert any("%%rowtype" in statement.lower() for statement in driver.statements)
|
||||
assert any("%%I" in statement for statement in driver.statements)
|
||||
|
||||
|
||||
class _Rows:
|
||||
@@ -324,10 +330,10 @@ class _StartupConnection:
|
||||
def __init__(self, facts: dict[str, Any]) -> None:
|
||||
self.facts = facts
|
||||
|
||||
def __enter__(self) -> _StartupConnection:
|
||||
def __enter__(self) -> Self:
|
||||
return self
|
||||
|
||||
def __exit__(self, *_args: Any) -> None:
|
||||
def __exit__(self, *_args: object) -> None:
|
||||
return None
|
||||
|
||||
def exec_driver_sql(self, _sql: str) -> _ScalarResult:
|
||||
@@ -335,7 +341,7 @@ class _StartupConnection:
|
||||
|
||||
def execute(self, statement: Any) -> _ScalarResult:
|
||||
if "alembic_version" in str(statement):
|
||||
return _ScalarResult("20260830_0024")
|
||||
return _ScalarResult("20260909_0030")
|
||||
return _ScalarResult(self.facts)
|
||||
|
||||
|
||||
@@ -363,6 +369,118 @@ def _production_settings(tmp_path: Path, **overrides: Any) -> Settings:
|
||||
return Settings(**values)
|
||||
|
||||
|
||||
def _psycopg_url(sqlalchemy_url: str) -> str:
|
||||
return sqlalchemy_url.replace("postgresql+psycopg://", "postgresql://", 1)
|
||||
|
||||
|
||||
def _assert_postgres_statement_is_denied(database_url: str, statement: str) -> None:
|
||||
with psycopg.connect(_psycopg_url(database_url)) as connection:
|
||||
# Keep the cursor scope nested so rollback happens before the connection context can
|
||||
# commit; combining these contexts would make an unexpectedly allowed DDL statement real.
|
||||
with connection.cursor() as cursor: # noqa: SIM117
|
||||
with pytest.raises(psycopg.errors.InsufficientPrivilege):
|
||||
cursor.execute(statement)
|
||||
connection.rollback()
|
||||
|
||||
|
||||
def test_managed_postgresql_executes_the_runtime_privilege_boundary(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
"""Prove the generated grant contract against PostgreSQL, not merely against SQL text."""
|
||||
|
||||
owner_url = os.getenv("MODELFORGE_TEST_POSTGRES_OWNER_URL")
|
||||
runtime_url = os.getenv("MODELFORGE_TEST_POSTGRES_RUNTIME_URL")
|
||||
if not owner_url or not runtime_url:
|
||||
pytest.skip("managed PostgreSQL owner/runtime URLs are not configured")
|
||||
|
||||
with psycopg.connect(_psycopg_url(owner_url)) as owner_connection:
|
||||
owner_facts = owner_connection.execute(
|
||||
"""
|
||||
select current_user, session_user, rolsuper, rolcreaterole, rolcreatedb,
|
||||
rolreplication, rolbypassrls
|
||||
from pg_catalog.pg_roles
|
||||
where rolname = current_user
|
||||
"""
|
||||
).fetchone()
|
||||
assert owner_facts == ("modelforge", "modelforge", False, False, False, False, False)
|
||||
|
||||
with psycopg.connect(_psycopg_url(runtime_url)) as runtime_connection:
|
||||
runtime_facts = runtime_connection.execute(
|
||||
"""
|
||||
select current_user, session_user, rolsuper, rolcreaterole, rolcreatedb,
|
||||
rolreplication, rolbypassrls, rolinherit
|
||||
from pg_catalog.pg_roles
|
||||
where rolname = current_user
|
||||
"""
|
||||
).fetchone()
|
||||
memberships = runtime_connection.execute(
|
||||
"""
|
||||
select count(*)
|
||||
from pg_catalog.pg_auth_members
|
||||
where member = (select oid from pg_catalog.pg_roles where rolname = current_user)
|
||||
"""
|
||||
).fetchone()
|
||||
visible_events = runtime_connection.execute(
|
||||
"select count(*) from public.audit_events"
|
||||
).fetchone()
|
||||
assert runtime_facts == (
|
||||
"modelforge_runtime",
|
||||
"modelforge_runtime",
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
False,
|
||||
)
|
||||
assert memberships == (0,)
|
||||
assert visible_events == (0,)
|
||||
|
||||
_assert_postgres_statement_is_denied(runtime_url, "set role modelforge")
|
||||
_assert_postgres_statement_is_denied(runtime_url, "truncate public.audit_events")
|
||||
_assert_postgres_statement_is_denied(
|
||||
runtime_url,
|
||||
"insert into public.audit_events default values",
|
||||
)
|
||||
_assert_postgres_statement_is_denied(
|
||||
runtime_url,
|
||||
"create table public.modelforge_forbidden_runtime_ddl (id integer)",
|
||||
)
|
||||
|
||||
engine = create_engine(runtime_url)
|
||||
try:
|
||||
with Session(engine) as session:
|
||||
AuditWriter(session, "system", "managed-postgres-boundary").write(
|
||||
"MANAGED_POSTGRES_BOUNDARY_VERIFIED",
|
||||
"release_validation",
|
||||
None,
|
||||
{"credential": "runtime", "direct_audit_dml": "denied"},
|
||||
)
|
||||
session.commit()
|
||||
|
||||
with Session(engine) as session:
|
||||
checkpoint = session.get(AuditChainHead, 1)
|
||||
event_count = session.scalar(select(func.count()).select_from(AuditEvent))
|
||||
assert checkpoint is not None
|
||||
assert event_count == 1
|
||||
assert checkpoint.event_count == 1
|
||||
assert checkpoint.last_sequence == 1
|
||||
assert checkpoint.last_event_hash is not None
|
||||
|
||||
report = validate_startup(
|
||||
_production_settings(tmp_path, database_url=runtime_url),
|
||||
engine,
|
||||
)
|
||||
incompatible = [
|
||||
problem
|
||||
for problem in report.problems
|
||||
if problem.code is StartupFailureCode.INCOMPATIBLE_DATABASE
|
||||
]
|
||||
assert incompatible == []
|
||||
finally:
|
||||
engine.dispose()
|
||||
|
||||
|
||||
def test_production_startup_uses_catalog_policy_and_refuses_a_broken_trigger(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
@@ -400,9 +518,12 @@ def test_production_configuration_rejects_owner_role_and_owner_secret_presence(
|
||||
def test_compose_and_image_keep_admin_owner_credentials_out_of_the_api_process() -> None:
|
||||
compose = (ROOT / "docker-compose.yml").read_text("utf-8")
|
||||
dockerfile = (ROOT / "backend" / "Dockerfile").read_text("utf-8")
|
||||
postgres_section = compose.split("\n postgres:", 1)[1].split("\n redis:", 1)[0]
|
||||
api_section = compose.split("\n api:", 1)[1].split("\n migrate:", 1)[0]
|
||||
migrate_section = compose.split("\n migrate:", 1)[1].split("\n web:", 1)[0]
|
||||
|
||||
assert "MODELFORGE_POSTGRES_ADMIN_USER:" in postgres_section
|
||||
assert "MODELFORGE_POSTGRES_ADMIN_PASSWORD:" in postgres_section
|
||||
assert "MODELFORGE_RUNTIME_DATABASE_URL" in api_section
|
||||
assert "MODELFORGE_MIGRATION_DATABASE_URL" not in api_section
|
||||
assert "MODELFORGE_POSTGRES_ADMIN_PASSWORD" not in api_section
|
||||
@@ -413,21 +534,32 @@ def test_compose_and_image_keep_admin_owner_credentials_out_of_the_api_process()
|
||||
|
||||
|
||||
def test_role_provisioning_contains_no_password_literal_and_demotes_both_app_roles() -> None:
|
||||
for relative_path in (
|
||||
"deploy/postgres/init/001-modelforge-roles.sql",
|
||||
"deploy/postgres/provision-existing-1.2.1.sql",
|
||||
):
|
||||
provisioning = (ROOT / relative_path).read_text("utf-8")
|
||||
provisioning = (
|
||||
ROOT / "deploy" / "postgres" / "init" / "001-modelforge-roles.sql"
|
||||
).read_text("utf-8")
|
||||
|
||||
assert "\\getenv owner_password" in provisioning
|
||||
assert "\\getenv runtime_password" in provisioning
|
||||
assert "nosuperuser nocreatedb nocreaterole" in provisioning.lower()
|
||||
assert "modelforge_runtime" in provisioning
|
||||
assert "noinherit" in provisioning.lower()
|
||||
assert "pg_auth_members" in provisioning
|
||||
assert "revoke create, temporary on database %I from public" in provisioning
|
||||
assert "password 'modelforge'" not in provisioning.lower()
|
||||
assert "password 'postgres'" not in provisioning.lower()
|
||||
assert "\\getenv owner_password" in provisioning
|
||||
assert "\\getenv runtime_password" in provisioning
|
||||
assert "nosuperuser nocreatedb nocreaterole" in provisioning.lower()
|
||||
assert "modelforge_runtime" in provisioning
|
||||
assert "noinherit" in provisioning.lower()
|
||||
assert "pg_auth_members" in provisioning
|
||||
assert "password 'modelforge'" not in provisioning.lower()
|
||||
assert "password 'postgres'" not in provisioning.lower()
|
||||
|
||||
|
||||
def test_existing_cluster_provisioning_refuses_bootstrap_owner_before_mutation() -> None:
|
||||
provisioning = (
|
||||
ROOT / "deploy" / "postgres" / "provision-existing-1.2.1.sql"
|
||||
).read_text("utf-8")
|
||||
lowered = provisioning.lower()
|
||||
|
||||
refusal = lowered.index("oid = 10")
|
||||
first_role_mutation = lowered.index("create role")
|
||||
assert refusal < first_role_mutation
|
||||
assert "fresh cluster" in lowered
|
||||
assert "--no-owner --no-privileges" in lowered
|
||||
assert "pg_authid mutation" in lowered
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
||||
Reference in new issue
Block a user