[Windows] Security model for files permissions - STEP 2 (#6895)

This PR is the second part of #6497 to ease the integration, following the new plan propose by @bmw here: #6497 (comment)

This PR creates the module certbot.compat.os, that delegates everything to os, and that will be the safeguard against problematic methods of the standard module. On top of that, a quality check wrapper is called in the lint tox environment. This wrapper calls pylint and ensures that standard os module is no used directly in the certbot codebase.

Finally local oldest requirements are updated to ensure that tests will take the new logic when running.

* Add executable permissions

* Add the delegate certbot.compat.os module, add check coding style to enforce usage of certbot.compat.os instead of standard os

* Load certbot.compat.os instead of os

* Move existing compat test

* Update local oldest requirements

* Import sys

* Update account_test.py

* Update os.py

* Update os.py

* Update local oldest requirements

* Implement the new linter_plugin

* Fix local oldest for nginx

* Remove check coding style

* Update linter_plugin.py

* Add several comments

* Update the setup.py

* Add documentation

* Update acme dependencies

* Update certbot/compat/os.py

* Update docs/contributing.rst

* Update linter_plugin.py

* Handle os.path. Simplify checker.

* Add a comment to a reference implementation

* Update changelog

* Fix module registering

* Update docs/contributing.rst

* Update config and changelog
This commit is contained in:
Adrien Ferrand
2019-04-12 13:32:51 -07:00
committed by Brad Warren
parent 9c54f3dec8
commit d5de24d9fc
133 changed files with 321 additions and 240 deletions
+2 -2
View File
@@ -1,6 +1,5 @@
"""Plugin common functions."""
import logging
import os
import re
import shutil
import tempfile
@@ -12,6 +11,7 @@ import zope.interface
from josepy import util as jose_util
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
from certbot import achallenges # pylint: disable=unused-import
from certbot import constants
from certbot import crypto_util
@@ -19,7 +19,7 @@ from certbot import errors
from certbot import interfaces
from certbot import reverter
from certbot import util
from certbot.compat import os
from certbot.plugins.storage import PluginStorage
logger = logging.getLogger(__name__)
+2 -3
View File
@@ -1,20 +1,19 @@
"""Tests for certbot.plugins.common."""
import functools
import os
import shutil
import tempfile
import unittest
import OpenSSL
import josepy as jose
import mock
import OpenSSL
from acme import challenges
from certbot import achallenges
from certbot import crypto_util
from certbot import errors
from certbot.compat import os
from certbot.tests import acme_util
from certbot.tests import util as test_util
+2 -1
View File
@@ -2,16 +2,17 @@
import abc
import logging
import os
import stat
from time import sleep
import configobj
import zope.interface
from acme import challenges
from certbot import errors
from certbot import interfaces
from certbot.compat import os
from certbot.display import ops
from certbot.display import util as display_util
from certbot.plugins import common
+1 -1
View File
@@ -2,12 +2,12 @@
import collections
import logging
import os
import unittest
import mock
from certbot import errors
from certbot.compat import os
from certbot.display import util as display_util
from certbot.plugins import dns_common
from certbot.plugins import dns_test_common
+2 -2
View File
@@ -1,14 +1,14 @@
"""Base test class for DNS authenticators."""
import os
import configobj
import josepy as jose
import mock
import six
from acme import challenges
from certbot import achallenges
from certbot.compat import os
from certbot.tests import acme_util
from certbot.tests import util as test_util
+2 -3
View File
@@ -1,6 +1,4 @@
"""Manual authenticator plugin"""
import os
import zope.component
import zope.interface
@@ -8,10 +6,11 @@ from acme import challenges
from acme.magic_typing import Dict # pylint: disable=unused-import, no-name-in-module
from certbot import achallenges # pylint: disable=unused-import
from certbot import interfaces
from certbot import errors
from certbot import hooks
from certbot import interfaces
from certbot import reverter
from certbot.compat import os
from certbot.plugins import common
+3 -4
View File
@@ -1,15 +1,14 @@
"""Tests for certbot.plugins.manual"""
import os
import unittest
import sys
import six
import mock
import six
from acme import challenges
from certbot import errors
from certbot.compat import os
from certbot.tests import acme_util
from certbot.tests import util as test_util
@@ -73,7 +72,7 @@ class AuthenticatorTest(test_util.TempDirTestCase):
self.config.manual_public_ip_logging_ok = True
self.config.manual_auth_hook = (
'{0} -c "from __future__ import print_function;'
'import os; print(os.environ.get(\'CERTBOT_DOMAIN\'));'
'from certbot.compat import os; print(os.environ.get(\'CERTBOT_DOMAIN\'));'
'print(os.environ.get(\'CERTBOT_TOKEN\', \'notoken\'));'
'print(os.environ.get(\'CERTBOT_VALIDATION\', \'novalidation\'));"'
.format(sys.executable))
+1 -2
View File
@@ -1,7 +1,6 @@
"""Decide which plugins to use for authentication & installation"""
from __future__ import print_function
import os
import logging
import six
@@ -9,7 +8,7 @@ import zope.component
from certbot import errors
from certbot import interfaces
from certbot.compat import os
from certbot.display import util as display_util
logger = logging.getLogger(__name__)
+1 -1
View File
@@ -1,5 +1,4 @@
"""Tests for letsencrypt.plugins.selection"""
import os
import sys
import unittest
@@ -10,6 +9,7 @@ from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-
from certbot import errors
from certbot import interfaces
from certbot.compat import os
from certbot.display import util as display_util
from certbot.plugins.disco import PluginsRegistry
from certbot.tests import util as test_util
+2 -1
View File
@@ -1,10 +1,11 @@
"""Plugin storage class."""
import json
import logging
import os
from acme.magic_typing import Any, Dict # pylint: disable=unused-import, no-name-in-module
from certbot import errors
from certbot.compat import os
logger = logging.getLogger(__name__)
+3 -2
View File
@@ -1,14 +1,15 @@
"""Tests for certbot.plugins.storage.PluginStorage"""
import json
import os
import unittest
import mock
from certbot import errors
from certbot.compat import os
from certbot.plugins import common
from certbot.tests import util as test_util
class PluginStorageTest(test_util.ConfigTestCase):
"""Test for certbot.plugins.storage.PluginStorage"""
@@ -71,7 +72,7 @@ class PluginStorageTest(test_util.ConfigTestCase):
def test_save_errors_unable_to_write_file(self):
mock_open = mock.mock_open()
mock_open.side_effect = IOError
with mock.patch("os.open", mock_open):
with mock.patch("certbot.compat.os.open", mock_open):
with mock.patch("certbot.plugins.storage.logger.error") as mock_log:
self.plugin.storage._data = {"valid": "data"} # pylint: disable=protected-access
self.plugin.storage._initialized = True # pylint: disable=protected-access
+1 -1
View File
@@ -1,8 +1,8 @@
"""Plugin utilities."""
import logging
import os
from certbot import util
from certbot.compat import os
logger = logging.getLogger(__name__)
+3 -1
View File
@@ -1,9 +1,11 @@
"""Tests for certbot.plugins.util."""
import os
import unittest
import mock
from certbot.compat import os
class GetPrefixTest(unittest.TestCase):
"""Tests for certbot.plugins.get_prefixes."""
def test_get_prefix(self):
+2 -3
View File
@@ -4,7 +4,6 @@ import collections
import errno
import json
import logging
import os
import six
import zope.component
@@ -19,12 +18,12 @@ from certbot import achallenges # pylint: disable=unused-import
from certbot import cli
from certbot import errors
from certbot import interfaces
from certbot.display import util as display_util
from certbot.compat import os
from certbot.display import ops
from certbot.display import util as display_util
from certbot.plugins import common
from certbot.plugins import util
logger = logging.getLogger(__name__)
+2 -2
View File
@@ -5,7 +5,6 @@ from __future__ import print_function
import argparse
import errno
import json
import os
import shutil
import tempfile
import unittest
@@ -19,6 +18,7 @@ from acme import challenges
from certbot import achallenges
from certbot import errors
from certbot.compat import misc
from certbot.compat import os
from certbot.display import util as display_util
from certbot.tests import acme_util
from certbot.tests import util as test_util
@@ -242,7 +242,7 @@ class AuthenticatorTest(unittest.TestCase):
os.rmdir(leftover_path)
@mock.patch('os.rmdir')
@mock.patch('certbot.compat.os.rmdir')
def test_cleanup_failure(self, mock_rmdir):
self.auth.prepare()
self.auth.perform([self.achall])