Publish curated Unraid-AppOps-Gateway source from ad0a390e431166c3198a2ac3bec010c2b44f2dea

This commit is contained in:
Public Source Publisher committed 2026-10-02 09:56:13 +00:00
1 parent 29c1e3d5a1
commit 98d31477f9
35 files changed
+7264 -185

No files matched your search

+123 -4
View File
@@ -22,7 +22,12 @@ from ..connectors.nginx_proxy_manager import NginxProxyManagerConnector
from ..connectors.portainer import PortainerConnector
from ..core.time import utc_now
from ..db.models import AppSetting, Enrollment, EnrollmentJob, Policy
from ..schemas.enrollment import EnrollmentPlanV1, EnrollmentTrustConfigV1
from ..schemas.enrollment import (
LEGACY_APPDATA_ROOT,
MANAGED_DOCKER_APPDATA_ROOT,
EnrollmentPlanV1,
EnrollmentTrustConfigV1,
)
from .audit_logger import log_event
from .deployment_broker import DeploymentBrokerClient
from .enrollment_profiles import PROFILE_VERSION, profile_contract, profile_summary
@@ -40,6 +45,47 @@ _TERMINAL = {"ready", "failed", "compensation_required", "preflight_failed"}
_CONTROLLER_EVIDENCE = {"status", "targetId", "repository", "applicationId", "appdataPath"}
_PROXY_EVIDENCE = {"success", "status", "hostId", "hostname"}
_OIDC_EVIDENCE = {"success", "status", "applicationId", "providerId", "clientSecretCreated"}
_APPDATA_ROOT_STATUSES = {"ready", "needs_initialization", "unavailable"}
def _trusted_appdata_roots_readiness(
controller_capability: dict[str, Any],
) -> list[dict[str, str]]:
roots = (LEGACY_APPDATA_ROOT, MANAGED_DOCKER_APPDATA_ROOT)
unavailable = {root: "unavailable" for root in roots}
reported = controller_capability.get("availableTrustedAppdataRoots")
if isinstance(reported, list):
if len(reported) != len(roots):
return [{"root": root, "status": unavailable[root]} for root in roots]
statuses: dict[str, str] = {}
for item in reported:
if not isinstance(item, dict):
return [{"root": root, "status": unavailable[root]} for root in roots]
root = item.get("root")
status = item.get("status")
if (
not isinstance(root, str)
or root not in unavailable
or root in statuses
or not isinstance(status, str)
or status not in _APPDATA_ROOT_STATUSES
):
return [{"root": expected, "status": unavailable[expected]} for expected in roots]
statuses[root] = status
if set(statuses) != set(roots):
return [{"root": root, "status": unavailable[root]} for root in roots]
return [{"root": root, "status": statuses[root]} for root in roots]
# A legacy V1 controller reports only its configured root. It cannot attest
# independent managed-volume readiness, so only its exact legacy root can
# be marked ready through this compatibility path.
if "availableTrustedAppdataRoots" not in controller_capability:
if (
controller_capability.get("status") == "ready"
and controller_capability.get("trustedAppdataRoot") == LEGACY_APPDATA_ROOT
):
unavailable[LEGACY_APPDATA_ROOT] = "ready"
return [{"root": root, "status": unavailable[root]} for root in roots]
class EnrollmentError(ValueError):
@@ -135,6 +181,8 @@ class EnrollmentPlane:
"status": "needs_setup",
"blockers": ["enrollment_trust_not_configured"],
"configured": False,
"trustedAppdataRoot": LEGACY_APPDATA_ROOT,
"managedAppdataBackupAcknowledged": False,
"secretStore": storage,
}
return {
@@ -143,6 +191,7 @@ class EnrollmentPlane:
"configured": True,
"controllerIdentity": trust.controller_identity,
"trustedAppdataRoot": trust.trusted_appdata_root,
"managedAppdataBackupAcknowledged": trust.managed_appdata_backup_acknowledged,
"approvedNetworks": list(trust.approved_networks),
"allowedDomainSuffixes": list(trust.allowed_domain_suffixes),
"autonomousProfiles": list(trust.autonomous_profiles),
@@ -162,11 +211,43 @@ class EnrollmentPlane:
bootstrap_secret = get_secret(session, trust.bootstrap_secret_ref, touch=False)
if bootstrap_secret:
controller_capability = self.broker.enrollment_capabilities(secret=bootstrap_secret)
available_roots = _trusted_appdata_roots_readiness(controller_capability)
if trust is not None:
selected_root = next(
(
item
for item in available_roots
if item["root"] == trust.trusted_appdata_root
),
None,
)
controller_root_matches = bool(selected_root and selected_root.get("status") == "ready")
else:
controller_root_matches = False
broker_ready = bool(
bootstrap
and self.broker.is_configured()
and controller_capability.get("status") == "ready"
and controller_root_matches
)
controller_managed_storage = controller_capability.get("managedStorage")
if not isinstance(controller_managed_storage, dict):
controller_managed_storage = {}
if trust is None or trust.trusted_appdata_root != MANAGED_DOCKER_APPDATA_ROOT:
managed_storage_status = "not_selected"
managed_storage_blocker = ""
elif not trust.managed_appdata_backup_acknowledged:
managed_storage_status = "blocked"
managed_storage_blocker = "managed_appdata_backup_acknowledgement_required"
elif controller_root_matches and controller_managed_storage.get("status") == "ready":
managed_storage_status = "ready"
managed_storage_blocker = ""
elif controller_managed_storage.get("initializationAvailable") is True:
managed_storage_status = "initialization_required"
managed_storage_blocker = "managed_appdata_initialization_required"
else:
managed_storage_status = "unavailable"
managed_storage_blocker = "managed_appdata_volume_unavailable"
npm_ready = self.npm.is_configured()
oidc_configured = bool(
trust
@@ -193,9 +274,27 @@ class EnrollmentPlane:
"policyProvisioning": item(configured, "policy_template_unavailable"),
"rollback": item(broker_ready, "deployment_executor_unavailable"),
"verification": item(broker_ready, "deployment_executor_unavailable"),
"availableTrustedAppdataRoots": available_roots,
"managedStorage": {
"status": managed_storage_status,
"blockerCode": managed_storage_blocker,
"root": MANAGED_DOCKER_APPDATA_ROOT,
"backupScope": "dockerRootDir",
"backupAcknowledged": bool(
trust and trust.managed_appdata_backup_acknowledged
),
},
"controller": {
"status": str(controller_capability.get("status") or "unavailable"),
"reason": str(controller_capability.get("reason") or "deployment_executor_unavailable"),
"status": "ready" if broker_ready else "unavailable",
"reason": (
""
if broker_ready
else str(controller_capability.get("reason") or (
"trusted_appdata_root_mismatch"
if controller_capability.get("status") == "ready" and not controller_root_matches
else "deployment_executor_unavailable"
))
),
},
"profiles": [profile_summary(name) for name in ("internal-webapp", "internal-webapp-oidc", "internal-service", "repopulse-authenticated")],
}
@@ -233,6 +332,7 @@ class EnrollmentPlane:
"container_name": plan.target.container_name,
"compose_file": plan.target.compose_file,
"appdata_path": plan.appdata_path,
"trusted_appdata_root": plan.trusted_appdata_root,
"data_path": plan.data_path,
"runtime_uid": plan.storage.runtime_uid,
"runtime_gid": plan.storage.runtime_gid,
@@ -264,6 +364,17 @@ class EnrollmentPlane:
checks.append(_check("network", "passed", "Requested Docker network is within the trusted profile boundary."))
else:
checks.append(_check("network_unavailable", "blocked", "Requested Docker network is not approved for enrollment."))
# RepoPulse is an established, fixed legacy-root exception; the
# operator's selected root applies to other new targets only.
expected_appdata_root = (
LEGACY_APPDATA_ROOT
if plan.profile == "repopulse-authenticated"
else trust.trusted_appdata_root
)
if plan.trusted_appdata_root == expected_appdata_root:
checks.append(_check("trusted_appdata_root", "passed", "Requested appdata root matches its fixed profile trust boundary."))
else:
checks.append(_check("trusted_appdata_root_mismatch", "blocked", "Requested appdata root does not match the explicit operator trust boundary."))
if plan.profile in trust.autonomous_profiles:
checks.append(_check("autonomous_profile", "passed", "Deployment profile is approved for autonomous enrollment."))
else:
@@ -397,7 +508,15 @@ class EnrollmentPlane:
checks.append(_check("secret_store", "passed" if storage_ready else "blocked", "Production-grade write-only secret storage is ready." if storage_ready else "Enrollment requires APPOPS_SECRET_KEY from a protected environment variable or file; the development fallback is not permitted."))
if trust:
checks.append(_check("controller_bootstrap_secret", "passed" if has_secret(session, trust.bootstrap_secret_ref) else "blocked", "Controller bootstrap secret is available by reference." if has_secret(session, trust.bootstrap_secret_ref) else "Controller bootstrap secret reference is not configured."))
if has_secret(session, trust.bootstrap_secret_ref):
expected_appdata_root = (
LEGACY_APPDATA_ROOT
if plan.profile == "repopulse-authenticated"
else trust.trusted_appdata_root
)
root_matches_trust = plan.trusted_appdata_root == expected_appdata_root
if not root_matches_trust:
checks.append(_check("controller_target", "blocked", "Controller preflight was skipped because the requested appdata root is outside the profile trust boundary."))
elif has_secret(session, trust.bootstrap_secret_ref):
controller = self.broker.enrollment_preflight(
self._controller_payload(plan, enrollment_id="enr-00000000000000000000"),
secret=get_secret(session, trust.bootstrap_secret_ref, touch=False) or "",