GuestOps/tests/production_smoke.py

63 lines
2.8 KiB
Python

"""Exercise disposable CI containers through the host's trusted proxy address.
The forwarded HTTPS header simulates Nginx TLS termination; this is never run
against an existing hotel database. Cookie values and credentials are not logged.
"""
import json
import os
import sys
from http.cookies import SimpleCookie
from urllib.request import Request, urlopen
from urllib.error import HTTPError
cookies = SimpleCookie()
csrf = ""
def request(path, method="GET", data=None, expected=200):
headers = {"X-Forwarded-Proto": "https", "Content-Type": "application/json",
"Cookie": "; ".join(f"{k}={v.value}" for k, v in cookies.items()),
"X-CSRF-TOKEN": csrf}
req = Request("http://127.0.0.1:8080" + path, method=method, headers=headers,
data=json.dumps(data).encode() if data is not None else None)
try:
response = urlopen(req, timeout=15)
except HTTPError as error:
response = error
assert response.status == expected, f"{method} {path}: {response.status}, expected {expected}"
for value in response.headers.get_all("Set-Cookie", []):
parsed = SimpleCookie(value)
for cookie in parsed.values():
assert cookie["secure"] and cookie["httponly"], "Authentication cookies must be secure and HttpOnly"
cookies.load(value)
body = response.read().decode()
return json.loads(body) if "application/json" in response.headers.get("Content-Type", "") else body
assert "root" in request("/"), "Container must serve the built React interface"
request("/api/hotel", expected=401)
session = request("/api/session")
assert session["preview"] is False and session["user"] is None
csrf = session["csrfToken"]
request("/api/auth/login", "POST", {"email": os.environ["BOOTSTRAP_EMAIL"], "password": os.environ["BOOTSTRAP_PASSWORD"]})
session = request("/api/session")
assert session["user"]["role"] == "Owner"
csrf = session["csrfToken"]
auto_status = request("/api/auto-replies/status")
assert auto_status["liveConfigured"] is False
request("/api/auto-replies/mode", "PUT", {"mode": "Live", "version": 0, "acceptanceConfirmed": True}, expected=400)
payment_status = request("/api/payments/status")
assert payment_status["configured"] is False and payment_status["createsConfigured"] is False
assert "securityKey" not in payment_status
request("/api/payments/controls", "PUT", {"version": 0, "enabled": True}, expected=400)
assert request("/api/payments/requests") == []
hotel = request("/api/hotel")
if "--read" in sys.argv:
assert hotel["signature"] == "Persisted across container restart"
else:
hotel["signature"] = "Persisted across container restart"
request("/api/hotel", "PUT", hotel)
request("/api/auth/logout", "POST")
request("/api/hotel", expected=401)
print("Production smoke checks passed: built UI, secure cookies, owner login, MongoDB settings and logout.")