[Python-checkins] peps: PEP 493: First draft as a standards track PEP

nick.coghlan python-checkins at python.org
Fri Nov 27 00:54:35 EST 2015


https://hg.python.org/peps/rev/f602a47ea795
changeset: 6132:f602a47ea795
user: Nick Coghlan <ncoghlan at gmail.com>
date: Fri Nov 27 15:51:43 2015 +1000
summary:
 PEP 493: First draft as a standards track PEP
- now has 2 feature sections, and 3 backport recommendations
- features are for a new Python API and environment setting
- backports are all for targeting versions < 2.7.9
- Python 3 is excluded from scope
files:
 pep-0493.txt | 333 ++++++++++++++++++++++++++++----------
 1 files changed, 240 insertions(+), 93 deletions(-)
diff --git a/pep-0493.txt b/pep-0493.txt
--- a/pep-0493.txt
+++ b/pep-0493.txt
@@ -1,78 +1,91 @@
 PEP: 493
-Title: HTTPS verification recommendations for Python 2.7 redistributors
+Title: HTTPS verification migration tools for Python 2.7
 Version: $Revision$
 Last-Modified: $Date$
 Author: Nick Coghlan <ncoghlan at gmail.com>,
 Robert Kuska <rkuska at redhat.com>,
 Marc-André Lemburg <mal at lemburg.com>
 Status: Draft
-Type: Informational
+Type: Standards Track
 Content-Type: text/x-rst
 Created: 10-May-2015
+Python-Version: 2.7.12
 Post-History: 06-Jul-2015, 11-Nov-2015, 24-Nov-2015
 
 
 Abstract
 ========
 
-PEP 476 updated Python's default handling of HTTPS certificates to be
-appropriate for communication over the public internet. The Python 2.7 long
-term maintenance series was judged to be in scope for this change, with the
-new behaviour introduced in the Python 2.7.9 maintenance release.
+PEP 476 updated Python's default handling of HTTPS certificates in client
+modules to align with certificate handling in web browsers, by validating
+that the certificates received belonged to the server the client was attempting
+to contact. The Python 2.7 long term maintenance series was judged to be in
+scope for this change, with the new behaviour introduced in the Python 2.7.9
+maintenance release.
 
-This PEP provides recommendations to downstream redistributors wishing to
-provide a smoother migration experience when helping their users to manage
-this change in Python's default behaviour.
-
-*Note that this PEP is not currently accepted, so it is a *proposed*
-recommendation, rather than an active one.*
+This has created a non-trivial barrier to adoption for affected Python 2.7
+maintenance releases, so this PEP proposes additional Python 2.7 specific
+features that allow system administrators and other users to more easily
+decouple the decision to verify server certificates in HTTPS client modules
+from the decision to update to newer Python 2.7 maintenance releases.
 
 
 Rationale
 =========
 
-PEP 476 changed Python's default behaviour to better match the needs and
-expectations of developers operating over the public internet, a category
-which appears to include most new Python developers. It is the position of
-the authors of this PEP that this was a correct decision.
+PEP 476 changed Python's default behaviour to align with expectations
+established by web browsers in regards to the semantics of HTTPS URLs:
+starting with Python 2.7.9 and 3.4.3, HTTPS clients in the standard library
+validate server certificates by default.
 
 However, it is also the case that this change *does* cause problems for
 infrastructure administrators operating private intranets that rely on
 self-signed certificates, or otherwise encounter problems with the new default
 certificate verification settings.
 
-The long term answer for such environments is to update their internal
-certificate management to at least match the standards set by the public
-internet, but in the meantime, it is desirable to offer these administrators
-a way to continue receiving maintenance updates to the Python 2.7 series,
-without having to gate that on upgrades to their certificate management
-infrastructure.
+To manage these kinds of situations, web browsers provide users with "click
+through" warnings that allow the user to add the server's certificate to the
+browser's certificate store. Network client tools like ``curl`` and ``wget``
+offer options to switch off certificate checking entirely (by way of
+``curl --insecure`` and ``wget --no-check-certificate``, respectively).
 
