Accept systemd credential delivery and clarify manual K1 control

This commit is contained in:
DCCONSTRUCTIONS
2026-09-07 14:44:46 +03:00
parent 102e93796b
commit a93f1f1b8b
19 changed files with 402 additions and 31 deletions
@@ -191,14 +191,31 @@ class LinuxApplicationAuthorityLoader:
os.environ.get("CREDENTIALS_DIRECTORY", "/run/credentials/mission-core-k1.service")
)
buffer = bytearray()
directory_fd = None
try:
fd = os.open(directory / "k1-application", os.O_RDONLY | os.O_NOFOLLOW)
directory_fd = os.open(directory, os.O_RDONLY | os.O_DIRECTORY | os.O_NOFOLLOW)
directory_info = os.fstat(directory_fd)
if (
directory_info.st_uid not in {0, os.geteuid()}
or directory_info.st_mode & 0o027
):
raise ValueError("Invalid credential directory")
fd = os.open(
"k1-application", os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK,
dir_fd=directory_fd,
)
with os.fdopen(fd, "rb") as stream:
info = os.fstat(stream.fileno())
# systemd prefers root ownership + a service-UID read ACL.
# Its ACL mask appears as group-read in st_mode (0440).
# The trusted root-owned directory/file and kernel access check
# own that authorization; do not mistake the mask for exposure.
acl_delivered = info.st_uid == 0 and directory_info.st_uid == 0
if (
not stat.S_ISREG(info.st_mode)
or info.st_uid != os.geteuid()
or info.st_mode & 0o077
or info.st_uid not in {0, os.geteuid()}
or info.st_mode & (0o037 if acl_delivered else 0o077)
or info.st_mode & 0o111
):
raise ValueError("Invalid credential permissions")
buffer.extend(stream.read(1025))
@@ -207,8 +224,10 @@ class LinuxApplicationAuthorityLoader:
return ApplicationControlAuthority(openapi_key=buffer.decode("ascii").strip())
except (OSError, ValueError, UnicodeError):
raise ApplicationAuthorityLoadError(
"Служебный ключ K1 не установлен на БК.",
"Службе K1 на БК не удалось загрузить служебный ключ.",
reason_code="application_authority_unavailable",
) from None
finally:
if directory_fd is not None:
os.close(directory_fd)
buffer[:] = b"\0" * len(buffer)
@@ -29,6 +29,7 @@ from .facade import (
_validate_installed_compatibility_profile,
)
from .linux_host import LinuxApplicationAuthorityLoader, LinuxWifiAssociationProbe, wifi_networks
from .protocol.application_authority import ApplicationAuthorityLoadError
ATTESTATION = {
"firmware_version": "3.0.2",
@@ -94,11 +95,20 @@ def node_operation_id(plugin_id: str | None) -> str | None:
class NodeBridge:
def __init__(self, repository_root: Path, *, service=None):
self.rerun = NodeRerunHub()
self.application_authority_available = None
if service is None:
_validate_installed_compatibility_profile(repository_root)
loader = LinuxApplicationAuthorityLoader()
# systemd's credential mount is immutable for this service lifetime.
# This startup check proves loading, not K1 authentication or control.
try:
loader.load()
self.application_authority_available = True
except ApplicationAuthorityLoadError:
self.application_authority_available = False
service = XgridsK1CompatibilityService(
repository_root,
application_authority_loader=LinuxApplicationAuthorityLoader(),
application_authority_loader=loader,
host_wifi_association_probe=LinuxWifiAssociationProbe(),
visualization_bridge_factory=self.rerun.create,
)
@@ -108,7 +118,10 @@ class NodeBridge:
async def state(self) -> dict:
snapshot = await self.invoke("state.read", {}, "state-read")
return self.project(snapshot)
result = self.project(snapshot)
if self.application_authority_available is not None:
result["application_authority_available"] = self.application_authority_available
return result
@staticmethod
def project(snapshot: dict) -> dict:
@@ -343,7 +356,11 @@ def create_app(repository_root: Path):
raise ValueError("Command expired")
result = await sensor.execute(command, request.headers["X-Node-Id"])
return {"state": "complete", "result": result}
except Exception:
except Exception as error:
logging.getLogger(__name__).warning(
"K1 sensor operation failed: exception=%s chain=%s",
type(error).__name__, failure_locations(error),
)
return {
"state": "unknown",
"error": "Действие K1 не подтверждено. Обновите состояние устройства.",
@@ -64,6 +64,7 @@ def project_sensor(snapshot, node_id):
"opened_at": session["opened_at"],
}
control = snapshot.get("application_control_session") or {}
attempt = snapshot.get("connection_attempt") or {}
return {
"id": identifier,
"name": "XGRIDS K1",
@@ -90,6 +91,12 @@ def project_sensor(snapshot, node_id):
"phase": control.get("state"),
"can_start": lifecycle.get("ready_to_start", False),
"can_stop": control.get("state") in {"start-requested", "initializing", "scanning"},
"can_verify": any(action in lifecycle.get("allowed_actions", []) for action in (
"verify-control-read-only", "observe-current-device-network",
"observe-configured-device-network", "observe-fresh-device-network",
)),
"network_applied": connected or attempt.get("phase") == "network_applied",
"reason_code": None if connected else attempt.get("public_error_code"),
"acquisition_id": acquisition.get("acquisition_id"),
},
"live_settings": snapshot.get("viewer_settings", {}),