1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-26 07:41:33 +03:00

Consistent directory mode apply when makedirs is called (#8010)

Fixes #7993 

This PR uses `os.umask()` during `certbot.compat.filesystem.makedirs()` call to ensure that all directories, and not only the leaf one, have the provided `mode` when created. This ensures a safe and consistent behavior independently from the Python version, since the behavior of `os.makedirs` changed on that matter with Python 3.7.

* Implement logic to apply the same permission on all dirs created by makedirs

* Add a test

* Add comment

* Update certbot/certbot/compat/filesystem.py

Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
This commit is contained in:
Adrien Ferrand
2020-05-22 00:29:06 +02:00
committed by GitHub
parent 3ea5170647
commit b42e24178a
2 changed files with 33 additions and 1 deletions

View File

@@ -237,8 +237,19 @@ def makedirs(file_path, mode=0o777):
will be applied if ``None``
"""
if POSIX_MODE:
return os.makedirs(file_path, mode)
# Since Python 3.7, os.makedirs does not set the given mode to the intermediate directories
# that could be created in the process. To keep things safe and consistent on all
# Python versions, we set the umask accordingly to have all directories (intermediate and
# leaf) created with the given mode.
current_umask = os.umask(0)
try:
os.umask(current_umask | 0o777 ^ mode)
return os.makedirs(file_path, mode)
finally:
os.umask(current_umask)
# TODO: Windows does not support umask. A specific PR (#7967) is handling this, and will need
# to add appropriate umask call for the Windows part of the logic below.
orig_mkdir_fn = os.mkdir
try:
# As we know that os.mkdir is called internally by os.makedirs, we will swap the function in

View File

@@ -1,6 +1,7 @@
"""Tests for certbot.compat.filesystem"""
import contextlib
import errno
import stat
import unittest
try:
@@ -280,6 +281,26 @@ class WindowsMkdirTests(test_util.TempDirTestCase):
self.assertEqual(original_mkdir, std_os.mkdir)
# TODO: This test can be used both by Linux and Windows once on #7967
@unittest.skipUnless(POSIX_MODE, reason='Needs umask to succeed, and Windows does not have it')
class LinuxMkdirTests(test_util.TempDirTestCase):
"""Unit tests for Linux mkdir + makedirs functions in filesystem module"""
def test_makedirs_correct_permissions(self):
path = os.path.join(self.tempdir, 'dir')
subpath = os.path.join(path, 'subpath')
previous_umask = os.umask(0o022)
try:
filesystem.makedirs(subpath, 0o700)
import os as std_os # pylint: disable=os-module-forbidden
assert stat.S_IMODE(std_os.stat(path).st_mode) == 0o700
assert stat.S_IMODE(std_os.stat(subpath).st_mode) == 0o700
finally:
os.umask(previous_umask)
class CopyOwnershipAndModeTest(test_util.TempDirTestCase):
"""Tests about copy_ownership_and_apply_mode, copy_ownership_and_mode and has_same_ownership"""
def setUp(self):