1
0
mirror of https://github.com/certbot/certbot.git synced 2025-08-06 16:42:41 +03:00

Release 0.21.0

This commit is contained in:
Brad Warren
2018-01-17 15:55:29 -08:00
parent 1bb2cfadf7
commit bf695d048d
22 changed files with 494 additions and 224 deletions

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi fi
VENV_BIN="$VENV_PATH/bin" VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.20.0" LE_AUTO_VERSION="0.21.0"
BASENAME=$(basename $0) BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS] USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -68,10 +68,12 @@ for arg in "$@" ; do
NO_BOOTSTRAP=1;; NO_BOOTSTRAP=1;;
--help) --help)
HELP=1;; HELP=1;;
--noninteractive|--non-interactive|renew) --noninteractive|--non-interactive)
ASSUME_YES=1;; NONINTERACTIVE=1;;
--quiet) --quiet)
QUIET=1;; QUIET=1;;
renew)
ASSUME_YES=1;;
--verbose) --verbose)
VERBOSE=1;; VERBOSE=1;;
-[!-]*) -[!-]*)
@@ -93,7 +95,7 @@ done
if [ $BASENAME = "letsencrypt-auto" ]; then if [ $BASENAME = "letsencrypt-auto" ]; then
# letsencrypt-auto does not respect --help or --yes for backwards compatibility # letsencrypt-auto does not respect --help or --yes for backwards compatibility
ASSUME_YES=1 NONINTERACTIVE=1
HELP=0 HELP=0
fi fi
@@ -244,23 +246,42 @@ DeprecationBootstrap() {
fi fi
} }
MIN_PYTHON_VERSION="2.6"
MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//')
# Sets LE_PYTHON to Python version string and PYVER to the first two
# digits of the python version
DeterminePythonVersion() { DeterminePythonVersion() {
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python
# Break (while keeping the LE_PYTHON value) if found. #
$EXISTS "$LE_PYTHON" > /dev/null && break # If no Python is found, PYVER is set to 0.
done if [ "$USE_PYTHON_3" = 1 ]; then
if [ "$?" != "0" ]; then for LE_PYTHON in "$LE_PYTHON" python3; do
error "Cannot find any Pythons; please install one!" # Break (while keeping the LE_PYTHON value) if found.
exit 1 $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
if [ "$1" != "NOCRASH" ]; then
error "Cannot find any Pythons; please install one!"
exit 1
else
PYVER=0
return 0
fi
fi fi
export LE_PYTHON
PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
if [ "$PYVER" -lt 26 ]; then if [ "$PYVER" -lt "$MIN_PYVER" ]; then
error "You have an ancient version of Python entombed in your operating system..." if [ "$1" != "NOCRASH" ]; then
error "This isn't going to work; you'll need at least version 2.6." error "You have an ancient version of Python entombed in your operating system..."
exit 1 error "This isn't going to work; you'll need at least version $MIN_PYTHON_VERSION."
exit 1
fi
fi fi
} }
@@ -384,23 +405,19 @@ BootstrapDebCommon() {
fi fi
} }
# If new packages are installed by BootstrapRpmCommon below, this version # If new packages are installed by BootstrapRpmCommonBase below, version
# number must be increased. # numbers in rpm_common.sh and rpm_python3.sh 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)
# 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 if type dnf 2>/dev/null
then then
tool=dnf TOOL=dnf
elif type yum 2>/dev/null elif type yum 2>/dev/null
then then
tool=yum TOOL=yum
else else
error "Neither yum nor dnf found. Aborting bootstrap!" error "Neither yum nor dnf found. Aborting bootstrap!"
@@ -408,15 +425,15 @@ BootstrapRpmCommon() {
fi fi
if [ "$ASSUME_YES" = 1 ]; then if [ "$ASSUME_YES" = 1 ]; then
yes_flag="-y" YES_FLAG="-y"
fi fi
if [ "$QUIET" = 1 ]; then if [ "$QUIET" = 1 ]; then
QUIET_FLAG='--quiet' QUIET_FLAG='--quiet'
fi 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." 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." error "Enable the EPEL repository and try running Certbot again."
exit 1 exit 1
fi fi
@@ -425,14 +442,20 @@ BootstrapRpmCommon() {
sleep 1s sleep 1s
/bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..."
sleep 1s sleep 1s
/bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 seconds..." /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..."
sleep 1s sleep 1s
fi 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!" error "Could not enable EPEL. Aborting bootstrap!"
exit 1 exit 1
fi fi
fi fi
}
BootstrapRpmCommonBase() {
# Arguments: whitespace-delimited python packages to install
InitializeRPMCommonBase # This call is superfluous in practice
pkgs=" pkgs="
gcc gcc
@@ -444,10 +467,39 @@ BootstrapRpmCommon() {
ca-certificates ca-certificates
" "
# Most RPM distros use the "python" or "python-" naming convention. Let's try that first. # Add the python packages
if $tool list python >/dev/null 2>&1; then pkgs="$pkgs
$1
"
if $TOOL list installed "httpd" >/dev/null 2>&1; then
pkgs="$pkgs 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-devel
python-virtualenv python-virtualenv
python-tools python-tools
@@ -455,9 +507,8 @@ BootstrapRpmCommon() {
" "
# Fedora 26 starts to use the prefix python2 for python2 based packages. # Fedora 26 starts to use the prefix python2 for python2 based packages.
# this elseif is theoretically for any Fedora over version 26: # this elseif is theoretically for any Fedora over version 26:
elif $tool list python2 >/dev/null 2>&1; then elif $TOOL list python2 >/dev/null 2>&1; then
pkgs="$pkgs python_pkgs="$python2
python2
python2-libs python2-libs
python2-setuptools python2-setuptools
python2-devel python2-devel
@@ -468,8 +519,7 @@ BootstrapRpmCommon() {
# Some distros and older versions of current distros use a "python27" # Some distros and older versions of current distros use a "python27"
# instead of the "python" or "python-" naming convention. # instead of the "python" or "python-" naming convention.
else else
pkgs="$pkgs python_pkgs="$python27
python27
python27-devel python27-devel
python27-virtualenv python27-virtualenv
python27-tools python27-tools
@@ -477,16 +527,31 @@ BootstrapRpmCommon() {
" "
fi fi
if $tool list installed "httpd" >/dev/null 2>&1; then BootstrapRpmCommonBase "$python_pkgs"
pkgs="$pkgs }
mod_ssl
"
fi
if ! $tool install $yes_flag $QUIET_FLAG $pkgs; then # If new packages are installed by BootstrapRpmPython3 below, this version
error "Could not install OS dependencies. Aborting bootstrap!" # 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 exit 1
fi fi
BootstrapRpmCommonBase "$python_pkgs"
} }
# If new packages are installed by BootstrapSuseCommon below, this version # If new packages are installed by BootstrapSuseCommon below, this version
@@ -715,11 +780,27 @@ elif [ -f /etc/mageia-release ]; then
} }
BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION" BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION"
elif [ -f /etc/redhat-release ]; then elif [ -f /etc/redhat-release ]; then
Bootstrap() { # Run DeterminePythonVersion to decide on the basis of available Python versions
BootstrapMessage "RedHat-based OSes" # whether to use 2.x or 3.x on RedHat-like systems.
BootstrapRpmCommon # Then, revert LE_PYTHON to its previous state.
} prev_le_python="$LE_PYTHON"
BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" 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
LE_PYTHON="$prev_le_python"
elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then
Bootstrap() { Bootstrap() {
BootstrapMessage "openSUSE-based OSes" BootstrapMessage "openSUSE-based OSes"
@@ -816,7 +897,11 @@ TempDir() {
mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS
} }
# Returns 0 if a letsencrypt installation exists at $OLD_VENV_PATH, otherwise,
# returns a non-zero number.
OldVenvExists() {
[ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ]
}
if [ "$1" = "--le-auto-phase2" ]; then if [ "$1" = "--le-auto-phase2" ]; then
# Phase 2: Create venv, install LE, and run. # Phase 2: Create venv, install LE, and run.
@@ -824,14 +909,26 @@ if [ "$1" = "--le-auto-phase2" ]; then
shift 1 # the --le-auto-phase2 arg shift 1 # the --le-auto-phase2 arg
SetPrevBootstrapVersion SetPrevBootstrapVersion
if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then
unset LE_PYTHON
fi
INSTALLED_VERSION="none" INSTALLED_VERSION="none"
if [ -d "$VENV_PATH" ]; then if [ -d "$VENV_PATH" ] || OldVenvExists; then
# If the selected Bootstrap function isn't a noop and it differs from the # If the selected Bootstrap function isn't a noop and it differs from the
# previously used version # previously used version
if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then
# if non-interactive mode or stdin and stdout are connected to a terminal # if non-interactive mode or stdin and stdout are connected to a terminal
if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then
rm -rf "$VENV_PATH" if [ -d "$VENV_PATH" ]; then
rm -rf "$VENV_PATH"
fi
# In the case the old venv was just a symlink to the new one,
# OldVenvExists is now false because we deleted the venv at VENV_PATH.
if OldVenvExists; then
rm -rf "$OLD_VENV_PATH"
ln -s "$VENV_PATH" "$OLD_VENV_PATH"
fi
RerunWithArgs "$@" RerunWithArgs "$@"
else else
error "Skipping upgrade because new OS dependencies may need to be installed." error "Skipping upgrade because new OS dependencies may need to be installed."
@@ -841,6 +938,10 @@ if [ "$1" = "--le-auto-phase2" ]; then
error "install any required packages." error "install any required packages."
# Set INSTALLED_VERSION to be the same so we don't update the venv # Set INSTALLED_VERSION to be the same so we don't update the venv
INSTALLED_VERSION="$LE_AUTO_VERSION" INSTALLED_VERSION="$LE_AUTO_VERSION"
# Continue to use OLD_VENV_PATH if the new venv doesn't exist
if [ ! -d "$VENV_PATH" ]; then
VENV_BIN="$OLD_VENV_PATH/bin"
fi
fi fi
elif [ -f "$VENV_BIN/letsencrypt" ]; then elif [ -f "$VENV_BIN/letsencrypt" ]; then
# --version output ran through grep due to python-cryptography DeprecationWarnings # --version output ran through grep due to python-cryptography DeprecationWarnings
@@ -858,10 +959,18 @@ if [ "$1" = "--le-auto-phase2" ]; then
say "Creating virtual environment..." say "Creating virtual environment..."
DeterminePythonVersion DeterminePythonVersion
rm -rf "$VENV_PATH" rm -rf "$VENV_PATH"
if [ "$VERBOSE" = 1 ]; then if [ "$PYVER" -le 27 ]; then
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH" 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 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 fi
if [ -n "$BOOTSTRAP_VERSION" ]; then if [ -n "$BOOTSTRAP_VERSION" ]; then
@@ -983,9 +1092,16 @@ idna==2.5 \
ipaddress==1.0.16 \ ipaddress==1.0.16 \
--hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \ --hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \
--hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0 --hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0
josepy==1.0.1 \
--hash=sha256:354a3513038a38bbcd27c97b7c68a8f3dfaff0a135b20a92c6db4cc4ea72915e \
--hash=sha256:9f48b88ca37f0244238b1cc77723989f7c54f7b90b2eee6294390bacfe870acc
linecache2==1.0.0 \ linecache2==1.0.0 \
--hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \ --hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \
--hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c --hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c
# Using an older version of mock here prevents regressions of #5276.
mock==1.3.0 \
--hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
--hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
ordereddict==1.1 \ ordereddict==1.1 \
--hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f --hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f
packaging==16.8 \ packaging==16.8 \
@@ -1062,10 +1178,6 @@ zope.interface==4.1.3 \
--hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \ --hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \
--hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \ --hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \
--hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392 --hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392
# Using an older version of mock here prevents regressions of #5276.
mock==1.3.0 \
--hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
--hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
# Contains the requirements for the letsencrypt package. # Contains the requirements for the letsencrypt package.
# #
@@ -1078,18 +1190,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.20.0 \ certbot==0.21.0 \
--hash=sha256:c6b6bd288700898d1eb31a65b605e3a5fc10f1e3213ce468207d76a2decb9d35 \ --hash=sha256:b6fc9cf80e8e2925827c61ca92c32faa935bbadaf14448e2d7f40e1f8f2cccdb \
--hash=sha256:cabf505b64fb400c4239dcdbaeb882079477eb6a8442268596a8791b9e34de88 --hash=sha256:07ca3246d3462fe73418113cc5c1036545f4b2312831024da923054de3a85857
acme==0.20.0 \ acme==0.21.0 \
--hash=sha256:8b0cee192c0d76d6f4045bdb14b3cfd29d9720e0dad2046794a2a555f1eaccb7 \ --hash=sha256:4ef91a62c30b9d6bd1dd0b5ac3a8c7e70203e08e5269d3d26311dd6648aaacda \
--hash=sha256:45121aed6c8cc2f31896ac1083068dfdeb613f3edeff9576dc0d10632ea5a3d5 --hash=sha256:d64eae267c0bb21c98fa889b4e0be4c473ca8e80488d3de057e803d6d167544d
certbot-apache==0.20.0 \ certbot-apache==0.21.0 \
--hash=sha256:f7e4dbc154d2e9d1461118b6dd3dbd16f6892da468f060eeaa162aff673347e2 \ --hash=sha256:026c23fec4def727f88acd15f66b5641f7ba1f767f0728fd56798cf3500be0c5 \
--hash=sha256:0ba499706451ffbccb172bcf93d6ef4c6cc8599157077a4fa6dfbe5a83c7921f --hash=sha256:185dae50c680fa3c09646907a6256c6b4ddf8525723d3b13b9b33d1a3118663b
certbot-nginx==0.20.0 \ certbot-nginx==0.21.0 \
--hash=sha256:b6e372e8740b20dd9bd63837646157ac97b3c9a65affd3954571b8e872ae9ecf \ --hash=sha256:e5ac3a203871f13e7e72d4922e401364342f2999d130c959f90949305c33d2bc \
--hash=sha256:6379fdf20d9a7651fe30bb8d4b828cbea178cc263d7af5a380fc4508d793b9ae --hash=sha256:88be95916935980edc4c6ec3f39031ac47f5b73d6e43dfa3694b927226432642
UNLIKELY_EOF UNLIKELY_EOF
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@@ -1319,9 +1431,10 @@ else
# upgrading. Phase 1 checks the version of the latest release of # upgrading. Phase 1 checks the version of the latest release of
# certbot-auto (which is always the same as that of the certbot # certbot-auto (which is always the same as that of the certbot
# package). Phase 2 checks the version of the locally installed certbot. # package). Phase 2 checks the version of the locally installed certbot.
export PHASE_1_VERSION="$LE_AUTO_VERSION"
if [ ! -f "$VENV_BIN/letsencrypt" ]; then if [ ! -f "$VENV_BIN/letsencrypt" ]; then
if [ -z "$OLD_VENV_PATH" -o ! -f "$OLD_VENV_PATH/bin/letsencrypt" ]; then if ! OldVenvExists; then
if [ "$HELP" = 1 ]; then if [ "$HELP" = 1 ]; then
echo "$USAGE" echo "$USAGE"
exit 0 exit 0
@@ -1353,17 +1466,22 @@ On failure, return non-zero.
""" """
from __future__ import print_function from __future__ import print_function, unicode_literals
from distutils.version import LooseVersion from distutils.version import LooseVersion
from json import loads from json import loads
from os import devnull, environ from os import devnull, environ
from os.path import dirname, join from os.path import dirname, join
import re import re
import ssl
from subprocess import check_call, CalledProcessError from subprocess import check_call, CalledProcessError
from sys import argv, exit from sys import argv, exit
from urllib2 import build_opener, HTTPHandler, HTTPSHandler try:
from urllib2 import HTTPError, URLError 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----- PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
@@ -1385,8 +1503,11 @@ class HttpsGetter(object):
def __init__(self): def __init__(self):
"""Build an HTTPS opener.""" """Build an HTTPS opener."""
# Based on pip 1.4.1's URLOpener # Based on pip 1.4.1's URLOpener
# This verifies certs on only Python >=2.7.9. # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.
self._opener = build_opener(HTTPSHandler()) if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):
self._opener = build_opener(HTTPSHandler(context=cert_none_context()))
else:
self._opener = build_opener(HTTPSHandler())
# Strip out HTTPHandler to prevent MITM spoof: # Strip out HTTPHandler to prevent MITM spoof:
for handler in self._opener.handlers: for handler in self._opener.handlers:
if isinstance(handler, HTTPHandler): if isinstance(handler, HTTPHandler):
@@ -1408,7 +1529,7 @@ class HttpsGetter(object):
def write(contents, dir, filename): def write(contents, dir, filename):
"""Write something to a file in a certain directory.""" """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) file.write(contents)
@@ -1416,13 +1537,13 @@ def latest_stable_version(get):
"""Return the latest stable release of letsencrypt.""" """Return the latest stable release of letsencrypt."""
metadata = loads(get( metadata = loads(get(
environ.get('LE_AUTO_JSON_URL', 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 # metadata['info']['version'] actually returns the latest of any kind of
# release release, contrary to https://wiki.python.org/moin/PyPIJSON. # release release, contrary to https://wiki.python.org/moin/PyPIJSON.
# The regex is a sufficient regex for picking out prereleases for most # The regex is a sufficient regex for picking out prereleases for most
# packages, LE included. # packages, LE included.
return str(max(LooseVersion(r) for r return str(max(LooseVersion(r) for r
in metadata['releases'].iterkeys() in metadata['releases'].keys()
if re.match('^[0-9.]+$', r))) if re.match('^[0-9.]+$', r)))
@@ -1439,7 +1560,7 @@ def verified_new_le_auto(get, tag, temp_dir):
'letsencrypt-auto-source/') % tag 'letsencrypt-auto-source/') % tag
write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto') 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(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: try:
with open(devnull, 'w') as dev_null: with open(devnull, 'w') as dev_null:
check_call(['openssl', 'dgst', '-sha256', '-verify', check_call(['openssl', 'dgst', '-sha256', '-verify',
@@ -1454,6 +1575,14 @@ def verified_new_le_auto(get, tag, temp_dir):
"certbot-auto.", exc) "certbot-auto.", exc)
def 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(): def main():
get = HttpsGetter().get get = HttpsGetter().get
flag = argv[1] flag = argv[1]
@@ -1475,8 +1604,10 @@ if __name__ == '__main__':
UNLIKELY_EOF UNLIKELY_EOF
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
DeterminePythonVersion DeterminePythonVersion "NOCRASH"
if ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then if [ "$PYVER" -lt "$MIN_PYVER" ]; then
error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates."
elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then
error "WARNING: unable to check for updates." error "WARNING: unable to check for updates."
elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
install_requires = [ install_requires = [
'certbot', 'certbot',

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -3,7 +3,7 @@ import sys
from distutils.core import setup from distutils.core import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
install_requires = [ install_requires = [
'acme=={0}'.format(version), 'acme=={0}'.format(version),

View File

@@ -4,7 +4,7 @@ from setuptools import setup
from setuptools import find_packages from setuptools import find_packages
version = '0.21.0.dev0' version = '0.21.0'
# Please update tox.ini when modifying dependency version requirements # Please update tox.ini when modifying dependency version requirements
install_requires = [ install_requires = [

View File

@@ -1,4 +1,4 @@
"""Certbot client.""" """Certbot client."""
# version number like 1.2.3a0, must have at least 2 parts, like 1.2 # version number like 1.2.3a0, must have at least 2 parts, like 1.2
__version__ = '0.21.0.dev0' __version__ = '0.21.0'

View File

@@ -107,7 +107,7 @@ optional arguments:
case, and to know when to deprecate support for past case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/0.20.0 (certbot; "". (default: CertbotACMEClient/0.21.0 (certbot;
Ubuntu 16.04.3 LTS) Authenticator/XXX Installer/YYY Ubuntu 16.04.3 LTS) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/2.7.12). The flags (SUBCOMMAND; flags: FLAGS) Py/2.7.12). The flags
encoded in the user agent are: --duplicate, --force- encoded in the user agent are: --duplicate, --force-
@@ -331,6 +331,14 @@ revoke:
--reason {unspecified,keycompromise,affiliationchanged,superseded,cessationofoperation} --reason {unspecified,keycompromise,affiliationchanged,superseded,cessationofoperation}
Specify reason for revoking certificate. (default: Specify reason for revoking certificate. (default:
unspecified) unspecified)
--delete-after-revoke
Delete certificates after revoking them. (default:
None)
--no-delete-after-revoke
Do not delete certificates after revoking them. This
option should be used with caution because the 'renew'
subcommand will attempt to renew undeleted revoked
certificates. (default: None)
register: register:
Options for account registration & modification Options for account registration & modification

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi fi
VENV_BIN="$VENV_PATH/bin" VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.20.0" LE_AUTO_VERSION="0.21.0"
BASENAME=$(basename $0) BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS] USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -68,10 +68,12 @@ for arg in "$@" ; do
NO_BOOTSTRAP=1;; NO_BOOTSTRAP=1;;
--help) --help)
HELP=1;; HELP=1;;
--noninteractive|--non-interactive|renew) --noninteractive|--non-interactive)
ASSUME_YES=1;; NONINTERACTIVE=1;;
--quiet) --quiet)
QUIET=1;; QUIET=1;;
renew)
ASSUME_YES=1;;
--verbose) --verbose)
VERBOSE=1;; VERBOSE=1;;
-[!-]*) -[!-]*)
@@ -93,7 +95,7 @@ done
if [ $BASENAME = "letsencrypt-auto" ]; then if [ $BASENAME = "letsencrypt-auto" ]; then
# letsencrypt-auto does not respect --help or --yes for backwards compatibility # letsencrypt-auto does not respect --help or --yes for backwards compatibility
ASSUME_YES=1 NONINTERACTIVE=1
HELP=0 HELP=0
fi fi
@@ -244,23 +246,42 @@ DeprecationBootstrap() {
fi fi
} }
MIN_PYTHON_VERSION="2.6"
MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//')
# Sets LE_PYTHON to Python version string and PYVER to the first two
# digits of the python version
DeterminePythonVersion() { DeterminePythonVersion() {
for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python
# Break (while keeping the LE_PYTHON value) if found. #
$EXISTS "$LE_PYTHON" > /dev/null && break # If no Python is found, PYVER is set to 0.
done if [ "$USE_PYTHON_3" = 1 ]; then
if [ "$?" != "0" ]; then for LE_PYTHON in "$LE_PYTHON" python3; do
error "Cannot find any Pythons; please install one!" # Break (while keeping the LE_PYTHON value) if found.
exit 1 $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
if [ "$1" != "NOCRASH" ]; then
error "Cannot find any Pythons; please install one!"
exit 1
else
PYVER=0
return 0
fi
fi fi
export LE_PYTHON
PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
if [ "$PYVER" -lt 26 ]; then if [ "$PYVER" -lt "$MIN_PYVER" ]; then
error "You have an ancient version of Python entombed in your operating system..." if [ "$1" != "NOCRASH" ]; then
error "This isn't going to work; you'll need at least version 2.6." error "You have an ancient version of Python entombed in your operating system..."
exit 1 error "This isn't going to work; you'll need at least version $MIN_PYTHON_VERSION."
exit 1
fi
fi fi
} }
@@ -384,23 +405,19 @@ BootstrapDebCommon() {
fi fi
} }
# If new packages are installed by BootstrapRpmCommon below, this version # If new packages are installed by BootstrapRpmCommonBase below, version
# number must be increased. # numbers in rpm_common.sh and rpm_python3.sh 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)
# 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 if type dnf 2>/dev/null
then then
tool=dnf TOOL=dnf
elif type yum 2>/dev/null elif type yum 2>/dev/null
then then
tool=yum TOOL=yum
else else
error "Neither yum nor dnf found. Aborting bootstrap!" error "Neither yum nor dnf found. Aborting bootstrap!"
@@ -408,15 +425,15 @@ BootstrapRpmCommon() {
fi fi
if [ "$ASSUME_YES" = 1 ]; then if [ "$ASSUME_YES" = 1 ]; then
yes_flag="-y" YES_FLAG="-y"
fi fi
if [ "$QUIET" = 1 ]; then if [ "$QUIET" = 1 ]; then
QUIET_FLAG='--quiet' QUIET_FLAG='--quiet'
fi 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." 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." error "Enable the EPEL repository and try running Certbot again."
exit 1 exit 1
fi fi
@@ -425,14 +442,20 @@ BootstrapRpmCommon() {
sleep 1s sleep 1s
/bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..." /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..."
sleep 1s sleep 1s
/bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 seconds..." /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..."
sleep 1s sleep 1s
fi 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!" error "Could not enable EPEL. Aborting bootstrap!"
exit 1 exit 1
fi fi
fi fi
}
BootstrapRpmCommonBase() {
# Arguments: whitespace-delimited python packages to install
InitializeRPMCommonBase # This call is superfluous in practice
pkgs=" pkgs="
gcc gcc
@@ -444,10 +467,39 @@ BootstrapRpmCommon() {
ca-certificates ca-certificates
" "
# Most RPM distros use the "python" or "python-" naming convention. Let's try that first. # Add the python packages
if $tool list python >/dev/null 2>&1; then pkgs="$pkgs
$1
"
if $TOOL list installed "httpd" >/dev/null 2>&1; then
pkgs="$pkgs 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-devel
python-virtualenv python-virtualenv
python-tools python-tools
@@ -455,9 +507,8 @@ BootstrapRpmCommon() {
" "
# Fedora 26 starts to use the prefix python2 for python2 based packages. # Fedora 26 starts to use the prefix python2 for python2 based packages.
# this elseif is theoretically for any Fedora over version 26: # this elseif is theoretically for any Fedora over version 26:
elif $tool list python2 >/dev/null 2>&1; then elif $TOOL list python2 >/dev/null 2>&1; then
pkgs="$pkgs python_pkgs="$python2
python2
python2-libs python2-libs
python2-setuptools python2-setuptools
python2-devel python2-devel
@@ -468,8 +519,7 @@ BootstrapRpmCommon() {
# Some distros and older versions of current distros use a "python27" # Some distros and older versions of current distros use a "python27"
# instead of the "python" or "python-" naming convention. # instead of the "python" or "python-" naming convention.
else else
pkgs="$pkgs python_pkgs="$python27
python27
python27-devel python27-devel
python27-virtualenv python27-virtualenv
python27-tools python27-tools
@@ -477,16 +527,31 @@ BootstrapRpmCommon() {
" "
fi fi
if $tool list installed "httpd" >/dev/null 2>&1; then BootstrapRpmCommonBase "$python_pkgs"
pkgs="$pkgs }
mod_ssl
"
fi
if ! $tool install $yes_flag $QUIET_FLAG $pkgs; then # If new packages are installed by BootstrapRpmPython3 below, this version
error "Could not install OS dependencies. Aborting bootstrap!" # 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 exit 1
fi fi
BootstrapRpmCommonBase "$python_pkgs"
} }
# If new packages are installed by BootstrapSuseCommon below, this version # If new packages are installed by BootstrapSuseCommon below, this version
@@ -715,11 +780,27 @@ elif [ -f /etc/mageia-release ]; then
} }
BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION" BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION"
elif [ -f /etc/redhat-release ]; then elif [ -f /etc/redhat-release ]; then
Bootstrap() { # Run DeterminePythonVersion to decide on the basis of available Python versions
BootstrapMessage "RedHat-based OSes" # whether to use 2.x or 3.x on RedHat-like systems.
BootstrapRpmCommon # Then, revert LE_PYTHON to its previous state.
} prev_le_python="$LE_PYTHON"
BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION" 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
LE_PYTHON="$prev_le_python"
elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then
Bootstrap() { Bootstrap() {
BootstrapMessage "openSUSE-based OSes" BootstrapMessage "openSUSE-based OSes"
@@ -816,7 +897,11 @@ TempDir() {
mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS
} }
# Returns 0 if a letsencrypt installation exists at $OLD_VENV_PATH, otherwise,
# returns a non-zero number.
OldVenvExists() {
[ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ]
}
if [ "$1" = "--le-auto-phase2" ]; then if [ "$1" = "--le-auto-phase2" ]; then
# Phase 2: Create venv, install LE, and run. # Phase 2: Create venv, install LE, and run.
@@ -824,14 +909,26 @@ if [ "$1" = "--le-auto-phase2" ]; then
shift 1 # the --le-auto-phase2 arg shift 1 # the --le-auto-phase2 arg
SetPrevBootstrapVersion SetPrevBootstrapVersion
if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then
unset LE_PYTHON
fi
INSTALLED_VERSION="none" INSTALLED_VERSION="none"
if [ -d "$VENV_PATH" ]; then if [ -d "$VENV_PATH" ] || OldVenvExists; then
# If the selected Bootstrap function isn't a noop and it differs from the # If the selected Bootstrap function isn't a noop and it differs from the
# previously used version # previously used version
if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then
# if non-interactive mode or stdin and stdout are connected to a terminal # if non-interactive mode or stdin and stdout are connected to a terminal
if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then
rm -rf "$VENV_PATH" if [ -d "$VENV_PATH" ]; then
rm -rf "$VENV_PATH"
fi
# In the case the old venv was just a symlink to the new one,
# OldVenvExists is now false because we deleted the venv at VENV_PATH.
if OldVenvExists; then
rm -rf "$OLD_VENV_PATH"
ln -s "$VENV_PATH" "$OLD_VENV_PATH"
fi
RerunWithArgs "$@" RerunWithArgs "$@"
else else
error "Skipping upgrade because new OS dependencies may need to be installed." error "Skipping upgrade because new OS dependencies may need to be installed."
@@ -841,6 +938,10 @@ if [ "$1" = "--le-auto-phase2" ]; then
error "install any required packages." error "install any required packages."
# Set INSTALLED_VERSION to be the same so we don't update the venv # Set INSTALLED_VERSION to be the same so we don't update the venv
INSTALLED_VERSION="$LE_AUTO_VERSION" INSTALLED_VERSION="$LE_AUTO_VERSION"
# Continue to use OLD_VENV_PATH if the new venv doesn't exist
if [ ! -d "$VENV_PATH" ]; then
VENV_BIN="$OLD_VENV_PATH/bin"
fi
fi fi
elif [ -f "$VENV_BIN/letsencrypt" ]; then elif [ -f "$VENV_BIN/letsencrypt" ]; then
# --version output ran through grep due to python-cryptography DeprecationWarnings # --version output ran through grep due to python-cryptography DeprecationWarnings
@@ -858,10 +959,18 @@ if [ "$1" = "--le-auto-phase2" ]; then
say "Creating virtual environment..." say "Creating virtual environment..."
DeterminePythonVersion DeterminePythonVersion
rm -rf "$VENV_PATH" rm -rf "$VENV_PATH"
if [ "$VERBOSE" = 1 ]; then if [ "$PYVER" -le 27 ]; then
virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH" 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 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 fi
if [ -n "$BOOTSTRAP_VERSION" ]; then if [ -n "$BOOTSTRAP_VERSION" ]; then
@@ -983,9 +1092,16 @@ idna==2.5 \
ipaddress==1.0.16 \ ipaddress==1.0.16 \
--hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \ --hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \
--hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0 --hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0
josepy==1.0.1 \
--hash=sha256:354a3513038a38bbcd27c97b7c68a8f3dfaff0a135b20a92c6db4cc4ea72915e \
--hash=sha256:9f48b88ca37f0244238b1cc77723989f7c54f7b90b2eee6294390bacfe870acc
linecache2==1.0.0 \ linecache2==1.0.0 \
--hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \ --hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \
--hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c --hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c
# Using an older version of mock here prevents regressions of #5276.
mock==1.3.0 \
--hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
--hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
ordereddict==1.1 \ ordereddict==1.1 \
--hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f --hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f
packaging==16.8 \ packaging==16.8 \
@@ -1062,10 +1178,6 @@ zope.interface==4.1.3 \
--hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \ --hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \
--hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \ --hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \
--hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392 --hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392
# Using an older version of mock here prevents regressions of #5276.
mock==1.3.0 \
--hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
--hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
# Contains the requirements for the letsencrypt package. # Contains the requirements for the letsencrypt package.
# #
@@ -1078,18 +1190,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.20.0 \ certbot==0.21.0 \
--hash=sha256:c6b6bd288700898d1eb31a65b605e3a5fc10f1e3213ce468207d76a2decb9d35 \ --hash=sha256:b6fc9cf80e8e2925827c61ca92c32faa935bbadaf14448e2d7f40e1f8f2cccdb \
--hash=sha256:cabf505b64fb400c4239dcdbaeb882079477eb6a8442268596a8791b9e34de88 --hash=sha256:07ca3246d3462fe73418113cc5c1036545f4b2312831024da923054de3a85857
acme==0.20.0 \ acme==0.21.0 \
--hash=sha256:8b0cee192c0d76d6f4045bdb14b3cfd29d9720e0dad2046794a2a555f1eaccb7 \ --hash=sha256:4ef91a62c30b9d6bd1dd0b5ac3a8c7e70203e08e5269d3d26311dd6648aaacda \
--hash=sha256:45121aed6c8cc2f31896ac1083068dfdeb613f3edeff9576dc0d10632ea5a3d5 --hash=sha256:d64eae267c0bb21c98fa889b4e0be4c473ca8e80488d3de057e803d6d167544d
certbot-apache==0.20.0 \ certbot-apache==0.21.0 \
--hash=sha256:f7e4dbc154d2e9d1461118b6dd3dbd16f6892da468f060eeaa162aff673347e2 \ --hash=sha256:026c23fec4def727f88acd15f66b5641f7ba1f767f0728fd56798cf3500be0c5 \
--hash=sha256:0ba499706451ffbccb172bcf93d6ef4c6cc8599157077a4fa6dfbe5a83c7921f --hash=sha256:185dae50c680fa3c09646907a6256c6b4ddf8525723d3b13b9b33d1a3118663b
certbot-nginx==0.20.0 \ certbot-nginx==0.21.0 \
--hash=sha256:b6e372e8740b20dd9bd63837646157ac97b3c9a65affd3954571b8e872ae9ecf \ --hash=sha256:e5ac3a203871f13e7e72d4922e401364342f2999d130c959f90949305c33d2bc \
--hash=sha256:6379fdf20d9a7651fe30bb8d4b828cbea178cc263d7af5a380fc4508d793b9ae --hash=sha256:88be95916935980edc4c6ec3f39031ac47f5b73d6e43dfa3694b927226432642
UNLIKELY_EOF UNLIKELY_EOF
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
@@ -1319,9 +1431,10 @@ else
# upgrading. Phase 1 checks the version of the latest release of # upgrading. Phase 1 checks the version of the latest release of
# certbot-auto (which is always the same as that of the certbot # certbot-auto (which is always the same as that of the certbot
# package). Phase 2 checks the version of the locally installed certbot. # package). Phase 2 checks the version of the locally installed certbot.
export PHASE_1_VERSION="$LE_AUTO_VERSION"
if [ ! -f "$VENV_BIN/letsencrypt" ]; then if [ ! -f "$VENV_BIN/letsencrypt" ]; then
if [ -z "$OLD_VENV_PATH" -o ! -f "$OLD_VENV_PATH/bin/letsencrypt" ]; then if ! OldVenvExists; then
if [ "$HELP" = 1 ]; then if [ "$HELP" = 1 ]; then
echo "$USAGE" echo "$USAGE"
exit 0 exit 0
@@ -1353,17 +1466,22 @@ On failure, return non-zero.
""" """
from __future__ import print_function from __future__ import print_function, unicode_literals
from distutils.version import LooseVersion from distutils.version import LooseVersion
from json import loads from json import loads
from os import devnull, environ from os import devnull, environ
from os.path import dirname, join from os.path import dirname, join
import re import re
import ssl
from subprocess import check_call, CalledProcessError from subprocess import check_call, CalledProcessError
from sys import argv, exit from sys import argv, exit
from urllib2 import build_opener, HTTPHandler, HTTPSHandler try:
from urllib2 import HTTPError, URLError 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----- PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
@@ -1385,8 +1503,11 @@ class HttpsGetter(object):
def __init__(self): def __init__(self):
"""Build an HTTPS opener.""" """Build an HTTPS opener."""
# Based on pip 1.4.1's URLOpener # Based on pip 1.4.1's URLOpener
# This verifies certs on only Python >=2.7.9. # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.
self._opener = build_opener(HTTPSHandler()) if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):
self._opener = build_opener(HTTPSHandler(context=cert_none_context()))
else:
self._opener = build_opener(HTTPSHandler())
# Strip out HTTPHandler to prevent MITM spoof: # Strip out HTTPHandler to prevent MITM spoof:
for handler in self._opener.handlers: for handler in self._opener.handlers:
if isinstance(handler, HTTPHandler): if isinstance(handler, HTTPHandler):
@@ -1408,7 +1529,7 @@ class HttpsGetter(object):
def write(contents, dir, filename): def write(contents, dir, filename):
"""Write something to a file in a certain directory.""" """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) file.write(contents)
@@ -1416,13 +1537,13 @@ def latest_stable_version(get):
"""Return the latest stable release of letsencrypt.""" """Return the latest stable release of letsencrypt."""
metadata = loads(get( metadata = loads(get(
environ.get('LE_AUTO_JSON_URL', 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 # metadata['info']['version'] actually returns the latest of any kind of
# release release, contrary to https://wiki.python.org/moin/PyPIJSON. # release release, contrary to https://wiki.python.org/moin/PyPIJSON.
# The regex is a sufficient regex for picking out prereleases for most # The regex is a sufficient regex for picking out prereleases for most
# packages, LE included. # packages, LE included.
return str(max(LooseVersion(r) for r return str(max(LooseVersion(r) for r
in metadata['releases'].iterkeys() in metadata['releases'].keys()
if re.match('^[0-9.]+$', r))) if re.match('^[0-9.]+$', r)))
@@ -1439,7 +1560,7 @@ def verified_new_le_auto(get, tag, temp_dir):
'letsencrypt-auto-source/') % tag 'letsencrypt-auto-source/') % tag
write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto') 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(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: try:
with open(devnull, 'w') as dev_null: with open(devnull, 'w') as dev_null:
check_call(['openssl', 'dgst', '-sha256', '-verify', check_call(['openssl', 'dgst', '-sha256', '-verify',
@@ -1454,6 +1575,14 @@ def verified_new_le_auto(get, tag, temp_dir):
"certbot-auto.", exc) "certbot-auto.", exc)
def 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(): def main():
get = HttpsGetter().get get = HttpsGetter().get
flag = argv[1] flag = argv[1]
@@ -1475,8 +1604,10 @@ if __name__ == '__main__':
UNLIKELY_EOF UNLIKELY_EOF
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
DeterminePythonVersion DeterminePythonVersion "NOCRASH"
if ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then if [ "$PYVER" -lt "$MIN_PYVER" ]; then
error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates."
elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then
error "WARNING: unable to check for updates." error "WARNING: unable to check for updates."
elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."

View File

@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v2 Version: GnuPG v2
iQEcBAABCAAGBQJaKHMlAAoJEE0XyZXNl3Xy6OEH/iPg6D6+zco4NHMwxYIcTWVt iQEcBAABCAAGBQJaX+JUAAoJEE0XyZXNl3XyUCkH/jowI7yayXREoBUWpLuByd/n
XE4u3CjuLcEVsvEnJYNSA48NHyi9rIqMHd+IneLU+lCG2D7eBsisNNyVPIgHktTf e1wGLQjnZYkxv/AJGJ63G3QvwpzmIqo3r/6K4ARlUcdOnepZRDpF6jC4F5q9vBwW
p9i0WoZB+axe1glv9FJSZvjvr2d/ic4/wYHBF1c+szb9p8Z7o5Lhqa9/gtLJ/SZX AvUVU2B7e6mC6l/jXNepS8xowEwkQptQBDfnqh8TTeTb3rQTFod8X41skZ2633HL
OGU0wok4hPIB6emq5zvmi/+r1AiOECXE26lZ0STp6wDkvz+ahTJSk6UaPCDY+Az4 RX4ditKaGMbcswMn6+5/juz0YK5ujVdVTcMeMcZKP2tvPJ9Y08YdpY6IdrM0Mfhn
X2VmnRSks/gk7Q8cloFnyiPXyFMQHdGIBRrIXsSix90QqmNUF7iYb8sbHksU23EI IqssjM06CzsiYHeNOXfRY4vAPw4Oq/md3bf6ZpPCee1HPiDm0NvHtTemWBkPIehf
/LmIwSJlDm6KNOO2nllBB/uIg2ki7g0z7R4uf7XF4im+P95PAL/tQQ45lVj8DXE= yy0U8JIDIZha4WKo3yifbZFL5Zf5czVkrtqQ3DBRcLrCFtBh2aTVsIMJkpW/wFo=
=Is56 =d/hS
-----END PGP SIGNATURE----- -----END PGP SIGNATURE-----

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi fi
VENV_BIN="$VENV_PATH/bin" VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt" BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="0.21.0.dev0" LE_AUTO_VERSION="0.21.0"
BASENAME=$(basename $0) BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS] USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -1190,18 +1190,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \ --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9 --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.20.0 \ certbot==0.21.0 \
--hash=sha256:c6b6bd288700898d1eb31a65b605e3a5fc10f1e3213ce468207d76a2decb9d35 \ --hash=sha256:b6fc9cf80e8e2925827c61ca92c32faa935bbadaf14448e2d7f40e1f8f2cccdb \
--hash=sha256:cabf505b64fb400c4239dcdbaeb882079477eb6a8442268596a8791b9e34de88 --hash=sha256:07ca3246d3462fe73418113cc5c1036545f4b2312831024da923054de3a85857
acme==0.20.0 \ acme==0.21.0 \
--hash=sha256:8b0cee192c0d76d6f4045bdb14b3cfd29d9720e0dad2046794a2a555f1eaccb7 \ --hash=sha256:4ef91a62c30b9d6bd1dd0b5ac3a8c7e70203e08e5269d3d26311dd6648aaacda \
--hash=sha256:45121aed6c8cc2f31896ac1083068dfdeb613f3edeff9576dc0d10632ea5a3d5 --hash=sha256:d64eae267c0bb21c98fa889b4e0be4c473ca8e80488d3de057e803d6d167544d
certbot-apache==0.20.0 \ certbot-apache==0.21.0 \
--hash=sha256:f7e4dbc154d2e9d1461118b6dd3dbd16f6892da468f060eeaa162aff673347e2 \ --hash=sha256:026c23fec4def727f88acd15f66b5641f7ba1f767f0728fd56798cf3500be0c5 \
--hash=sha256:0ba499706451ffbccb172bcf93d6ef4c6cc8599157077a4fa6dfbe5a83c7921f --hash=sha256:185dae50c680fa3c09646907a6256c6b4ddf8525723d3b13b9b33d1a3118663b
certbot-nginx==0.20.0 \ certbot-nginx==0.21.0 \
--hash=sha256:b6e372e8740b20dd9bd63837646157ac97b3c9a65affd3954571b8e872ae9ecf \ --hash=sha256:e5ac3a203871f13e7e72d4922e401364342f2999d130c959f90949305c33d2bc \
--hash=sha256:6379fdf20d9a7651fe30bb8d4b828cbea178cc263d7af5a380fc4508d793b9ae --hash=sha256:88be95916935980edc4c6ec3f39031ac47f5b73d6e43dfa3694b927226432642
UNLIKELY_EOF UNLIKELY_EOF
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------

View File

@@ -1,12 +1,12 @@
certbot==0.20.0 \ certbot==0.21.0 \
--hash=sha256:c6b6bd288700898d1eb31a65b605e3a5fc10f1e3213ce468207d76a2decb9d35 \ --hash=sha256:b6fc9cf80e8e2925827c61ca92c32faa935bbadaf14448e2d7f40e1f8f2cccdb \
--hash=sha256:cabf505b64fb400c4239dcdbaeb882079477eb6a8442268596a8791b9e34de88 --hash=sha256:07ca3246d3462fe73418113cc5c1036545f4b2312831024da923054de3a85857
acme==0.20.0 \ acme==0.21.0 \
--hash=sha256:8b0cee192c0d76d6f4045bdb14b3cfd29d9720e0dad2046794a2a555f1eaccb7 \ --hash=sha256:4ef91a62c30b9d6bd1dd0b5ac3a8c7e70203e08e5269d3d26311dd6648aaacda \
--hash=sha256:45121aed6c8cc2f31896ac1083068dfdeb613f3edeff9576dc0d10632ea5a3d5 --hash=sha256:d64eae267c0bb21c98fa889b4e0be4c473ca8e80488d3de057e803d6d167544d
certbot-apache==0.20.0 \ certbot-apache==0.21.0 \
--hash=sha256:f7e4dbc154d2e9d1461118b6dd3dbd16f6892da468f060eeaa162aff673347e2 \ --hash=sha256:026c23fec4def727f88acd15f66b5641f7ba1f767f0728fd56798cf3500be0c5 \
--hash=sha256:0ba499706451ffbccb172bcf93d6ef4c6cc8599157077a4fa6dfbe5a83c7921f --hash=sha256:185dae50c680fa3c09646907a6256c6b4ddf8525723d3b13b9b33d1a3118663b
certbot-nginx==0.20.0 \ certbot-nginx==0.21.0 \
--hash=sha256:b6e372e8740b20dd9bd63837646157ac97b3c9a65affd3954571b8e872ae9ecf \ --hash=sha256:e5ac3a203871f13e7e72d4922e401364342f2999d130c959f90949305c33d2bc \
--hash=sha256:6379fdf20d9a7651fe30bb8d4b828cbea178cc263d7af5a380fc4508d793b9ae --hash=sha256:88be95916935980edc4c6ec3f39031ac47f5b73d6e43dfa3694b927226432642