From b21498e2affdb22b788b9b5739f099e488a161f7 Mon Sep 17 00:00:00 2001 From: Niall Byrne <9848926+niall-byrne@users.noreply.github.com> Date: Mon, 4 Mar 2024 16:43:50 +0000 Subject: [PATCH] feat(INSTALLER): run processes as pi_portal user --- packaging/debian/assets/debian/postinst | 9 ++++++--- pi_portal/config.py | 11 ++++++++--- .../installation/steps/step_configure_motion.py | 3 ++- .../steps/step_initialize_data_paths.py | 2 ++ .../steps/tests/test_step_configure_motion.py | 17 ++++++++++++++++- .../tests/test_step_initialize_data_paths.py | 2 ++ pi_portal/installation/templates/__init__.py | 8 +++++--- .../installation/templates/logzio/filebeat.yml | 2 +- .../templates/supervisor/supervisord.conf | 8 ++++++-- 9 files changed, 48 insertions(+), 14 deletions(-) diff --git a/packaging/debian/assets/debian/postinst b/packaging/debian/assets/debian/postinst index 52b6daee..83199e05 100755 --- a/packaging/debian/assets/debian/postinst +++ b/packaging/debian/assets/debian/postinst @@ -4,16 +4,19 @@ set -eo pipefail PACKAGE_USER="pi_portal" -gpio_access() { +groups() { if grep -q gpio /etc/group; then usermod -a -G gpio "${PACKAGE_USER}" fi + if grep -q video /etc/group; then + usermod -a -G video "${PACKAGE_USER}" + fi } permissions() { local FILEPATH - FILEPATH_LIST=("/opt/venvs/pi_portal" "/usr/bin/portal" "/var/lib/motion") + FILEPATH_LIST=("/opt/venvs/pi_portal" "/usr/bin/filebeat" "/usr/bin/portal" "/var/lib/motion") for FILEPATH in "${FILEPATH_LIST[@]}"; do chown -R "${PACKAGE_USER}":"${PACKAGE_USER}" "${FILEPATH}" @@ -28,8 +31,8 @@ users() { main() { users + groups permissions - gpio_access } main "$@" diff --git a/pi_portal/config.py b/pi_portal/config.py index ce9cb7c8..f5434550 100644 --- a/pi_portal/config.py +++ b/pi_portal/config.py @@ -21,9 +21,6 @@ CRON_INTERVAL_QUEUE_METRICS = 60 * 30 CRON_INTERVAL_VIDEO_UPLOAD = 60 * 10 -FILE_BEAT_BINARY = os.getenv("PI_PORTAL_FILEBEAT_LOCATION", "/usr/bin/filebeat") -FILE_BEAT_CONFIG = "/etc/filebeat/filebeat.yml" - LOG_FILE_BASE_FOLDER = "/var/log/pi_portal" LOG_FILE_CAMERA = f"{LOG_FILE_BASE_FOLDER}/pi_portal.camera.log" LOG_FILE_CONTACT_SWITCH_MONITOR = ( @@ -50,7 +47,15 @@ "queue_videos", ) PATH_CAMERA_BINARY = "/usr/bin/motion" +PATH_CAMERA_CONFIG = "/etc/motion/motion.yml" PATH_CAMERA_CONTENT = "/var/lib/motion" +PATH_FILEBEAT_BINARY = os.getenv( + "PI_PORTAL_FILEBEAT_LOCATION", + "/usr/bin/filebeat", +) +PATH_FILEBEAT_CONFIG = "/etc/filebeat/filebeat.yml" +PATH_FILEBEAT_CONTENT = "/var/lib/filebeat" +PATH_SUPERVISOR_CONFIG = "/etc/supervisor/supervisord.conf" PATH_SUPERVISOR_SOCKET = "/var/run/supervisor.sock" PATH_TASKS_SERVICE_DATABASES = os.path.join( PI_PORTAL_INSTALL_LOCATION, diff --git a/pi_portal/installation/steps/step_configure_motion.py b/pi_portal/installation/steps/step_configure_motion.py index 7504d178..a864ad18 100644 --- a/pi_portal/installation/steps/step_configure_motion.py +++ b/pi_portal/installation/steps/step_configure_motion.py @@ -2,6 +2,7 @@ from typing import List +from pi_portal import config from pi_portal.installation.templates import config_file, motion_templates from pi_portal.modules.configuration import state from .bases import render_templates_step @@ -35,7 +36,7 @@ def generate_camera_templates(self) -> None: source='motion/camera.conf', destination=f'/etc/motion/camera{index}.conf', permissions="600", - user="root", + user=config.PI_PORTAL_USER, ) camera_config_file.context["CAMERA"] = camera camera_config_file.context["CAMERA"]["NAME"] = f"CAMERA-{index}" diff --git a/pi_portal/installation/steps/step_initialize_data_paths.py b/pi_portal/installation/steps/step_initialize_data_paths.py index d6f52d63..e65e4d77 100644 --- a/pi_portal/installation/steps/step_initialize_data_paths.py +++ b/pi_portal/installation/steps/step_initialize_data_paths.py @@ -13,6 +13,8 @@ class StepInitializeDataPaths(base_step.StepBase): data_paths = [ config.PATH_ARCHIVAL_QUEUE_LOG_UPLOAD, config.PATH_ARCHIVAL_QUEUE_VIDEO_UPLOAD, + config.PATH_CAMERA_CONTENT, + config.PATH_FILEBEAT_CONTENT, config.PATH_TASKS_SERVICE_DATABASES, ] diff --git a/pi_portal/installation/steps/tests/test_step_configure_motion.py b/pi_portal/installation/steps/tests/test_step_configure_motion.py index 6f80d7d2..990cf5e7 100644 --- a/pi_portal/installation/steps/tests/test_step_configure_motion.py +++ b/pi_portal/installation/steps/tests/test_step_configure_motion.py @@ -5,8 +5,10 @@ from unittest import mock import pytest +from pi_portal import config from pi_portal.installation.templates import config_file, motion_templates from pi_portal.modules.configuration import state +from ..bases import base_step, render_templates_step from ..step_configure_motion import StepConfigureMotion @@ -21,6 +23,19 @@ def test__initialize__attrs( assert isinstance(step_configure_motion_instance.log, logging.Logger) assert step_configure_motion_instance.templates == motion_templates + def test__initialize__inheritance( + self, + step_configure_motion_instance: StepConfigureMotion, + ) -> None: + assert isinstance( + step_configure_motion_instance, + base_step.StepBase, + ) + assert isinstance( + step_configure_motion_instance, + render_templates_step.RenderTemplateStepBase, + ) + def test__invoke__success__logging( self, step_configure_motion_instance: StepConfigureMotion, @@ -87,7 +102,7 @@ def test__generate_camera_templates__creates_valid_templates( ) assert template.destination == f'/etc/motion/camera{index}.conf' assert template.permissions == "600" - assert template.user == "root" + assert template.user == config.PI_PORTAL_USER assert template.context["CAMERA"] == camera_config[index0] assert template.context["CAMERA"]["NAME"] == f"CAMERA-{index}" assert template.context["CAMERA"]["ID"] == index diff --git a/pi_portal/installation/steps/tests/test_step_initialize_data_paths.py b/pi_portal/installation/steps/tests/test_step_initialize_data_paths.py index 2cc2d0c4..513a8765 100644 --- a/pi_portal/installation/steps/tests/test_step_initialize_data_paths.py +++ b/pi_portal/installation/steps/tests/test_step_initialize_data_paths.py @@ -64,6 +64,8 @@ def test__initialize__attrs( assert step_initialize_data_paths_instance.data_paths == [ config.PATH_ARCHIVAL_QUEUE_LOG_UPLOAD, config.PATH_ARCHIVAL_QUEUE_VIDEO_UPLOAD, + config.PATH_CAMERA_CONTENT, + config.PATH_FILEBEAT_CONTENT, config.PATH_TASKS_SERVICE_DATABASES, ] diff --git a/pi_portal/installation/templates/__init__.py b/pi_portal/installation/templates/__init__.py index d04d255d..7f5d76b8 100644 --- a/pi_portal/installation/templates/__init__.py +++ b/pi_portal/installation/templates/__init__.py @@ -13,20 +13,22 @@ ), ConfileFileTemplate( source='supervisor/supervisord.conf', - destination='/etc/supervisor/supervisord.conf', + destination=config.PATH_SUPERVISOR_CONFIG, ), ] logzio_templates: List[ConfileFileTemplate] = [ ConfileFileTemplate( source='logzio/filebeat.yml', - destination='/etc/filebeat/filebeat.yml', + destination=config.PATH_FILEBEAT_CONFIG, + user=config.PI_PORTAL_USER, ), ] motion_templates: List[ConfileFileTemplate] = [ ConfileFileTemplate( source='motion/motion.conf', - destination='/etc/motion/motion.conf', + destination=config.PATH_CAMERA_CONFIG, + user=config.PI_PORTAL_USER, ), ] diff --git a/pi_portal/installation/templates/logzio/filebeat.yml b/pi_portal/installation/templates/logzio/filebeat.yml index 8adfb241..3f0bd58a 100644 --- a/pi_portal/installation/templates/logzio/filebeat.yml +++ b/pi_portal/installation/templates/logzio/filebeat.yml @@ -59,7 +59,7 @@ filebeat.inputs: ignore_older: 12h # For version 7 and higher -filebeat.registry.path: /var/lib/filebeat +filebeat.registry.path: {{ PATH_FILEBEAT_CONTENT }} # The following processors are to ensure compatibility with version 7 processors: diff --git a/pi_portal/installation/templates/supervisor/supervisord.conf b/pi_portal/installation/templates/supervisor/supervisord.conf index 58d8f08f..8baf66f7 100644 --- a/pi_portal/installation/templates/supervisor/supervisord.conf +++ b/pi_portal/installation/templates/supervisor/supervisord.conf @@ -7,7 +7,7 @@ chown={{ PI_PORTAL_USER }}:root [supervisord] logfile={{ SUPERVISOR_LOG_PREFIX }}d.log -pidfile=/var/run/supervisord.pid +pidfile={{ PID_FILE_SUPERVISORD }} childlogdir=/var/log/supervisor minfds=1000000 @@ -53,6 +53,8 @@ stdout_capture_maxbytes=1MB umask=027 [program:camera] +user={{ PI_PORTAL_USER }} +environment=HOME="/var/run",USER="{{ PI_PORTAL_USER }}" command={{ PATH_CAMERA_BINARY }} process_name=%(program_name)s numprocs=1 @@ -97,7 +99,9 @@ stdout_capture_maxbytes=1MB umask=027 [program:filebeat] -command={{ FILE_BEAT_BINARY }} -c {{ FILE_BEAT_CONFIG }} +user={{ PI_PORTAL_USER }} +environment=HOME="/var/run",USER="{{ PI_PORTAL_USER }}" +command={{ PATH_FILEBEAT_BINARY }} -c {{ PATH_FILEBEAT_CONFIG }} process_name=%(program_name)s numprocs=1 directory=/var/run