-PEP 476 did attempt to address this question, by covering how to revert the
-new settings process wide by monkeypatching the ``ssl`` module to restore the
+At a different layer of the technology stack, Linux security modules like
+`SELinux` and `AppArmor`, while enabled by default by distribution vendors,
+offer relatively straightforward mechanisms for turning them off.
+
+At the moment, no such convenient mechanisms exist to disable Python's
+default certificate checking for a whole process.
+
+PEP 476 did attempt to address this question, by covering how to revert to the
+old settings process wide by monkeypatching the ``ssl`` module to restore the
 old behaviour. Unfortunately, the ``sitecustomize.py`` based technique proposed
 to allow system administrators to disable the feature by default in their
 Standard Operating Environment definition has been determined to be
-insufficient in at least some cases. The specific case of interest to the
-authors of this PEP is the one where a Linux distributor aims to provide
-their users with a
+insufficient in at least some cases. The specific case that led to the
+initial creation of this PEP is the one where a Linux distributor aims to
+provide their users with a
 `smoother migration path <https://bugzilla.redhat.com/show_bug.cgi?id=1173041>`__
 than the standard one provided by consuming upstream CPython 2.7 releases
 directly, but other potential challenges have also been pointed out with
 updating embedded Python runtimes and other user level installations of Python.
 
 Rather than allowing a plethora of mutually incompatibile migration techniques
-to bloom, this PEP proposes two alternative approaches that redistributors
-may take when addressing these problems. Redistributors may choose to implement
-one, both, or neither of these approaches based on their assessment of the
-needs of their particular userbase.
+to bloom, this PEP proposes an additional feature to be added to Python 2.7.12
+to make it easier to revert a process to the past behaviour of skipping
+certificate validation in HTTPS client modules. It also provides additional
+recommendations to redistributors backporting these features to versions of
+Python prior to Python 2.7.9.
 
-These designs are being proposed as a recommendation for redistributors, rather
-than as new upstream features, as they are needed purely to support legacy
-environments migrating from older versions of Python 2.7. Neither approach
-is being proposed as an upstream Python 2.7 feature, nor as a feature in any
-version of Python 3 (whether published directly by the Python Software
-Foundation or by a redistributor).
+These designs are being proposed purely as tools for helping to manage the
+transition to the new default certificate handling behaviour in the context
+of Python 2.7. They are not being proposed as new features for Python 3, as
+it is expected that the vast majority of client applications affected by this
+problem without the ability to update the application itself will be Python 2
+applications.
+
+It would likely be desirable for a future version of Python 3 to allow default
+certificate handling for secure protocols to be configurable on a per-protocol
+basis, but that question is beyond the scope of this PEP.
 
 Alternatives
 ------------
@@ -84,20 +97,20 @@
 * Continuing to rebase on new Python 2.7.x releases, while providing no
 additional assistance beyond the mechanisms defined in PEP 476 in migrating
 from unchecked to checked hostnames in standard library HTTPS clients
-* Gating availability of the improved default handling of HTTPS connections on
- upgrading from Python 2 to Python 3
-* For Linux distribution vendors, gating availability of the improved default
+* Gating availability of the changes in default handling of HTTPS connections
+ on upgrading from Python 2 to Python 3
+* For Linux distribution vendors, gating availability of the changes in default
 handling of HTTPS connections on upgrading to a new operating system version
-* Implementing one or both of the design suggestions described in this PEP,
+* Implementing one or both of the backport suggestions described in this PEP,
 regardless of the formal status of the PEP
 
 
 Requirements for capability detection
 =====================================
 
-As these recommendations are intended to cover backports to earlier Python
+As the proposals in this PEP aim to facilitate backports to earlier Python
 versions, the Python version number cannot be used as a reliable means for
