letsencrypt: When copying certificate reset the umask reliably

- When there is an error writing to certificate files, the umask is not reset
properly. Fix this my using umask context manager from action utils. This could
be core reason behind: #2564.

Tests:

- Changing the domain name creates the file /var/lib/quassel/quasselCert.pem
with the proper permissions of 0o600. If in Quassel app's Let's Encrypt component
the certificate file path is changed, then two files are created on domain name
change. Private key is created with 0o600 permissions and certificate file is
created with 0o644 permissions.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2026-02-18 16:48:09 -08:00 committed by James Valleroy
parent 03b4a78fd0
commit 9a16e20fa9
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808

View File

@ -160,21 +160,19 @@ def copy_certificate(managing_app: str, source_private_key: str,
certificate_path.parent.mkdir(mode=0o755, parents=True, exist_ok=True)
# Private key is only accessible to the user owner
old_mask = os.umask(0o177)
shutil.copyfile(source_private_key_path, private_key_path)
with action_utils.umask(0o177):
shutil.copyfile(source_private_key_path, private_key_path)
if certificate_path != private_key_path:
# Certificate is only writable by the user owner
os.umask(0o133)
shutil.copyfile(source_certificate_path, certificate_path)
else:
# If private key and certificate are the same file, append one after
# the other.
source_certificate_bytes = source_certificate_path.read_bytes()
with private_key_path.open(mode='a+b') as file_handle:
file_handle.write(source_certificate_bytes)
os.umask(old_mask)
if certificate_path != private_key_path:
# Certificate is only writable by the user owner
with action_utils.umask(0o133):
shutil.copyfile(source_certificate_path, certificate_path)
else:
# If private key and certificate are the same file, append one
# after the other.
source_certificate_bytes = source_certificate_path.read_bytes()
with private_key_path.open(mode='a+b') as file_handle:
file_handle.write(source_certificate_bytes)
shutil.chown(certificate_path, user=user_owner, group=group_owner)
shutil.chown(private_key_path, user=user_owner, group=group_owner)