PEP 493: Clarify scope & deemphasise PEP 476 backport

* Scope limitations now have their own section, rather than being
  part of the Rationale section
* reordered backport sections so PEP 493 backport is discussed
  prior to the PEP 476 backport
* made it explicit that the PEP 476 section is aimed at "*IF* you
  backport this feature, do it *this* way", so simply not implementing
  that section at all is entirely PEP compliant
This commit is contained in:
Nick Coghlan 2015-12-08 18:43:52 +10:00
parent efb59d3cd6
commit a0a5b34663
1 changed files with 118 additions and 106 deletions

View File

@ -76,17 +76,6 @@ 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 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
------------
@ -105,6 +94,21 @@ their customers. The main approaches available are:
regardless of the formal status of the PEP
Scope Limitations
=================
These changes 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 the
default certificate handling for secure protocols to be configurable on a
per-protocol basis, but that question is beyond the scope of this PEP.
Requirements for capability detection
=====================================
@ -124,6 +128,7 @@ distributions will offer them, only those that are providing a multi-stage
migration process from the original Python 2.7 HTTPS handling to the new
default behaviour.
Feature: Configuration API
==========================
@ -250,17 +255,99 @@ works the same way regardless of whether or not the interpreter is being run
inside an activated Python virtual environment.
Backporting this PEP to earlier Python versions
===============================================
If this PEP is accepted, then commercial Python redistributors may choose to
backport the per-process configuration mechanisms defined in this PEP to base
versions older than Python 2.7.9, *without* also backporting PEP 476's change
to 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._https_verify_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.
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
earlier Python 2 maintenance releases. In these cases, a configuration
mechanism is needed that provides:
The backporting approach described above leaves the default HTTPS certificate
verification behaviour of a Python 2.7 installation unmodified: verifying
certificates still needs to be opted into on a per-connection or per-process
basis.
To allow the default behaviour of the entire installation to be modified
without breaking backwards compatibility, Red Hat designed a configuration
mechanism for the system Python 2.7 installation in Red Hat Enterprise Linux
7.2+ that provides:
* an opt-in model that allows the decision to enable HTTPS certificate
verification to be made independently of the decision to upgrade to the
Python version where the feature was first backported
operating system version where the feature was first backported
* the ability for system administrators to set the default behaviour of Python
applications and scripts run directly in the system Python installation
* the ability for the redistributor to consider changing the default behaviour
@ -270,13 +357,19 @@ mechanism is needed that provides:
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.
a recommendation to other redistributors that choose to offer a similar feature
to their users.
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.
This PEP doesn't take a position on whether or not this particular change is a
good idea - rather, it suggests that *if* a redistributor chooses to go down
the path of making the default behaviour configurable in a version of Python
older than Python 2.7.9, then maintaining a consistent approach across
redistributors would be beneficial for users.
However, 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 verify
HTTPS certificates by default.
Feature detection
@ -392,7 +485,7 @@ locked down configuration:
escalation attacks)
The intent is that the *only* reason HTTPS verification should be getting
turned off system wide when using this approach is because:
turned off installation wide when using this approach is because:
* an end user is running a redistributor provided version of CPython rather
than running upstream CPython directly
@ -400,7 +493,7 @@ turned off system wide when using this approach is because:
verifying HTTPS certificates by default than that being provided by the
upstream project
* either the redistributor or the local infrastructure administrator has
determined that it is appropriate to override the default upstream behaviour
determined that it is appropriate to retaing the default pre-2.7.9 behaviour
(at least for the time being)
Using an administrator controlled configuration file rather than an environment
@ -425,93 +518,12 @@ 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>`__.
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._https_verify_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
implements the configuration file based PEP 476 backport, 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.