diff --git a/apps/node-agent/internal/node/environment-profile.json b/apps/node-agent/internal/node/environment-profile.json index 578addb..0d0a983 100644 --- a/apps/node-agent/internal/node/environment-profile.json +++ b/apps/node-agent/internal/node/environment-profile.json @@ -1,6 +1,6 @@ { "schema": "missioncore.node.environment/v1", - "revision": "ubuntu-24.04-amd64/1", + "revision": "ubuntu-24.04-amd64/2", "steps": [ {"id":"platform","label":"Проверка системы","description":"Операционная система и архитектура БК","requires":[]}, {"id":"packages","label":"Установка системных пакетов","description":"OpenSSH Server и зависимости окружения","requires":["platform"]}, diff --git a/apps/node-agent/packaging/build_deb.py b/apps/node-agent/packaging/build_deb.py index e3fe8b0..edddc7f 100644 --- a/apps/node-agent/packaging/build_deb.py +++ b/apps/node-agent/packaging/build_deb.py @@ -13,7 +13,7 @@ import tarfile ROOT = Path(__file__).resolve().parents[1] -VERSION = "0.4.0" +VERSION = "0.4.1" BRAND_SHA256 = "8bfee8ca9f98e0db48d98aae3af4b32493b8593e18b064a0239d513d824182af" diff --git a/apps/node-agent/packaging/environment_helper.py b/apps/node-agent/packaging/environment_helper.py index 85df8fd..5c34852 100644 --- a/apps/node-agent/packaging/environment_helper.py +++ b/apps/node-agent/packaging/environment_helper.py @@ -38,10 +38,16 @@ def command(argv, *, timeout=15): def trusted_directory(path, mode=0o755): + created = not path.exists() and not path.is_symlink() path.mkdir(mode=mode, parents=True, exist_ok=True) info = path.lstat() if not stat.S_ISDIR(info.st_mode) or info.st_uid != 0 or info.st_mode & 0o022: raise SetupError("Каталог настройки имеет неподходящие права. Переустановите пакет Node через интерфейс системы.") + # umask 0077 must protect working files, but this nonsensitive report and + # newly created configuration directories must be traversable by readers. + # The only existing directory repaired here is our dedicated report store. + if created or path == STATE: + path.chmod(mode) def publish(path, data): diff --git a/apps/node-agent/packaging/test_environment_helper.py b/apps/node-agent/packaging/test_environment_helper.py index 92dcfcb..acfd543 100644 --- a/apps/node-agent/packaging/test_environment_helper.py +++ b/apps/node-agent/packaging/test_environment_helper.py @@ -1,6 +1,8 @@ """Workflow acceptance boundaries without touching the host OS or credentials.""" import copy import json +import os +from types import SimpleNamespace from pathlib import Path import subprocess import tempfile @@ -98,6 +100,23 @@ class EnvironmentWorkflowTests(unittest.TestCase): self.assertTrue(target.is_symlink()) self.assertEqual(template.read_bytes(), b'owned') + def test_restrictive_umask_does_not_hide_report_and_existing_report_dir_is_repaired(self): + with tempfile.TemporaryDirectory() as directory: + target = Path(directory)/'report' + with patch.object(helper, 'STATE', target), patch.object(Path, 'lstat', autospec=True, side_effect=lambda path: SimpleNamespace(st_uid=0, st_mode=os.stat(path).st_mode)): + previous = os.umask(0o077) + try: + helper.trusted_directory(target) + self.assertEqual(target.stat().st_mode & 0o777, 0o755) + target.chmod(0o700) + helper.trusted_directory(target) + self.assertEqual(target.stat().st_mode & 0o777, 0o755) + foreign = Path(directory)/'foreign' + foreign.mkdir(mode=0o700) + helper.trusted_directory(foreign) + self.assertEqual(foreign.stat().st_mode & 0o777, 0o700) + finally: os.umask(previous) + def test_delayed_service_start_retries_only_readiness(self): with patch.object(helper, 'probe_node', side_effect=[OSError('not listening'), {}]) as read, patch.object(helper.time, 'sleep'), patch.object(helper, 'command') as mutation: helper.wait_for_node() diff --git a/apps/node-agent/ui/src/EnvironmentView.tsx b/apps/node-agent/ui/src/EnvironmentView.tsx index 78e34ea..3af1bcb 100644 --- a/apps/node-agent/ui/src/EnvironmentView.tsx +++ b/apps/node-agent/ui/src/EnvironmentView.tsx @@ -14,11 +14,11 @@ export function EnvironmentView({environment,failure,success}: {environment:Retu return
Сконфигурируйте окружение при первом запуске или повторите проверку после изменений. Приложение установит нужные пакеты, настроит службы и получит системные сведения. Вход в частную сеть и доверенный SSH-ключ подтверждаются ниже.
- + {!environmentSetupAvailable()&&Настройка запускается из установленного приложения на БК.
} {pending&&(!value?.run||value.run.state!=="running")&&Сведения о настройке недоступны. Обновите страницу.
:<> - {!value.available&&Не удалось прочитать результат предыдущей настройки. Запустите настройку, чтобы заново проверить окружение.
} + {!value.available&&Журнал предыдущего запуска недоступен. Нажмите «Сконфигурировать» — приложение восстановит доступ и выполнит этапы заново.
}