Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate Python2.6 by using Python3 on CentOS/RHEL 6 #5329

Merged
merged 28 commits into from
Jan 8, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dee46d8
If there's no python or there's only python2.6 on red hat systems, in…
ohemorange Dec 13, 2017
f60ff96
Always check for python2.6
ohemorange Dec 15, 2017
defd06b
address style, documentation, nits
ohemorange Dec 18, 2017
533b45c
factor out all initialization code
ohemorange Dec 20, 2017
694d7b1
fix up python version return value when no python installed
ohemorange Dec 20, 2017
a2c1e4b
add no python error and exit
ohemorange Dec 20, 2017
2b2b93f
document DeterminePythonVersion parameters
ohemorange Dec 20, 2017
8502502
build letsencrypt-auto
ohemorange Dec 20, 2017
4076ae7
close brace
ohemorange Dec 20, 2017
dd52dfa
build leauto
ohemorange Dec 20, 2017
6b5100d
Merge branch 'master' into killpy26
ohemorange Dec 20, 2017
48cbaf2
fix syntax errors
ohemorange Dec 21, 2017
f23dc97
set USE_PYTHON_3 for all cases
ohemorange Dec 21, 2017
eed279c
rip out NOCRASH
ohemorange Dec 21, 2017
07975a5
replace NOCRASH, update LE_PYTHON set logic
ohemorange Dec 21, 2017
c5102f1
use built-in venv for py3
ohemorange Dec 21, 2017
48f0cf1
switch to LE_PYTHON not affecting bootstrap selection and not overwri…
ohemorange Dec 21, 2017
173c819
python3ify fetch.py
ohemorange Dec 21, 2017
80ef7c6
get fetch.py working with python2 and 3
ohemorange Dec 21, 2017
5a58af7
don't verify server certificates in fetch.py HttpsGetter
ohemorange Jan 3, 2018
b11dec0
Merge branch 'master' into killpy26
ohemorange Jan 3, 2018
0e2b86d
Use SSLContext and an environment variable so that our tests continue…
ohemorange Jan 3, 2018
6c18b5b
typo
ohemorange Jan 3, 2018
21a56b3
build
ohemorange Jan 3, 2018
7344bb3
remove commented out code
ohemorange Jan 3, 2018
835e4c0
address review comments
ohemorange Jan 4, 2018
007383d
add documentation for YES_FLAG and QUIET_FLAG
ohemorange Jan 4, 2018
1d3141e
Add tests to centos6 Dockerfile to make sure we install python3 if an…
ohemorange Jan 5, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion letsencrypt-auto-source/Dockerfile.centos6
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ COPY . /home/lea/certbot/letsencrypt-auto-source
USER lea
WORKDIR /home/lea

CMD ["pytest", "-v", "-s", "certbot/letsencrypt-auto-source/tests"]
RUN sudo chmod +x certbot/letsencrypt-auto-source/tests/centos6_tests.sh
CMD sudo certbot/letsencrypt-auto-source/tests/centos6_tests.sh
205 changes: 150 additions & 55 deletions letsencrypt-auto-source/letsencrypt-auto
Original file line number Diff line number Diff line change
Expand Up @@ -244,15 +244,29 @@ DeprecationBootstrap() {
fi
}


