Initial curated ITWorx_MCP_Hub source from 368fba691ea8d23403b4d56b53b5ec670d7c5020
This commit is contained in:
commit
cb5be898ea
663 files changed
+82674
No files matched your search
@@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fail closed unless the live router reads the operator's revocation file.
|
||||
|
||||
Run this on the Docker host before minting or revoking a Fleet Ops demo token.
|
||||
It reads Docker mount metadata and file metadata only; it never reads a token,
|
||||
signing key, or revocation-file contents.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
ROUTER_DIRECTORY = "/etc/itworx"
|
||||
ROUTER_DESTINATION = ROUTER_DIRECTORY + "/demo-token-revocations.json"
|
||||
|
||||
|
||||
def validate_mount(mounts: list[dict[str, Any]], expected_host_file: Path) -> dict[str, object]:
|
||||
if not expected_host_file.is_absolute():
|
||||
raise ValueError("expected host file must be an absolute path")
|
||||
matching = [mount for mount in mounts if mount.get("Destination") == ROUTER_DIRECTORY]
|
||||
if len(matching) != 1:
|
||||
raise ValueError("router must have exactly one demo-token revocation mount")
|
||||
source = Path(str(matching[0].get("Source", "")))
|
||||
if source != expected_host_file.parent:
|
||||
raise ValueError("router revocation directory mount does not match the operator host file")
|
||||
try:
|
||||
metadata = expected_host_file.stat()
|
||||
except OSError as exc:
|
||||
raise ValueError("operator revocation file is missing") from exc
|
||||
if not stat.S_ISREG(metadata.st_mode):
|
||||
raise ValueError("operator revocation file is not a regular file")
|
||||
mode = stat.S_IMODE(metadata.st_mode)
|
||||
# The operator command runs on Tower (Linux). Windows does not expose
|
||||
# NTFS ACLs through POSIX mode bits, so local unit tests cannot make this
|
||||
# assertion meaningful there.
|
||||
if os.name != "nt" and mode != 0o600:
|
||||
raise ValueError("operator revocation file mode must be exactly 0600")
|
||||
if matching[0].get("RW") is not False:
|
||||
raise ValueError("router revocation mount must be read-only")
|
||||
return {
|
||||
"status": "pass",
|
||||
"containerDestination": ROUTER_DESTINATION,
|
||||
"hostFile": str(expected_host_file),
|
||||
"mode": f"{mode:04o}",
|
||||
"readOnly": True,
|
||||
}
|
||||
|
||||
|
||||
def inspect_mounts(router_container: str) -> list[dict[str, Any]]:
|
||||
result = subprocess.run( # noqa: S603
|
||||
["docker", "inspect", router_container, "--format", "{{json .Mounts}}"], # noqa: S607
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
raise ValueError("could not inspect router container")
|
||||
try:
|
||||
mounts = json.loads(result.stdout)
|
||||
except json.JSONDecodeError as exc:
|
||||
raise ValueError("router mount metadata is invalid") from exc
|
||||
if not isinstance(mounts, list) or not all(isinstance(item, dict) for item in mounts):
|
||||
raise ValueError("router mount metadata is invalid")
|
||||
return mounts
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--router-container", required=True)
|
||||
parser.add_argument("--expected-host-file", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
try:
|
||||
report = validate_mount(inspect_mounts(args.router_container), args.expected_host_file)
|
||||
except ValueError as exc:
|
||||
print(json.dumps({"status": "fail", "reason": str(exc)}, sort_keys=True))
|
||||
return 1
|
||||
print(json.dumps(report, sort_keys=True))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in new issue
Block a user