Preserve app gate TLS access through provisioning and certificate rotation
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Keep the node TLS leaf private while allowing the management daemon to read it."""
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
import pwd
|
||||
import stat
|
||||
|
||||
|
||||
def repair(key: Path, service_uid: int, service_gid: int) -> bool:
|
||||
try:
|
||||
fd = os.open(key, os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK)
|
||||
except FileNotFoundError:
|
||||
return False # A node without TLS is not provisioned by this repair.
|
||||
try:
|
||||
before = os.fstat(fd)
|
||||
if not stat.S_ISREG(before.st_mode) or before.st_uid not in (0, service_uid):
|
||||
raise RuntimeError('Unexpected node TLS key type or owner; left unchanged')
|
||||
# The daemon's primary group is the sole additional reader. Never make
|
||||
# the key world-readable or grant group write/execute permissions.
|
||||
mode = 0o640 if before.st_mode & stat.S_IWUSR else 0o440
|
||||
if before.st_gid == service_gid and stat.S_IMODE(before.st_mode) == mode:
|
||||
return False
|
||||
os.fchown(fd, -1, service_gid)
|
||||
os.fchmod(fd, mode)
|
||||
os.fsync(fd)
|
||||
return True
|
||||
finally:
|
||||
os.close(fd)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--key-name', choices=['archipelago.key', 'archipelago.key.new', 'archipelago.key.rotnew'], default='archipelago.key')
|
||||
args = parser.parse_args()
|
||||
account = pwd.getpwnam('archipelago')
|
||||
changed = repair(Path('/etc/archipelago/ssl') / args.key_name, account.pw_uid, account.pw_gid)
|
||||
print('Node app TLS permissions repaired' if changed else 'Node app TLS permissions unchanged')
|
||||
Reference in New Issue
Block a user