# Sets LE_PYTHON to Python version string and PYVER to the first two
# digits of the python version
DeterminePythonVersion() {
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do
# Break (while keeping the LE_PYTHON value) if found.
$EXISTS "$LE_PYTHON" > /dev/null && break
done
# Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python
if [ -n "$USE_PYTHON_3" ]; then
for LE_PYTHON in "$LE_PYTHON" python3; do
# Break (while keeping the LE_PYTHON value) if found.
$EXISTS "$LE_PYTHON" > /dev/null && break
done
else
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do
# Break (while keeping the LE_PYTHON value) if found.
$EXISTS "$LE_PYTHON" > /dev/null && break
done
fi
if [ "$?" != "0" ]; then
error "Cannot find any Pythons; please install one!"
exit 1
if [ "$1" != "NOCRASH" ]; then
error "Cannot find any Pythons; please install one!"
exit 1
else
PYVER=0
return 0
fi
fi
export LE_PYTHON

Expand Down Expand Up @@ -384,39 +398,35 @@ BootstrapDebCommon() {
fi
}

# If new packages are installed by BootstrapRpmCommon below, this version
# number must be increased.
BOOTSTRAP_RPM_COMMON_VERSION=1

BootstrapRpmCommon() {
# Tested with:
# - Fedora 20, 21, 22, 23 (x64)
# - Centos 7 (x64: on DigitalOcean droplet)
# - CentOS 7 Minimal install in a Hyper-V VM
# - CentOS 6 (EPEL must be installed manually)
# If new packages are installed by BootstrapRpmCommonBase below, version
# numbers in rpm_common.sh and rpm_python3.sh must be increased.

# Sets TOOL to the name of the package manager
# Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG.
# Enables EPEL if applicable and possible.
InitializeRPMCommonBase() {
if type dnf 2>/dev/null
then
tool=dnf
TOOL=dnf
elif type yum 2>/dev/null
then
tool=yum
TOOL=yum

else
error "Neither yum nor dnf found. Aborting bootstrap!"
exit 1
fi

if [ "$ASSUME_YES" = 1 ]; then
yes_flag="-y"
YES_FLAG="-y"
fi
if [ "$QUIET" = 1 ]; then
QUIET_FLAG='--quiet'
fi

if ! $tool list *virtualenv >/dev/null 2>&1; then
if ! $TOOL list *virtualenv >/dev/null 2>&1; then
echo "To use Certbot, packages from the EPEL repository need to be installed."
if ! $tool list epel-release >/dev/null 2>&1; then
if ! $TOOL list epel-release >/dev/null 2>&1; then
error "Enable the EPEL repository and try running Certbot again."
exit 1
fi
Expand All @@ -428,11 +438,17 @@ BootstrapRpmCommon() {
/bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 seconds..."
sleep 1s
fi
if ! $tool install $yes_flag $QUIET_FLAG epel-release; then
if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then
error "Could not enable EPEL. Aborting bootstrap!"
exit 1
fi
fi
}

BootstrapRpmCommonBase() {
# Arguments: whitespace-delimited python packages to install

InitializeRPMCommonBase # This call is superfluous in practice

pkgs="
gcc
Expand All @@ -444,20 +460,48 @@ BootstrapRpmCommon() {
ca-certificates
"

# Most RPM distros use the "python" or "python-" naming convention. Let's try that first.
if $tool list python >/dev/null 2>&1; then
# Add the python packages
pkgs="$pkgs
$1
"

if $TOOL list installed "httpd" >/dev/null 2>&1; then
pkgs="$pkgs
python
mod_ssl
"
fi

if ! $TOOL install $YES_FLAG $QUIET_FLAG $pkgs; then
error "Could not install OS dependencies. Aborting bootstrap!"
exit 1
fi
}

# If new packages are installed by BootstrapRpmCommon below, this version
# number must be increased.
BOOTSTRAP_RPM_COMMON_VERSION=1

BootstrapRpmCommon() {
# Tested with:
# - Fedora 20, 21, 22, 23 (x64)
# - Centos 7 (x64: on DigitalOcean droplet)
# - CentOS 7 Minimal install in a Hyper-V VM
# - CentOS 6

InitializeRPMCommonBase

# Most RPM distros use the "python" or "python-" naming convention. Let's try that first.
if $TOOL list python >/dev/null 2>&1; then
python_pkgs="$python
python-devel
python-virtualenv
python-tools
python-pip
"
# Fedora 26 starts to use the prefix python2 for python2 based packages.
# this elseif is theoretically for any Fedora over version 26:
elif $tool list python2 >/dev/null 2>&1; then
pkgs="$pkgs
python2
elif $TOOL list python2 >/dev/null 2>&1; then
python_pkgs="$python2
python2-libs
python2-setuptools
python2-devel
Expand All @@ -468,25 +512,39 @@ BootstrapRpmCommon() {
# Some distros and older versions of current distros use a "python27"
# instead of the "python" or "python-" naming convention.
else
pkgs="$pkgs
python27
python_pkgs="$python27
python27-devel
python27-virtualenv
python27-tools
python27-pip
"
fi

if $tool list installed "httpd" >/dev/null 2>&1; then
pkgs="$pkgs
mod_ssl
"
fi
BootstrapRpmCommonBase "$python_pkgs"
}

if ! $tool install $yes_flag $QUIET_FLAG $pkgs; then
error "Could not install OS dependencies. Aborting bootstrap!"
# If new packages are installed by BootstrapRpmPython3 below, this version
# number must be increased.
BOOTSTRAP_RPM_PYTHON3_VERSION=1

BootstrapRpmPython3() {
# Tested with:
# - CentOS 6

InitializeRPMCommonBase

# EPEL uses python34
if $TOOL list python34 >/dev/null 2>&1; then
python_pkgs="python34
python34-devel
python34-tools
"
else
error "No supported Python package available to install. Aborting bootstrap!"
exit 1
fi

BootstrapRpmCommonBase "$python_pkgs"
}

# If new packages are installed by BootstrapSuseCommon below, this version
Expand Down Expand Up @@ -715,11 +773,24 @@ elif [ -f /etc/mageia-release ]; then
}
BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION"
elif [ -f /etc/redhat-release ]; then
Bootstrap() {
BootstrapMessage "RedHat-based OSes"
BootstrapRpmCommon
}
BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"
prev_le_python="$LE_PYTHON"
unset LE_PYTHON
DeterminePythonVersion "NOCRASH"
if [ "$PYVER" -eq 26 ]; then
Bootstrap() {
BootstrapMessage "RedHat-based OSes that will use Python3"
BootstrapRpmPython3
}
USE_PYTHON_3=1
BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION"
else
Bootstrap() {
BootstrapMessage "RedHat-based OSes"
BootstrapRpmCommon
}
BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"
fi
export LE_PYTHON="$prev_le_python"
elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then
Bootstrap() {
BootstrapMessage "openSUSE-based OSes"
Expand Down Expand Up @@ -858,10 +929,18 @@ if [ "$1" = "--le-auto-phase2" ]; then
say "Creating virtual environment..."
DeterminePythonVersion
rm -rf "$VENV_PATH"
if [ "$VERBOSE" = 1 ]; then
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH"
if [ "$PYVER" -le 27 ]; then
if [ "$VERBOSE" = 1 ]; then
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH"
else
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH" > /dev/null
fi
else
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH" > /dev/null
if [ "$VERBOSE" = 1 ]; then
"$LE_PYTHON" -m venv "$VENV_PATH"
else
"$LE_PYTHON" -m venv "$VENV_PATH" > /dev/null
fi
fi

if [ -n "$BOOTSTRAP_VERSION" ]; then
Expand Down Expand Up @@ -1356,17 +1435,22 @@ On failure, return non-zero.

"""

from __future__ import print_function
from __future__ import print_function, unicode_literals

from distutils.version import LooseVersion
from json import loads
from os import devnull, environ
from os.path import dirname, join
import re
import ssl
from subprocess import check_call, CalledProcessError
from sys import argv, exit
from urllib2 import build_opener, HTTPHandler, HTTPSHandler
from urllib2 import HTTPError, URLError
try:
from urllib2 import build_opener, HTTPHandler, HTTPSHandler
from urllib2 import HTTPError, URLError
except ImportError:
from urllib.request import build_opener, HTTPHandler, HTTPSHandler
from urllib.error import HTTPError, URLError

PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
Expand All @@ -1388,8 +1472,11 @@ class HttpsGetter(object):
def __init__(self):
"""Build an HTTPS opener."""
# Based on pip 1.4.1's URLOpener
# This verifies certs on only Python >=2.7.9.
self._opener = build_opener(HTTPSHandler())
# This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.
if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):
self._opener = build_opener(HTTPSHandler(context=create_CERT_NONE_context()))
else:
self._opener = build_opener(HTTPSHandler())
# Strip out HTTPHandler to prevent MITM spoof:
for handler in self._opener.handlers:
if isinstance(handler, HTTPHandler):
Expand All @@ -1411,21 +1498,21 @@ class HttpsGetter(object):

def write(contents, dir, filename):
"""Write something to a file in a certain directory."""
with open(join(dir, filename), 'w') as file:
with open(join(dir, filename), 'wb') as file:
file.write(contents)


def latest_stable_version(get):
"""Return the latest stable release of letsencrypt."""
metadata = loads(get(
environ.get('LE_AUTO_JSON_URL',
'https://pypi.python.org/pypi/certbot/json')))
'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8'))
# metadata['info']['version'] actually returns the latest of any kind of
# release release, contrary to https://wiki.python.org/moin/PyPIJSON.
# The regex is a sufficient regex for picking out prereleases for most
# packages, LE included.
return str(max(LooseVersion(r) for r
in metadata['releases'].iterkeys()
in iter(metadata['releases'].keys())
if re.match('^[0-9.]+$', r)))


Expand All @@ -1442,7 +1529,7 @@ def verified_new_le_auto(get, tag, temp_dir):
'letsencrypt-auto-source/') % tag
write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
write(PUBLIC_KEY, temp_dir, 'public_key.pem')
write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem')
try:
with open(devnull, 'w') as dev_null:
check_call(['openssl', 'dgst', '-sha256', '-verify',
Expand All @@ -1457,6 +1544,14 @@ def verified_new_le_auto(get, tag, temp_dir):
"certbot-auto.", exc)


def create_CERT_NONE_context():
"""Create a SSLContext object to not check hostname."""
# PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this.
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_NONE
return context


def main():
get = HttpsGetter().get
flag = argv[1]
Expand Down
Loading