From 46ac508eae63bfa671dec0429fe71a20e28fd8e8 Mon Sep 17 00:00:00 2001 From: Kunal Mehta Date: Wed, 6 Nov 2024 17:16:12 -0500 Subject: [PATCH] Clean out old OSSEC diff and state files These files are never pruned by OSSEC so they tend to accumulate, which can be a big deal for very big binary files like the ones in /boot. A script triggered by a daily timer will now clean up old state and diff files that are more than a year old. Fixes #7325. --- .../common/test_basic_configuration.py | 25 ++++++++++++++++ .../system/securedrop-cleanup-ossec.service | 7 +++++ .../system/securedrop-cleanup-ossec.timer | 10 +++++++ .../usr/bin/securedrop-cleanup-ossec.py | 29 +++++++++++++++++++ securedrop/debian/rules | 2 ++ 5 files changed, 73 insertions(+) create mode 100644 securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.service create mode 100644 securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.timer create mode 100644 securedrop/debian/config/usr/bin/securedrop-cleanup-ossec.py diff --git a/molecule/testinfra/common/test_basic_configuration.py b/molecule/testinfra/common/test_basic_configuration.py index 97b9697d11..6db173a950 100644 --- a/molecule/testinfra/common/test_basic_configuration.py +++ b/molecule/testinfra/common/test_basic_configuration.py @@ -1,3 +1,5 @@ +import time + import testutils from testinfra.host import Host @@ -21,3 +23,26 @@ def test_system_time(host: Host) -> None: c = host.run("timedatectl show") assert "NTP=yes" in c.stdout assert "NTPSynchronized=yes" in c.stdout + + +def test_ossec_cleanup(host: Host) -> None: + with host.sudo(): + c = host.run("mkdir -p /var/ossec/queue/diff/local/boot/appinfra-test") + assert c.rc == 0 + c = host.run("echo 'test' | /var/ossec/queue/diff/local/boot/appinfra-test/state.123456789") + assert c.rc == 0 + # change the mtime on the file to be 2 years ago + c = host.run( + "touch -d '2 years ago' /var/ossec/queue/diff/local/boot/appinfra-test/state.123456789" + ) + assert c.rc == 0 + c = host.run("systemctl start securedrop-cleanup-ossec") + assert c.rc == 0 + while host.service("securedrop-cleanup-ossec").is_running: + time.sleep(1) + assert not host.file( + "/var/ossec/queue/diff/local/boot/appinfra-test/state.123456789" + ).exists + # cleanup + c = host.run("rm -r /var/ossec/queue/diff/local/boot/appinfra-test") + assert c.rc == 0 diff --git a/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.service b/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.service new file mode 100644 index 0000000000..236070148d --- /dev/null +++ b/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.service @@ -0,0 +1,7 @@ +[Unit] +Description=Cleanup OSSEC diff queue + +[Service] +Type=oneshot +ExecStart=/usr/bin/securedrop-cleanup-ossec.py +User=root diff --git a/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.timer b/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.timer new file mode 100644 index 0000000000..33ee35e1de --- /dev/null +++ b/securedrop/debian/config/lib/systemd/system/securedrop-cleanup-ossec.timer @@ -0,0 +1,10 @@ +[Unit] +Description=Cleanup OSSEC diff queue + +[Timer] +OnCalendar=daily +Persistent=true +RandomizedDelaySec=5m + +[Install] +WantedBy=timers.target diff --git a/securedrop/debian/config/usr/bin/securedrop-cleanup-ossec.py b/securedrop/debian/config/usr/bin/securedrop-cleanup-ossec.py new file mode 100644 index 0000000000..fe665cb10d --- /dev/null +++ b/securedrop/debian/config/usr/bin/securedrop-cleanup-ossec.py @@ -0,0 +1,29 @@ +import os +import re +from datetime import datetime, timedelta + +OSSEC_DIFFS = "/var/ossec/queue/diff/local/" +KEEP_DAYS = 365 +# Match e.g. state.1667271785 +RE_REMOVE = re.compile(r"^(state|diff)\.\d+$") + + +def main(): + """ + Delete OSSEC diff/state files older than a year + """ + cutoff_date = datetime.now() - timedelta(days=KEEP_DAYS) + + for root, dirs, files in os.walk(OSSEC_DIFFS): + for file in files: + if RE_REMOVE.match(file): + file_path = os.path.join(root, file) + modified_time = os.path.getmtime(file_path) + file_modified_date = datetime.fromtimestamp(modified_time) + if file_modified_date < cutoff_date: + os.remove(file_path) + print(f"Deleted file: {file_path} (Last modified: {file_modified_date})") + + +if __name__ == "__main__": + main() diff --git a/securedrop/debian/rules b/securedrop/debian/rules index 2f12ea154b..d344809f06 100755 --- a/securedrop/debian/rules +++ b/securedrop/debian/rules @@ -78,6 +78,7 @@ override_dh_systemd_enable: dh_systemd_enable --no-enable securedrop-submissions-today.service dh_systemd_enable --no-enable securedrop-clean-tmp.service dh_systemd_enable --no-enable securedrop-remove-pending-sources.service + dh_systemd_enable --no-enable securedrop-cleanup-ossec.service dh_systemd_enable # This is basically the same as the enable stanza above, just whether the @@ -86,4 +87,5 @@ override_dh_systemd_start: dh_systemd_start --no-start securedrop-submissions-today.service dh_systemd_start --no-start securedrop-clean-tmp.service dh_systemd_start --no-start securedrop-remove-pending-sources.service + dh_systemd_start --no-start securedrop-cleanup-ossec.service dh_systemd_start