-
Notifications
You must be signed in to change notification settings - Fork 686
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a basic noble migration check script
Perform a number of checks to ensure the system is ready for the noble migration. The results are written to a JSON file in /etc/ that other things like the JI and the upgrade script itself can read from. The script is run hourly on a systemd timer but can also be run interactively for administrators who want slightly more details. Refs #7322.
- Loading branch information
Showing
5 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
securedrop/debian/config/lib/systemd/system/securedrop-noble-migration-check.service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[Unit] | ||
Description=Check noble migration readiness | ||
|
||
[Service] | ||
Type=oneshot | ||
ExecStart=/usr/bin/securedrop-noble-migration-check.py | ||
User=root |
10 changes: 10 additions & 0 deletions
10
securedrop/debian/config/lib/systemd/system/securedrop-noble-migration-check.timer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[Unit] | ||
Description=Check noble migration readiness | ||
|
||
[Timer] | ||
OnCalendar=hourly | ||
Persistent=true | ||
RandomizedDelaySec=5m | ||
|
||
[Install] | ||
WantedBy=timers.target |
137 changes: 137 additions & 0 deletions
137
securedrop/debian/config/usr/bin/securedrop-noble-migration-check.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#!/usr/bin/python3 | ||
""" | ||
Check migration of a SecureDrop server from focal to noble | ||
This script is run as root on both the app and mon servers. | ||
""" | ||
|
||
import grp | ||
import json | ||
import os | ||
import shutil | ||
import subprocess | ||
import sys | ||
from pathlib import Path | ||
from urllib.parse import urlparse | ||
|
||
|
||
def os_codename() -> str: | ||
with open("/etc/os-release") as f: | ||
os_release = f.readlines() | ||
for line in os_release: | ||
if line.startswith("VERSION_CODENAME="): | ||
return line.split("=")[1].strip().strip('"') | ||
raise ValueError("Could not determine Ubuntu codename") | ||
|
||
|
||
def check_ssh_group() -> bool: | ||
"""Check the UNIX "ssh" group is empty""" | ||
try: | ||
group = grp.getgrnam("ssh") | ||
except KeyError: | ||
print("ssh: group does not exist") | ||
return True | ||
|
||
if len(group.gr_mem) > 0: | ||
print(f"ssh: group is not empty: {group.gr_mem}") | ||
return False | ||
|
||
print("ssh: group is empty") | ||
return True | ||
|
||
|
||
def check_ufw_removed() -> bool: | ||
"""Check that ufw is removed""" | ||
if Path("/usr/sbin/ufw").exists(): | ||
print("ufw: ufw is still installed") | ||
return False | ||
else: | ||
print("ufw: ufw was removed") | ||
return True | ||
|
||
|
||
def check_free_space() -> bool: | ||
"""Check the root partition has more than 10G free""" | ||
root = shutil.disk_usage("/") | ||
if root.free < (10 * 1024 * 1024 * 1024): | ||
print("free space: not enough free space") | ||
return False | ||
else: | ||
print("free space: enough free space") | ||
return True | ||
|
||
|
||
def check_apt() -> bool: | ||
"""Verify only expected sources are configured""" | ||
try: | ||
output = subprocess.check_output(["apt-get", "indextargets"], text=True) | ||
except subprocess.CalledProcessError: | ||
print("apt: error invoking apt-get indextargets") | ||
return False | ||
|
||
for line in output.splitlines(): | ||
if line.startswith("URI:"): | ||
parsed = urlparse(line.split(":", 1)[1].strip()) | ||
if parsed.hostname not in [ | ||
"archive.ubuntu.com", | ||
"security.ubuntu.com", | ||
"apt.freedom.press", | ||
"apt-test.freedom.press", | ||
]: | ||
print(f"apt: unexpected source: {parsed.hostname}") | ||
return False | ||
|
||
print("apt: all sources are expected") | ||
return True | ||
|
||
|
||
def check_systemd() -> bool: | ||
""" "No systemd units are failed""" | ||
try: | ||
subprocess.check_output(["systemctl", "is-failed"]) | ||
print("systemd: some systemd units are failed") | ||
return False | ||
except subprocess.CalledProcessError: | ||
print("systemd: all systemd units are running") | ||
return True | ||
|
||
|
||
def main() -> None: | ||
if os.geteuid() != 0: | ||
print("You need to run this as root") | ||
sys.exit(1) | ||
|
||
state_path = Path("/etc/securedrop-noble-migration.json") | ||
codename = os_codename() | ||
|
||
if codename != "focal": | ||
print(f"Unsupported Ubuntu version: {codename}") | ||
# nothing to do, write an empty JSON blob | ||
state_path.write_text(json.dumps({})) | ||
return | ||
|
||
state = {} | ||
state["ssh"] = check_ssh_group() | ||
state["ufw"] = check_ufw_removed() | ||
state["free_space"] = check_free_space() | ||
state["apt"] = check_apt() | ||
state["systemd"] = check_systemd() | ||
|
||
state_path.write_text(json.dumps(state)) | ||
|
||
if all(state.values()): | ||
print("All ready for migration!") | ||
sys.exit(0) | ||
else: | ||
print("""\ | ||
Some errors were found that will block migration. | ||
If you are unsure what to do, please contact the SecureDrop | ||
support team: <https://docs.securedrop.org/en/stable/getting_support.html>. | ||
""") | ||
sys.exit(1) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters