Publish curated Unraid-AppOps-Gateway source from 451646fee806a47e3256731766980a05a262dcdd
This commit is contained in:
1 parent
532f3d9f26
commit
0a82153d95
43 files changed
+17722
-93
No files matched your search
@@ -8,6 +8,7 @@ runtime topology before it can mutate production.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import ipaddress
|
||||
@@ -27,6 +28,7 @@ from ..core.config import settings
|
||||
from ..core.redaction import redact_message
|
||||
from ..schemas.deployment import DeploymentPlanV1
|
||||
from ..schemas.forge_bootstrap import ForgeBootstrapPreflightV1
|
||||
from ..schemas.forge_bootstrap_apply import ForgeBootstrapApplyV1
|
||||
|
||||
_REQUEST_ID = re.compile(r"^[0-9a-f]{64}$")
|
||||
_MAX_DELIVERY_STATUS_BYTES = 512 * 1024
|
||||
@@ -35,6 +37,18 @@ _MAX_CONTROLLER_HEALTH_BYTES = 64 * 1024
|
||||
_WORKMESH_REVISION = re.compile(r"^[0-9a-f]{40}$")
|
||||
_WORKMESH_PREFLIGHT_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
||||
_WORKMESH_IDEMPOTENCY = re.compile(r"^[A-Za-z0-9._:-]{8,128}$")
|
||||
_FORGE_SECRET_DELIVERY_PATH = "/v1/appops/forge/bootstrap/secrets"
|
||||
_MAX_FORGE_SECRET_DELIVERY_BODY_BYTES = 16 * 1024
|
||||
_MAX_FORGE_SECRET_DELIVERY_RESPONSE_BYTES = 64 * 1024
|
||||
|
||||
|
||||
def _unique_json_object(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
|
||||
result: dict[str, Any] = {}
|
||||
for key, value in pairs:
|
||||
if key in result:
|
||||
raise ValueError("duplicate_json_key")
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
|
||||
class DeploymentBrokerClient:
|
||||
@@ -197,6 +211,8 @@ class DeploymentBrokerClient:
|
||||
value = decoded.get(field)
|
||||
if isinstance(value, str) and len(value) <= 256:
|
||||
rejected[field] = value
|
||||
elif field == "noMutation" and isinstance(value, bool):
|
||||
rejected[field] = value
|
||||
return rejected
|
||||
return {"status": str(decoded.get("status") or "ok"), **decoded}
|
||||
|
||||
@@ -314,6 +330,184 @@ class DeploymentBrokerClient:
|
||||
payload={"profile": profile.model_dump(mode="json")},
|
||||
)
|
||||
|
||||
def forge_bootstrap_apply(
|
||||
self,
|
||||
profile: ForgeBootstrapApplyV1,
|
||||
*,
|
||||
idempotency_key: str,
|
||||
secret: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Submit only the fixed, preflight-bound Forge first-install profile."""
|
||||
result = self._request(
|
||||
"POST",
|
||||
"/v1/appops/forge/bootstrap/apply",
|
||||
secret=secret,
|
||||
payload={
|
||||
"profile": profile.model_dump(mode="json"),
|
||||
"idempotencyKey": idempotency_key,
|
||||
},
|
||||
error_response_fields=frozenset({
|
||||
"apiVersion", "request", "repository", "revision", "operation",
|
||||
"workspaceImageDigest", "frontdoorImageDigest", "noMutation",
|
||||
}),
|
||||
)
|
||||
if result.get("status") == "preflight_changed":
|
||||
result.pop("reason", None)
|
||||
return result
|
||||
|
||||
def forge_secret_delivery(
|
||||
self,
|
||||
profile: ForgeBootstrapPreflightV1,
|
||||
*,
|
||||
config_bytes: bytes,
|
||||
oidc_client_secret: bytes,
|
||||
authentik_read_token: bytes,
|
||||
secret: str,
|
||||
) -> dict[str, Any]:
|
||||
"""Send the single fixed Forge credential bundle request.
|
||||
|
||||
Any response after transmission is treated as an unknown outcome unless
|
||||
it is a bounded, strict JSON object. Caller-side validation still owns
|
||||
the complete success contract and never echoes this internal response.
|
||||
"""
|
||||
configuration_error = self.configuration_error()
|
||||
if configuration_error is not None:
|
||||
return {
|
||||
"status": "missing_config",
|
||||
"reason": "forge_secret_delivery_broker_configuration_invalid",
|
||||
}
|
||||
if (
|
||||
not isinstance(secret, str)
|
||||
or len(secret) < 32
|
||||
or not secret.isascii()
|
||||
or not secret.isprintable()
|
||||
or not isinstance(config_bytes, bytes)
|
||||
or not 1 <= len(config_bytes) <= 8192
|
||||
or not isinstance(oidc_client_secret, bytes)
|
||||
or not 32 <= len(oidc_client_secret) <= 255
|
||||
or any(byte < 0x20 or byte > 0x7E for byte in oidc_client_secret)
|
||||
or not isinstance(authentik_read_token, bytes)
|
||||
or not 32 <= len(authentik_read_token) <= 256
|
||||
or any(byte < 0x21 or byte > 0x7E for byte in authentik_read_token)
|
||||
):
|
||||
return {"status": "missing_secret", "reason": "forge_secret_delivery_inputs_invalid"}
|
||||
|
||||
payload = {
|
||||
"apiVersion": "itworx.forge-secret-delivery/v1",
|
||||
"target": "itworx-forge",
|
||||
"profile": profile.model_dump(mode="json"),
|
||||
"configBase64": base64.b64encode(config_bytes).decode("ascii"),
|
||||
"oidcClientSecretBase64": base64.b64encode(oidc_client_secret).decode("ascii"),
|
||||
"authentikReadTokenBase64": base64.b64encode(authentik_read_token).decode("ascii"),
|
||||
}
|
||||
body = self._canonical_payload(payload)
|
||||
payload.clear()
|
||||
if len(body) > _MAX_FORGE_SECRET_DELIVERY_BODY_BYTES:
|
||||
return {"status": "missing_secret", "reason": "forge_secret_delivery_request_too_large"}
|
||||
|
||||
timestamp = str(int(time.time()))
|
||||
nonce = uuid.uuid4().hex
|
||||
path = _FORGE_SECRET_DELIVERY_PATH
|
||||
headers = {
|
||||
"Accept": "application/json",
|
||||
"Accept-Encoding": "identity",
|
||||
"Content-Type": "application/json",
|
||||
"X-ITWorx-Deployment-Timestamp": timestamp,
|
||||
"X-ITWorx-Deployment-Nonce": nonce,
|
||||
"X-ITWorx-Deployment-Signature": self._signature(
|
||||
secret, "POST", path, timestamp, nonce, body
|
||||
),
|
||||
}
|
||||
response_body = bytearray()
|
||||
try:
|
||||
with httpx.Client(
|
||||
timeout=self.timeout_seconds,
|
||||
verify=self._verify_option(),
|
||||
follow_redirects=False,
|
||||
) as client, client.stream(
|
||||
"POST",
|
||||
f"{self.base_url}{path}",
|
||||
content=body,
|
||||
headers=headers,
|
||||
) as response:
|
||||
if response.status_code != 200:
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_controller_rejected",
|
||||
}
|
||||
content_length = response.headers.get("content-length")
|
||||
if content_length is not None and (
|
||||
not content_length.isascii()
|
||||
or not content_length.isdecimal()
|
||||
or len(content_length) > 10
|
||||
or int(content_length) > _MAX_FORGE_SECRET_DELIVERY_RESPONSE_BYTES
|
||||
):
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_response_invalid",
|
||||
}
|
||||
for chunk in response.iter_bytes(chunk_size=16 * 1024):
|
||||
response_body.extend(chunk)
|
||||
if len(response_body) > _MAX_FORGE_SECRET_DELIVERY_RESPONSE_BYTES:
|
||||
response_body.clear()
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_response_invalid",
|
||||
}
|
||||
except Exception: # noqa: BLE001 - exception text can contain held credentials.
|
||||
response_body.clear()
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_transport_unknown",
|
||||
}
|
||||
|
||||
try:
|
||||
decoded = json.loads(
|
||||
bytes(response_body).decode("utf-8"),
|
||||
object_pairs_hook=_unique_json_object,
|
||||
)
|
||||
except (UnicodeError, ValueError, TypeError):
|
||||
response_body.clear()
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_response_invalid",
|
||||
}
|
||||
response_body.clear()
|
||||
if not isinstance(decoded, dict):
|
||||
return {
|
||||
"status": "outcome_unknown",
|
||||
"reason": "forge_secret_delivery_response_invalid",
|
||||
}
|
||||
return {"status": "response", "response": decoded}
|
||||
|
||||
def forge_bootstrap_resume(self, request_id: str, *, secret: str) -> dict[str, Any]:
|
||||
"""Resume only one recorded pre-migration credentials blocker."""
|
||||
if not _REQUEST_ID.fullmatch(request_id):
|
||||
return {"status": "invalid_request_id"}
|
||||
result = self._request(
|
||||
"POST",
|
||||
f"/v1/appops/forge/bootstrap/resume/{request_id}",
|
||||
secret=secret,
|
||||
payload={},
|
||||
error_response_fields=frozenset({
|
||||
"apiVersion", "request", "repository", "revision", "operation",
|
||||
"workspaceImageDigest", "frontdoorImageDigest", "noMutation",
|
||||
}),
|
||||
)
|
||||
if result.get("status") == "preflight_changed":
|
||||
result.pop("reason", None)
|
||||
return result
|
||||
|
||||
def forge_bootstrap_status(self, request_id: str, *, secret: str) -> dict[str, Any]:
|
||||
"""Read one fixed Forge first-install request; never submits mutations."""
|
||||
if not _REQUEST_ID.fullmatch(request_id):
|
||||
return {"status": "invalid_request_id"}
|
||||
return self._request(
|
||||
"GET",
|
||||
f"/v1/appops/forge/bootstrap/status/{request_id}",
|
||||
secret=secret,
|
||||
)
|
||||
|
||||
def enrollment_capabilities(self, *, secret: str) -> dict[str, Any]:
|
||||
"""Read the bootstrap-protected enrollment controller capability."""
|
||||
return self._request(
|
||||
|
||||
Reference in new issue
Block a user