-detecting them. Instead, the recommendations are defined to allow the presence
+detecting them. Instead, they are designed to allow the presence
 or absence of the feature to be determined using the following technique::
 
 python -c "import ssl; ssl._relevant_attribute"
@@ -108,57 +121,99 @@
 The marker attributes are prefixed with an underscore to indicate the
 implementation dependent nature of these capabilities - not all Python
 distributions will offer them, only those that are providing a multi-stage
-migration process from the legacy HTTPS handling to the new default behaviour.
+migration process from the original Python 2.7 HTTPS handling to the new
+default behaviour.
 
+Feature: Configuration API
+==========================
 
-Recommendation for an environment variable based security downgrade
-===================================================================
+This change is proposed for inclusion in CPython 2.7.12 and later CPython 2.7.x
+releases. It consists of a new ``ssl._verify_https_certificates()`` to specify
+the default handling of HTTPS certificates in standard library client libraries.
 
-Some redistributors may wish to provide a per-application option to disable
-certificate verification in selected applications that run on or embed CPython
-without needing to modify the application itself.
+It is not proposed to forward port this change to Python 3, so Python 3
+applications that need to support skipping certificate verification will still
+need to define their own suitable security context.
 
-In these cases, a configuration mechanism is needed that provides:
+Feature detection
+-----------------
 
-* an opt-out model that allows certificate verification to be selectively
- turned off for particular applications after upgrading to a version of
- Python that verifies certificates by default
-* the ability for all users to configure this setting on a per-application
- basis, rather than on a per-system, or per-Python-installation basis
+The marker attribute on the ``ssl`` module related to this feature is the
+``ssl._verify_https_certificates`` function itself.
 
-This approach may be used for any redistributor provided version of Python 2.7,
-including those that advertise themselves as providing Python 2.7.9 or later.
+Specification
+-------------
 
+The ``ssl._verify_https_certificates`` function will work as follows::
 
-Required marker attribute
--------------------------
+ def _verify_https_certificates(enable=True):
+ """Verify server HTTPS certificates by default?"""
+ global _create_default_https_context
+ if enable:
+ _create_default_https_context = create_default_context
+ else:
+ _create_default_https_context = _create_unverified_context
 
-The required marker attribute on the ``ssl`` module when implementing this
-recommendation is::
+If called without arguments, or with ``enable`` set to a true value, then
+standard library client modules will subsequently verify HTTPS certificates by default, otherwise they will skip verification.
 
- _https_verify_envvar = 'PYTHONHTTPSVERIFY'
+If called with ``enable`` set to a false value, then standard library client
+modules will subsequently skip verifying HTTPS certificates by default.
+
+Security Considerations
+-----------------------
+
+The inclusion of this feature will allow security sensitive applications to
+include the following forward-compatible snippet in their code::
+
+ if hasattr(ssl, "_verify_https_certificates"):
+ ssl._verify_https_certificates()
+
+Some developers may also choose to opt out of certificate checking using
+``ssl._verify_https_certificates(enable=False)``. This doesn't introduce any
+major new security concerns, as monkeypatching the affected internal APIs was
+already possible.
+
+
+Feature: environment based configuration
+========================================
+
+This change is proposed for inclusion in CPython 2.7.12 and later CPython 2.7.x
+releases. It consists of a new ``PYTHONHTTPSVERIFY`` environment variable that
+allows the default verification to be disabled without modifying the
+application source code (which may not even be available in cases of
+bytecode-only application distribution)
+
+It is not proposed to forward port this change to Python 3, so Python 3
+applications that need to support skipping certificate verification will still
+need to define their own suitable security context.
+
+Feature detection
+-----------------
+
+The marker attribute on the ``ssl`` module related to this feature is:
+
+* the ``ssl._https_verify_envvar`` attribute, giving the name of environment
+ variable affecting the default behaviour
 
 This not only makes it straightforward to detect the presence (or absence) of
 the capability, it also makes it possible to programmatically determine the
 relevant environment variable name.
 
