"""RBC HTTPS transport, certificate validation, and resource-flow tests."""
from __future__ import annotations
import base64
import json
import ssl
import subprocess
from pathlib import Path
from typing import Any
import httpx
import pytest
from e2e.rbc.support import run_rbc
from e2e.rbs.support import create_resource
pytestmark = [pytest.mark.e2e, pytest.mark.rbc]
@pytest.fixture
def wrong_ca_cert(tmp_path: Path) -> Path:
"""Generate a CA that does not trust the E2E HTTPS server certificate."""
wrong_cert = tmp_path / "wrong-ca.crt"
wrong_key = tmp_path / "wrong-ca.key"
subprocess.run(
[
"openssl",
"req",
"-x509",
"-newkey",
"rsa:2048",
"-keyout",
str(wrong_key),
"-out",
str(wrong_cert),
"-days",
"1",
"-nodes",
"-subj",
"/CN=wrong-ca",
],
check=True,
capture_output=True,
)
return wrong_cert
def _assert_certificate_rejected(result: subprocess.CompletedProcess[str]) -> None:
"""Require a certificate-verification failure, not a generic connection failure."""
assert result.returncode != 0
diagnostic = f"{result.stdout}\n{result.stderr}".lower()
assert "connection refused" not in diagnostic, diagnostic
assert "connection reset" not in diagnostic, diagnostic
assert (
"certificate" in diagnostic
or "unknownissuer" in diagnostic
or "unknown issuer" in diagnostic
), diagnostic
def test_rbc_challenge_accepts_configured_ca(
rbc_binary: Path, https_rbc_tools_environment: Any, https_agent_config_path: Path
) -> None:
"""Use --cert with the real CA and verify the HTTPS challenge response."""
result = run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(https_rbc_tools_environment.ca_cert_path),
"--format",
"json",
"challenge",
"--agent-config",
str(https_agent_config_path),
)
payload = json.loads(result.stdout)
assert set(payload) == {"nonce"}
assert base64.b64decode(payload["nonce"], validate=True)
def test_rbc_rejects_wrong_ca(
rbc_binary: Path,
https_rbc_tools_environment: Any,
https_agent_config_path: Path,
wrong_ca_cert: Path,
) -> None:
"""Reject the HTTPS server when --cert points to an unrelated CA."""
result = run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(wrong_ca_cert),
"challenge",
"--agent-config",
str(https_agent_config_path),
check=False,
)
_assert_certificate_rejected(result)
def test_rbc_rejects_missing_ca(
rbc_binary: Path, https_rbc_tools_environment: Any, https_agent_config_path: Path
) -> None:
"""Reject the self-signed HTTPS server when --cert is omitted."""
result = run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"challenge",
"--agent-config",
str(https_agent_config_path),
check=False,
)
_assert_certificate_rejected(result)
def test_rbc_https_resource_flow(
rbc_binary: Path,
https_rbc_tools_environment: Any,
https_agent_config_path: Path,
rbc_key_material: Any,
tmp_path: Path,
) -> None:
"""Run challenge, evidence, token, and decrypted resource retrieval entirely over HTTPS."""
verify = https_rbc_tools_environment.ca_cert_path
tls_context = ssl.create_default_context(cafile=str(verify))
with httpx.Client(verify=tls_context, trust_env=False) as client:
uri, _, secret = create_resource(client, https_rbc_tools_environment)
challenge = json.loads(
run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(verify),
"--format",
"json",
"challenge",
"--agent-config",
str(https_agent_config_path),
).stdout
)["nonce"]
evidence = json.loads(
run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(verify),
"--format",
"json",
"collect-evidence",
"--agent-config",
str(https_agent_config_path),
"--nonce",
challenge,
"--attester-pubkey",
f"@{rbc_key_material.public_key_path}",
).stdout
)
evidence_path = tmp_path / "https-evidence.json"
evidence_path.write_text(json.dumps(evidence), encoding="utf-8")
token = json.loads(
run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(verify),
"--format",
"json",
"get-token",
"--agent-config",
str(https_agent_config_path),
"--evidence",
f"@{evidence_path}",
).stdout
)["token"]
resource = json.loads(
run_rbc(
rbc_binary,
https_rbc_tools_environment.base_url,
"--cert",
str(verify),
"--format",
"json",
"get-resource",
"--agent-config",
str(https_agent_config_path),
"--uri",
uri,
"--attest-token",
token,
"--private-key-file",
str(rbc_key_material.private_key_path),
).stdout
)
assert resource["uri"] == f"/rbs/v0/{uri}"
assert json.loads(base64.b64decode(resource["content"], validate=True)) == secret