Initial commit: SHARED library with LFS for binary assets
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from aiohttp.test_utils import TestClient, TestServer
|
||||
|
||||
from relay_gateway.keys import KeyStore, hash_token
|
||||
from relay_gateway.channels import build_channels
|
||||
from relay_gateway.gateway import create_app
|
||||
|
||||
|
||||
def _keyfile(tmp_path: Path, tokens: dict[str, dict]) -> Path:
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
kf.write_text(
|
||||
json.dumps({hash_token(t): m for t, m in tokens.items()}), encoding="utf-8"
|
||||
)
|
||||
return kf
|
||||
|
||||
|
||||
async def _client(tmp_path, tokens, *, tss_upstream=None) -> TestClient:
|
||||
kf = _keyfile(tmp_path, tokens)
|
||||
channels = build_channels(tmp_path, sre_upstream="http://127.0.0.1:1", tss_upstream=tss_upstream)
|
||||
app = create_app(key_store=KeyStore(kf), channels=channels)
|
||||
client = TestClient(TestServer(app))
|
||||
await client.start_server()
|
||||
return client
|
||||
|
||||
|
||||
async def test_health_is_open(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "all"}})
|
||||
resp = await client.get("/health")
|
||||
assert resp.status == 200
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_missing_token_is_401(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "sre"}})
|
||||
resp = await client.get("/api/sre/info")
|
||||
assert resp.status == 401
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_sqb_key_denied_tss_is_403(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "sre"}})
|
||||
resp = await client.get("/api/tss/info", headers={"Authorization": "Bearer k"})
|
||||
assert resp.status == 403
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_tss_proxy_501_when_no_upstream(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "tss"}})
|
||||
resp = await client.get("/api/tss/info", headers={"Authorization": "Bearer k"})
|
||||
assert resp.status == 501
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_tss_proxy_not_501_with_upstream(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "tss"}},
|
||||
tss_upstream="http://127.0.0.1:6100")
|
||||
resp = await client.get("/api/tss/info", headers={"Authorization": "Bearer k"})
|
||||
assert resp.status != 501 # proxied (likely 502 no-connection in test, never 501)
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_whoami_returns_grant(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "cn", "level": "sre"}})
|
||||
resp = await client.get("/api/whoami", headers={"Authorization": "Bearer k"})
|
||||
assert resp.status == 200
|
||||
body = await resp.json()
|
||||
assert body == {"name": "cn", "level": "sre", "channels": ["sre"]}
|
||||
await client.close()
|
||||
|
||||
|
||||
async def test_ws_rejects_bad_token(tmp_path):
|
||||
client = await _client(tmp_path, {"k": {"name": "n", "level": "tss"}})
|
||||
ws = await client.ws_connect("/ws/sre", headers={"Authorization": "Bearer k"})
|
||||
msg = await ws.receive()
|
||||
assert msg.type.name in {"CLOSE", "CLOSED", "CLOSING"}
|
||||
await client.close()
|
||||
@@ -0,0 +1,68 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from relay_gateway.keys import KeyStore, hash_token, can_access, CHANNELS_FOR_LEVEL
|
||||
|
||||
|
||||
def _write(path: Path, tokens: dict[str, dict]) -> None:
|
||||
body = {hash_token(tok): meta for tok, meta in tokens.items()}
|
||||
path.write_text(json.dumps(body), encoding="utf-8")
|
||||
|
||||
|
||||
def test_resolve_returns_grant_with_derived_channels(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"sekret": {"name": "cn-axbot", "level": "sre"}})
|
||||
store = KeyStore(kf)
|
||||
grant = store.resolve("sekret")
|
||||
assert grant is not None
|
||||
assert grant.name == "cn-axbot"
|
||||
assert grant.level == "sre"
|
||||
assert grant.channels == ("sre",)
|
||||
|
||||
|
||||
def test_resolve_unknown_token_is_none(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"sekret": {"name": "x", "level": "all"}})
|
||||
store = KeyStore(kf)
|
||||
assert store.resolve("nope") is None
|
||||
|
||||
|
||||
def test_all_level_grants_both_channels(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"k": {"name": "internal", "level": "all"}})
|
||||
grant = KeyStore(kf).resolve("k")
|
||||
assert grant is not None
|
||||
assert set(grant.channels) == {"sre", "tss"}
|
||||
|
||||
|
||||
def test_can_access_enforces_channel(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"k": {"name": "t", "level": "tss"}})
|
||||
grant = KeyStore(kf).resolve("k")
|
||||
assert grant is not None
|
||||
assert can_access(grant, "tss") is True
|
||||
assert can_access(grant, "sre") is False
|
||||
|
||||
|
||||
def test_hot_reload_on_mtime_change(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"k": {"name": "t", "level": "sre"}})
|
||||
store = KeyStore(kf)
|
||||
assert store.resolve("k").level == "sre"
|
||||
import os, time
|
||||
time.sleep(0.01)
|
||||
_write(kf, {"k": {"name": "t", "level": "tss"}})
|
||||
os.utime(kf, None)
|
||||
assert store.resolve("k").level == "tss"
|
||||
|
||||
|
||||
def test_missing_file_resolves_none(tmp_path):
|
||||
store = KeyStore(tmp_path / "absent.json")
|
||||
assert store.resolve("anything") is None
|
||||
|
||||
|
||||
def test_bad_level_is_skipped(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
_write(kf, {"k": {"name": "t", "level": "bogus"}})
|
||||
assert KeyStore(kf).resolve("k") is None
|
||||
assert "bogus" not in CHANNELS_FOR_LEVEL
|
||||
@@ -0,0 +1,29 @@
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from relay_gateway.manage_keys import add_key, list_keys, revoke
|
||||
from relay_gateway.keys import hash_token
|
||||
|
||||
|
||||
def test_add_key_writes_hashed_entry(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
token = add_key(kf, name="cn", level="sre")
|
||||
body = json.loads(kf.read_text())
|
||||
assert hash_token(token) in body
|
||||
assert body[hash_token(token)] == {"name": "cn", "level": "sre"}
|
||||
|
||||
|
||||
def test_add_key_rejects_bad_level(tmp_path):
|
||||
with pytest.raises(ValueError):
|
||||
add_key(tmp_path / "k.json", name="x", level="bogus")
|
||||
|
||||
|
||||
def test_revoke_removes_by_name(tmp_path):
|
||||
kf = tmp_path / "relay_keys.json"
|
||||
add_key(kf, name="cn", level="sre")
|
||||
add_key(kf, name="keep", level="tss")
|
||||
removed = revoke(kf, "cn")
|
||||
assert removed == 1
|
||||
names = {e["name"] for e in list_keys(kf)}
|
||||
assert names == {"keep"}
|
||||
Reference in New Issue
Block a user