+Specification
+-------------
 
-Recommended modifications to the Python standard library
---------------------------------------------------------
+Rather than always defaulting to the use of ``ssl.create_default_context``,
+the ``ssl`` module will be modified to:
 
-The recommended approach to providing a per-application configuration setting
-for HTTPS certificate verification that doesn't require modifications to the
-application itself is to:
-
-* modify the ``ssl`` module to read the ``PYTHONHTTPSVERIFY`` environment
- variable when the module is first imported into a Python process
+* read the ``PYTHONHTTPSVERIFY`` environment variable when the module is first
+ imported into a Python process
 * set the ``ssl._create_default_https_context`` function to be an alias for
 ``ssl._create_unverified_context`` if this environment variable is present
 and set to ``'0'``
 * otherwise, set the ``ssl._create_default_https_context`` function to be an
 alias for ``ssl.create_default_context`` as usual
 
-
 Example implementation
 ----------------------
 
@@ -175,14 +230,13 @@
 
 _create_default_https_context = _get_https_context_factory()
 
-
 Security Considerations
 -----------------------
 
-Relative to an unmodified version of CPython 2.7.9 or later, this approach
-does introduce a new downgrade attack against the default security settings
-that potentially allows a sufficiently determined attacker to revert Python
-to the vulnerable configuration used in CPython 2.7.8 and earlier releases.
+Relative to the behaviour in Python 3.4.3+ and Python 2.7.9->2.7.11, this
+approach does introduce a new downgrade attack against the default security
+settings that potentially allows a sufficiently determined attacker to revert
+Python to the default behaviour used in CPython 2.7.8 and earlier releases.
 However, such an attack requires the ability to modify the execution
 environment of a Python process prior to the import of the ``ssl`` module,
 and any attacker with such access would already be able to modify the
@@ -191,13 +245,13 @@
 Interaction with Python virtual environments
 --------------------------------------------
 
-This setting is read directly from the process environment, and hence works
-the same way regardless of whether or not the interpreter is being run inside
-an activated Python virtual environment.
+The default setting is read directly from the process environment, and hence
+works the same way regardless of whether or not the interpreter is being run
+inside an activated Python virtual environment.
 
 
-Recommendation for backporting to earlier Python versions
-=========================================================
+Backporting PEP 476 to earlier Python versions
+==============================================
 
 Some redistributors, most notably Linux distributions, may choose to backport
 the PEP 476 HTTPS verification changes to modified Python versions based on
@@ -214,17 +268,21 @@
 installations that have been explicitly configured to skip verifying HTTPS
 certificates by default
 
-This approach should not be used for any Python installation that advertises
+As it only affects backports to earlier releases of Python 2.7, this change is
+not proposed for inclusion in upstream CPython, but rather is offered as
+guidance to redistributors to reduce the likelihood of multiple mutually
+incompatible approaches to backporting being adopted.
+
+This approach SHOULD NOT be used for any Python installation that advertises
 itself as providing Python 2.7.9 or later, as most Python users will have the
 reasonable expectation that all such environments will validate HTTPS
 certificates by default.
 
 
-Required marker attribute
--------------------------
+Feature detection
+-----------------
 
-The required marker attribute on the ``ssl`` module when implementing this
-recommendation is::
+The marker attribute on the ``ssl`` module related to this feature is::
 
 _cert_verification_config = '<path to configuration file>'
 
@@ -320,7 +378,7 @@
 Security Considerations
 -----------------------
 
-The specific recommendations for the backporting case are designed to work for
+The specific recommendations for this backporting case are designed to work for
 privileged, security sensitive processes, even those being run in the following
 locked down configuration:
 
@@ -356,19 +414,108 @@
 processes using that interpreter, regardless of whether or not the interpreter
 is being run inside an activated Python virtual environment.
 
+Origins of this recommendation
+------------------------------
 
-Combining the recommendations
-=============================
+This recommendation is based on the backporting approach adopted for Red Hat
+Enterprise Linux 7.2, as published in the original July 2015 draft of this PEP
+and described in detail in `this KnowledgeBase article
+<https://access.redhat.com/articles/2039753>`__. Red Hat's patches implementing
+this backport for Python 2.7.5 can be found in the `CentOS git repository
+<https://git.centos.org/commit/rpms!python.git/refs!heads!c7>`__.
 
-If a redistributor chooses to implement both recommendations, then the
-environment variable should take precedence over the system-wide configuration
-setting. This allows the setting to be changed for a given user, virtual
-environment or application, regardless of the system-wide default behaviour.
+
+Backporting this PEP to earlier Python versions
+===============================================
+
+The configuration file based backport described above is designed to cover
+backporting the PEP 476 changes to default certificate handling without the
+additional configuration mechanisms defined in this PEP.
+
+If this PEP is accepted, then an additional backporting option becomes
+available, which is to backport the per-process configuration mechanisms
+defined in this PEP, without backporting the ability to change the default behaviour of the overall Python installation.
+
+Such a backport would differ from the mechanism proposed in this PEP solely in
+the default behaviour when ``PYTHONHTTPSVERIFY`` was not set at all: it would
+continue to default to skipping certificate validation.
 
 In this case, if the ``PYTHONHTTPSVERIFY`` environment variable is defined, and
 set to anything *other* than ``'0'``, then HTTPS certificate verification
 should be enabled.
 
+
+Feature detection
+-----------------
+
+There's no specific attribute indicating that this situation applies. Rather,
+it is indicated by the ``ssl._verify_https_certificates`` and
+``ssl._https_verify_envvar`` attributes being present in a Python version that
+is nominally older than Python 2.7.9.
+
+Specification
+-------------
+
+Implementing this backport involves backporting the changes in PEP 466, 476 and
+this PEP, with the following change to the handling of the
+``PYTHONHTTPSVERIFY`` environment variable in the ``ssl`` module:
+
+* read the ``PYTHONHTTPSVERIFY`` environment variable when the module is first
+ imported into a Python process
+* set the ``ssl._create_default_https_context`` function to be an alias for
+ ``ssl.create_default_context`` if this environment variable is present
+ and set to any value other than ``'0'``
+* otherwise, set the ``ssl._create_default_https_context`` function to be an
+ alias for ``ssl._create_unverified_context``
+
+Example implementation
+----------------------
+
+::
+
+ _https_verify_envvar = 'PYTHONHTTPSVERIFY'
+
+ def _get_https_context_factory():
+ if not sys.flags.ignore_environment:
+ config_setting = os.environ.get(_https_verify_envvar)
+ if config_setting != '0':
+ return create_default_context
+ return _create_unverified_context
+
+ _create_default_https_context = _get_https_context_factory()
+
+ def _disable_https_default_verification():
+ """Skip verification of HTTPS certificates by default"""
+ global _create_default_https_context
+ _create_default_https_context = _create_unverified_context
+
+Security Considerations
+-----------------------
+
+This change would be a strict security upgrade for any Python version that
+currently defaults to skipping certificate validation in standard library
+HTTPS clients. The technical trade-offs to be taken into account relate largely
+to the magnitude of the PEP 466 backport also required rather than to anything
+security related.
+
+Interaction with Python virtual environments
+--------------------------------------------
+
+The default setting is read directly from the process environment, and hence
+works the same way regardless of whether or not the interpreter is being run
+inside an activated Python virtual environment.
+
+
+Recommendation for combined feature backports
+=============================================
+
+If a redistributor chooses to backport the environment variable based
+configuration setting from this PEP to a modified Python version that also
+implements the configuration file based PEP 476 , then the environment
+variable should take precedence over the system-wide configuration setting.
+This allows the setting to be changed for a given user or application,
+regardless of the installation-wide default behaviour.
+
 Example implementation
 ----------------------
 
-- 
Repository URL: https://hg.python.org/peps


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /