source: main/trunk/greenstone3/bin/linux/certbot-auto@ 32353

Last change on this file since 32353 was 32353, checked in by ak19, 6 years ago

Adding in the certbot-auto script from https://certbot.eff.org/ for Software: I'm using None Of The Above on System: Other Unix settings.

  • Property svn:executable set to *
File size: 60.8 KB
Line 
1#!/bin/sh
2#
3# Download and run the latest release version of the Certbot client.
4#
5# NOTE: THIS SCRIPT IS AUTO-GENERATED AND SELF-UPDATING
6#
7# IF YOU WANT TO EDIT IT LOCALLY, *ALWAYS* RUN YOUR COPY WITH THE
8# "--no-self-upgrade" FLAG
9#
10# IF YOU WANT TO SEND PULL REQUESTS, THE REAL SOURCE FOR THIS FILE IS
11# letsencrypt-auto-source/letsencrypt-auto.template AND
12# letsencrypt-auto-source/pieces/bootstrappers/*
13
14set -e # Work even if somebody does "sh thisscript.sh".
15
16# Note: you can set XDG_DATA_HOME or VENV_PATH before running this script,
17# if you want to change where the virtual environment will be installed
18
19# HOME might not be defined when being run through something like systemd
20if [ -z "$HOME" ]; then
21 HOME=~root
22fi
23if [ -z "$XDG_DATA_HOME" ]; then
24 XDG_DATA_HOME=~/.local/share
25fi
26if [ -z "$VENV_PATH" ]; then
27 # We export these values so they are preserved properly if this script is
28 # rerun with sudo/su where $HOME/$XDG_DATA_HOME may have a different value.
29 export OLD_VENV_PATH="$XDG_DATA_HOME/letsencrypt"
30 export VENV_PATH="/opt/eff.org/certbot/venv"
31fi
32VENV_BIN="$VENV_PATH/bin"
33BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
34LE_AUTO_VERSION="0.26.1"
35BASENAME=$(basename $0)
36USAGE="Usage: $BASENAME [OPTIONS]
37A self-updating wrapper script for the Certbot ACME client. When run, updates
38to both this script and certbot will be downloaded and installed. After
39ensuring you have the latest versions installed, certbot will be invoked with
40all arguments you have provided.
41
42Help for certbot itself cannot be provided until it is installed.
43
44 --debug attempt experimental installation
45 -h, --help print this help
46 -n, --non-interactive, --noninteractive run without asking for user input
47 --no-bootstrap do not install OS dependencies
48 --no-self-upgrade do not download updates
49 --os-packages-only install OS dependencies and exit
50 --install-only install certbot, upgrade if needed, and exit
51 -v, --verbose provide more output
52 -q, --quiet provide only update/error output;
53 implies --non-interactive
54
55All arguments are accepted and forwarded to the Certbot client when run."
56export CERTBOT_AUTO="$0"
57
58for arg in "$@" ; do
59 case "$arg" in
60 --debug)
61 DEBUG=1;;
62 --os-packages-only)
63 OS_PACKAGES_ONLY=1;;
64 --install-only)
65 INSTALL_ONLY=1;;
66 --no-self-upgrade)
67 # Do not upgrade this script (also prevents client upgrades, because each
68 # copy of the script pins a hash of the python client)
69 NO_SELF_UPGRADE=1;;
70 --no-bootstrap)
71 NO_BOOTSTRAP=1;;
72 --help)
73 HELP=1;;
74 --noninteractive|--non-interactive)
75 NONINTERACTIVE=1;;
76 --quiet)
77 QUIET=1;;
78 renew)
79 ASSUME_YES=1;;
80 --verbose)
81 VERBOSE=1;;
82 -[!-]*)
83 OPTIND=1
84 while getopts ":hnvq" short_arg $arg; do
85 case "$short_arg" in
86 h)
87 HELP=1;;
88 n)
89 NONINTERACTIVE=1;;
90 q)
91 QUIET=1;;
92 v)
93 VERBOSE=1;;
94 esac
95 done;;
96 esac
97done
98
99if [ $BASENAME = "letsencrypt-auto" ]; then
100 # letsencrypt-auto does not respect --help or --yes for backwards compatibility
101 NONINTERACTIVE=1
102 HELP=0
103fi
104
105# Set ASSUME_YES to 1 if QUIET or NONINTERACTIVE
106if [ "$QUIET" = 1 -o "$NONINTERACTIVE" = 1 ]; then
107 ASSUME_YES=1
108fi
109
110say() {
111 if [ "$QUIET" != 1 ]; then
112 echo "$@"
113 fi
114}
115
116error() {
117 echo "$@"
118}
119
120# Support for busybox and others where there is no "command",
121# but "which" instead
122if command -v command > /dev/null 2>&1 ; then
123 export EXISTS="command -v"
124elif which which > /dev/null 2>&1 ; then
125 export EXISTS="which"
126else
127 error "Cannot find command nor which... please install one!"
128 exit 1
129fi
130
131# Certbot itself needs root access for almost all modes of operation.
132# certbot-auto needs root access to bootstrap OS dependencies and install
133# Certbot at a protected path so it can be safely run as root. To accomplish
134# this, this script will attempt to run itself as root if it doesn't have the
135# necessary privileges by using `sudo` or falling back to `su` if it is not
136# available. The mechanism used to obtain root access can be set explicitly by
137# setting the environment variable LE_AUTO_SUDO to 'sudo', 'su', 'su_sudo',
138# 'SuSudo', or '' as used below.
139
140# Because the parameters in `su -c` has to be a string,
141# we need to properly escape it.
142SuSudo() {
143 args=""
144 # This `while` loop iterates over all parameters given to this function.
145 # For each parameter, all `'` will be replace by `'"'"'`, and the escaped string
146 # will be wrapped in a pair of `'`, then appended to `$args` string
147 # For example, `echo "It's only 1\$\!"` will be escaped to:
148 # 'echo' 'It'"'"'s only 1$!'
149 # │ │└┌┘│
150 # │ │ │ └── `'s only 1$!'` the literal string
151 # │ │ └── `\"'\"` is a single quote (as a string)
152 # │ └── `'It'`, to be concatenated with the strings following it
153 # └── `echo` wrapped in a pair of `'`, it's totally fine for the shell command itself
154 while [ $# -ne 0 ]; do
155 args="$args'$(printf "%s" "$1" | sed -e "s/'/'\"'\"'/g")' "
156 shift
157 done
158 su root -c "$args"
159}
160
161# Sets the environment variable SUDO to be the name of the program or function
162# to call to get root access. If this script already has root privleges, SUDO
163# is set to an empty string. The value in SUDO should be run with the command
164# to called with root privileges as arguments.
165SetRootAuthMechanism() {
166 SUDO=""
167 if [ -n "${LE_AUTO_SUDO+x}" ]; then
168 case "$LE_AUTO_SUDO" in
169 SuSudo|su_sudo|su)
170 SUDO=SuSudo
171 ;;
172 sudo)
173 SUDO="sudo -E"
174 ;;
175 '') ;; # Nothing to do for plain root method.
176 *)
177 error "Error: unknown root authorization mechanism '$LE_AUTO_SUDO'."
178 exit 1
179 esac
180 say "Using preset root authorization mechanism '$LE_AUTO_SUDO'."
181 else
182 if test "`id -u`" -ne "0" ; then
183 if $EXISTS sudo 1>/dev/null 2>&1; then
184 SUDO="sudo -E"
185 else
186 say \"sudo\" is not available, will use \"su\" for installation steps...
187 SUDO=SuSudo
188 fi
189 fi
190 fi
191}
192
193if [ "$1" = "--cb-auto-has-root" ]; then
194 shift 1
195else
196 SetRootAuthMechanism
197 if [ -n "$SUDO" ]; then
198 echo "Requesting to rerun $0 with root privileges..."
199 $SUDO "$0" --cb-auto-has-root "$@"
200 exit 0
201 fi
202fi
203
204# Runs this script again with the given arguments. --cb-auto-has-root is added
205# to the command line arguments to ensure we don't try to acquire root a
206# second time. After the script is rerun, we exit the current script.
207RerunWithArgs() {
208 "$0" --cb-auto-has-root "$@"
209 exit 0
210}
211
212BootstrapMessage() {
213 # Arguments: Platform name
214 say "Bootstrapping dependencies for $1... (you can skip this with --no-bootstrap)"
215}
216
217ExperimentalBootstrap() {
218 # Arguments: Platform name, bootstrap function name
219 if [ "$DEBUG" = 1 ]; then
220 if [ "$2" != "" ]; then
221 BootstrapMessage $1
222 $2
223 fi
224 else
225 error "FATAL: $1 support is very experimental at present..."
226 error "if you would like to work on improving it, please ensure you have backups"
227 error "and then run this script again with the --debug flag!"
228 error "Alternatively, you can install OS dependencies yourself and run this script"
229 error "again with --no-bootstrap."
230 exit 1
231 fi
232}
233
234DeprecationBootstrap() {
235 # Arguments: Platform name, bootstrap function name
236 if [ "$DEBUG" = 1 ]; then
237 if [ "$2" != "" ]; then
238 BootstrapMessage $1
239 $2
240 fi
241 else
242 error "WARNING: certbot-auto support for this $1 is DEPRECATED!"
243 error "Please visit certbot.eff.org to learn how to download a version of"
244 error "Certbot that is packaged for your system. While an existing version"
245 error "of certbot-auto may work currently, we have stopped supporting updating"
246 error "system packages for your system. Please switch to a packaged version"
247 error "as soon as possible."
248 exit 1
249 fi
250}
251
252MIN_PYTHON_VERSION="2.7"
253MIN_PYVER=$(echo "$MIN_PYTHON_VERSION" | sed 's/\.//')
254# Sets LE_PYTHON to Python version string and PYVER to the first two
255# digits of the python version
256DeterminePythonVersion() {
257 # Arguments: "NOCRASH" if we shouldn't crash if we don't find a good python
258 #
259 # If no Python is found, PYVER is set to 0.
260 if [ "$USE_PYTHON_3" = 1 ]; then
261 for LE_PYTHON in "$LE_PYTHON" python3; do
262 # Break (while keeping the LE_PYTHON value) if found.
263 $EXISTS "$LE_PYTHON" > /dev/null && break
264 done
265 else
266 for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do
267 # Break (while keeping the LE_PYTHON value) if found.
268 $EXISTS "$LE_PYTHON" > /dev/null && break
269 done
270 fi
271 if [ "$?" != "0" ]; then
272 if [ "$1" != "NOCRASH" ]; then
273 error "Cannot find any Pythons; please install one!"
274 exit 1
275 else
276 PYVER=0
277 return 0
278 fi
279 fi
280
281 PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'`
282 if [ "$PYVER" -lt "$MIN_PYVER" ]; then
283 if [ "$1" != "NOCRASH" ]; then
284 error "You have an ancient version of Python entombed in your operating system..."
285 error "This isn't going to work; you'll need at least version $MIN_PYTHON_VERSION."
286 exit 1
287 fi
288 fi
289}
290
291# If new packages are installed by BootstrapDebCommon below, this version
292# number must be increased.
293BOOTSTRAP_DEB_COMMON_VERSION=1
294
295BootstrapDebCommon() {
296 # Current version tested with:
297 #
298 # - Ubuntu
299 # - 14.04 (x64)
300 # - 15.04 (x64)
301 # - Debian
302 # - 7.9 "wheezy" (x64)
303 # - sid (2015-10-21) (x64)
304
305 # Past versions tested with:
306 #
307 # - Debian 8.0 "jessie" (x64)
308 # - Raspbian 7.8 (armhf)
309
310 # Believed not to work:
311 #
312 # - Debian 6.0.10 "squeeze" (x64)
313
314 if [ "$QUIET" = 1 ]; then
315 QUIET_FLAG='-qq'
316 fi
317
318 apt-get $QUIET_FLAG update || error apt-get update hit problems but continuing anyway...
319
320 # virtualenv binary can be found in different packages depending on
321 # distro version (#346)
322
323 virtualenv=
324 # virtual env is known to apt and is installable
325 if apt-cache show virtualenv > /dev/null 2>&1 ; then
326 if ! LC_ALL=C apt-cache --quiet=0 show virtualenv 2>&1 | grep -q 'No packages found'; then
327 virtualenv="virtualenv"
328 fi
329 fi
330
331 if apt-cache show python-virtualenv > /dev/null 2>&1; then
332 virtualenv="$virtualenv python-virtualenv"
333 fi
334
335 augeas_pkg="libaugeas0 augeas-lenses"
336 AUGVERSION=`LC_ALL=C apt-cache show --no-all-versions libaugeas0 | grep ^Version: | cut -d" " -f2`
337
338 if [ "$ASSUME_YES" = 1 ]; then
339 YES_FLAG="-y"
340 fi
341
342 AddBackportRepo() {
343 # ARGS:
344 BACKPORT_NAME="$1"
345 BACKPORT_SOURCELINE="$2"
346 say "To use the Apache Certbot plugin, augeas needs to be installed from $BACKPORT_NAME."
347 if ! grep -v -e ' *#' /etc/apt/sources.list | grep -q "$BACKPORT_NAME" ; then
348 # This can theoretically error if sources.list.d is empty, but in that case we don't care.
349 if ! grep -v -e ' *#' /etc/apt/sources.list.d/* 2>/dev/null | grep -q "$BACKPORT_NAME"; then
350 if [ "$ASSUME_YES" = 1 ]; then
351 /bin/echo -n "Installing augeas from $BACKPORT_NAME in 3 seconds..."
352 sleep 1s
353 /bin/echo -ne "\e[0K\rInstalling augeas from $BACKPORT_NAME in 2 seconds..."
354 sleep 1s
355 /bin/echo -e "\e[0K\rInstalling augeas from $BACKPORT_NAME in 1 second ..."
356 sleep 1s
357 add_backports=1
358 else
359 read -p "Would you like to enable the $BACKPORT_NAME repository [Y/n]? " response
360 case $response in
361 [yY][eE][sS]|[yY]|"")
362 add_backports=1;;
363 *)
364 add_backports=0;;
365 esac
366 fi
367 if [ "$add_backports" = 1 ]; then
368 sh -c "echo $BACKPORT_SOURCELINE >> /etc/apt/sources.list.d/$BACKPORT_NAME.list"
369 apt-get $QUIET_FLAG update
370 fi
371 fi
372 fi
373 if [ "$add_backports" != 0 ]; then
374 apt-get install $QUIET_FLAG $YES_FLAG --no-install-recommends -t "$BACKPORT_NAME" $augeas_pkg
375 augeas_pkg=
376 fi
377 }
378
379
380 if dpkg --compare-versions 1.0 gt "$AUGVERSION" ; then
381 if lsb_release -a | grep -q wheezy ; then
382 AddBackportRepo wheezy-backports "deb http://http.debian.net/debian wheezy-backports main"
383 elif lsb_release -a | grep -q precise ; then
384 # XXX add ARM case
385 AddBackportRepo precise-backports "deb http://archive.ubuntu.com/ubuntu precise-backports main restricted universe multiverse"
386 else
387 echo "No libaugeas0 version is available that's new enough to run the"
388 echo "Certbot apache plugin..."
389 fi
390 # XXX add a case for ubuntu PPAs
391 fi
392
393 apt-get install $QUIET_FLAG $YES_FLAG --no-install-recommends \
394 python \
395 python-dev \
396 $virtualenv \
397 gcc \
398 $augeas_pkg \
399 libssl-dev \
400 openssl \
401 libffi-dev \
402 ca-certificates \
403
404
405 if ! $EXISTS virtualenv > /dev/null ; then
406 error Failed to install a working \"virtualenv\" command, exiting
407 exit 1
408 fi
409}
410
411# If new packages are installed by BootstrapRpmCommonBase below, version
412# numbers in rpm_common.sh and rpm_python3.sh must be increased.
413
414# Sets TOOL to the name of the package manager
415# Sets appropriate values for YES_FLAG and QUIET_FLAG based on $ASSUME_YES and $QUIET_FLAG.
416# Enables EPEL if applicable and possible.
417InitializeRPMCommonBase() {
418 if type dnf 2>/dev/null
419 then
420 TOOL=dnf
421 elif type yum 2>/dev/null
422 then
423 TOOL=yum
424
425 else
426 error "Neither yum nor dnf found. Aborting bootstrap!"
427 exit 1
428 fi
429
430 if [ "$ASSUME_YES" = 1 ]; then
431 YES_FLAG="-y"
432 fi
433 if [ "$QUIET" = 1 ]; then
434 QUIET_FLAG='--quiet'
435 fi
436
437 if ! $TOOL list *virtualenv >/dev/null 2>&1; then
438 echo "To use Certbot, packages from the EPEL repository need to be installed."
439 if ! $TOOL list epel-release >/dev/null 2>&1; then
440 error "Enable the EPEL repository and try running Certbot again."
441 exit 1
442 fi
443 if [ "$ASSUME_YES" = 1 ]; then
444 /bin/echo -n "Enabling the EPEL repository in 3 seconds..."
445 sleep 1s
446 /bin/echo -ne "\e[0K\rEnabling the EPEL repository in 2 seconds..."
447 sleep 1s
448 /bin/echo -e "\e[0K\rEnabling the EPEL repository in 1 second..."
449 sleep 1s
450 fi
451 if ! $TOOL install $YES_FLAG $QUIET_FLAG epel-release; then
452 error "Could not enable EPEL. Aborting bootstrap!"
453 exit 1
454 fi
455 fi
456}
457
458BootstrapRpmCommonBase() {
459 # Arguments: whitespace-delimited python packages to install
460
461 InitializeRPMCommonBase # This call is superfluous in practice
462
463 pkgs="
464 gcc
465 augeas-libs
466 openssl
467 openssl-devel
468 libffi-devel
469 redhat-rpm-config
470 ca-certificates
471 "
472
473 # Add the python packages
474 pkgs="$pkgs
475 $1
476 "
477
478 if $TOOL list installed "httpd" >/dev/null 2>&1; then
479 pkgs="$pkgs
480 mod_ssl
481 "
482 fi
483
484 if ! $TOOL install $YES_FLAG $QUIET_FLAG $pkgs; then
485 error "Could not install OS dependencies. Aborting bootstrap!"
486 exit 1
487 fi
488}
489
490# If new packages are installed by BootstrapRpmCommon below, this version
491# number must be increased.
492BOOTSTRAP_RPM_COMMON_VERSION=1
493
494BootstrapRpmCommon() {
495 # Tested with:
496 # - Fedora 20, 21, 22, 23 (x64)
497 # - Centos 7 (x64: on DigitalOcean droplet)
498 # - CentOS 7 Minimal install in a Hyper-V VM
499 # - CentOS 6
500
501 InitializeRPMCommonBase
502
503 # Most RPM distros use the "python" or "python-" naming convention. Let's try that first.
504 if $TOOL list python >/dev/null 2>&1; then
505 python_pkgs="$python
506 python-devel
507 python-virtualenv
508 python-tools
509 python-pip
510 "
511 # Fedora 26 starts to use the prefix python2 for python2 based packages.
512 # this elseif is theoretically for any Fedora over version 26:
513 elif $TOOL list python2 >/dev/null 2>&1; then
514 python_pkgs="$python2
515 python2-libs
516 python2-setuptools
517 python2-devel
518 python2-virtualenv
519 python2-tools
520 python2-pip
521 "
522 # Some distros and older versions of current distros use a "python27"
523 # instead of the "python" or "python-" naming convention.
524 else
525 python_pkgs="$python27
526 python27-devel
527 python27-virtualenv
528 python27-tools
529 python27-pip
530 "
531 fi
532
533 BootstrapRpmCommonBase "$python_pkgs"
534}
535
536# If new packages are installed by BootstrapRpmPython3 below, this version
537# number must be increased.
538BOOTSTRAP_RPM_PYTHON3_VERSION=1
539
540BootstrapRpmPython3() {
541 # Tested with:
542 # - CentOS 6
543
544 InitializeRPMCommonBase
545
546 # EPEL uses python34
547 if $TOOL list python34 >/dev/null 2>&1; then
548 python_pkgs="python34
549 python34-devel
550 python34-tools
551 "
552 else
553 error "No supported Python package available to install. Aborting bootstrap!"
554 exit 1
555 fi
556
557 BootstrapRpmCommonBase "$python_pkgs"
558}
559
560# If new packages are installed by BootstrapSuseCommon below, this version
561# number must be increased.
562BOOTSTRAP_SUSE_COMMON_VERSION=1
563
564BootstrapSuseCommon() {
565 # SLE12 don't have python-virtualenv
566
567 if [ "$ASSUME_YES" = 1 ]; then
568 zypper_flags="-nq"
569 install_flags="-l"
570 fi
571
572 if [ "$QUIET" = 1 ]; then
573 QUIET_FLAG='-qq'
574 fi
575
576 zypper $QUIET_FLAG $zypper_flags in $install_flags \
577 python \
578 python-devel \
579 python-virtualenv \
580 gcc \
581 augeas-lenses \
582 libopenssl-devel \
583 libffi-devel \
584 ca-certificates
585}
586
587# If new packages are installed by BootstrapArchCommon below, this version
588# number must be increased.
589BOOTSTRAP_ARCH_COMMON_VERSION=1
590
591BootstrapArchCommon() {
592 # Tested with:
593 # - ArchLinux (x86_64)
594 #
595 # "python-virtualenv" is Python3, but "python2-virtualenv" provides
596 # only "virtualenv2" binary, not "virtualenv" necessary in
597 # ./tools/_venv_common.sh
598
599 deps="
600 python2
601 python-virtualenv
602 gcc
603 augeas
604 openssl
605 libffi
606 ca-certificates
607 pkg-config
608 "
609
610 # pacman -T exits with 127 if there are missing dependencies
611 missing=$(pacman -T $deps) || true
612
613 if [ "$ASSUME_YES" = 1 ]; then
614 noconfirm="--noconfirm"
615 fi
616
617 if [ "$missing" ]; then
618 if [ "$QUIET" = 1 ]; then
619 pacman -S --needed $missing $noconfirm > /dev/null
620 else
621 pacman -S --needed $missing $noconfirm
622 fi
623 fi
624}
625
626# If new packages are installed by BootstrapGentooCommon below, this version
627# number must be increased.
628BOOTSTRAP_GENTOO_COMMON_VERSION=1
629
630BootstrapGentooCommon() {
631 PACKAGES="
632 dev-lang/python:2.7
633 dev-python/virtualenv
634 app-admin/augeas
635 dev-libs/openssl
636 dev-libs/libffi
637 app-misc/ca-certificates
638 virtual/pkgconfig"
639
640 ASK_OPTION="--ask"
641 if [ "$ASSUME_YES" = 1 ]; then
642 ASK_OPTION=""
643 fi
644
645 case "$PACKAGE_MANAGER" in
646 (paludis)
647 cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x
648 ;;
649 (pkgcore)
650 pmerge --noreplace --oneshot $ASK_OPTION $PACKAGES
651 ;;
652 (portage|*)
653 emerge --noreplace --oneshot $ASK_OPTION $PACKAGES
654 ;;
655 esac
656}
657
658# If new packages are installed by BootstrapFreeBsd below, this version number
659# must be increased.
660BOOTSTRAP_FREEBSD_VERSION=1
661
662BootstrapFreeBsd() {
663 if [ "$QUIET" = 1 ]; then
664 QUIET_FLAG="--quiet"
665 fi
666
667 pkg install -Ay $QUIET_FLAG \
668 python \
669 py27-virtualenv \
670 augeas \
671 libffi
672}
673
674# If new packages are installed by BootstrapMac below, this version number must
675# be increased.
676BOOTSTRAP_MAC_VERSION=1
677
678BootstrapMac() {
679 if hash brew 2>/dev/null; then
680 say "Using Homebrew to install dependencies..."
681 pkgman=brew
682 pkgcmd="brew install"
683 elif hash port 2>/dev/null; then
684 say "Using MacPorts to install dependencies..."
685 pkgman=port
686 pkgcmd="port install"
687 else
688 say "No Homebrew/MacPorts; installing Homebrew..."
689 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
690 pkgman=brew
691 pkgcmd="brew install"
692 fi
693
694 $pkgcmd augeas
695 if [ "$(which python)" = "/System/Library/Frameworks/Python.framework/Versions/2.7/bin/python" \
696 -o "$(which python)" = "/usr/bin/python" ]; then
697 # We want to avoid using the system Python because it requires root to use pip.
698 # python.org, MacPorts or HomeBrew Python installations should all be OK.
699 say "Installing python..."
700 $pkgcmd python
701 fi
702
703 # Workaround for _dlopen not finding augeas on macOS
704 if [ "$pkgman" = "port" ] && ! [ -e "/usr/local/lib/libaugeas.dylib" ] && [ -e "/opt/local/lib/libaugeas.dylib" ]; then
705 say "Applying augeas workaround"
706 mkdir -p /usr/local/lib/
707 ln -s /opt/local/lib/libaugeas.dylib /usr/local/lib/
708 fi
709
710 if ! hash pip 2>/dev/null; then
711 say "pip not installed"
712 say "Installing pip..."
713 curl --silent --show-error --retry 5 https://bootstrap.pypa.io/get-pip.py | python
714 fi
715
716 if ! hash virtualenv 2>/dev/null; then
717 say "virtualenv not installed."
718 say "Installing with pip..."
719 pip install virtualenv
720 fi
721}
722
723# If new packages are installed by BootstrapSmartOS below, this version number
724# must be increased.
725BOOTSTRAP_SMARTOS_VERSION=1
726
727BootstrapSmartOS() {
728 pkgin update
729 pkgin -y install 'gcc49' 'py27-augeas' 'py27-virtualenv'
730}
731
732# If new packages are installed by BootstrapMageiaCommon below, this version
733# number must be increased.
734BOOTSTRAP_MAGEIA_COMMON_VERSION=1
735
736BootstrapMageiaCommon() {
737 if [ "$QUIET" = 1 ]; then
738 QUIET_FLAG='--quiet'
739 fi
740
741 if ! urpmi --force $QUIET_FLAG \
742 python \
743 libpython-devel \
744 python-virtualenv
745 then
746 error "Could not install Python dependencies. Aborting bootstrap!"
747 exit 1
748 fi
749
750 if ! urpmi --force $QUIET_FLAG \
751 git \
752 gcc \
753 python-augeas \
754 libopenssl-devel \
755 libffi-devel \
756 rootcerts
757 then
758 error "Could not install additional dependencies. Aborting bootstrap!"
759 exit 1
760 fi
761}
762
763
764# Set Bootstrap to the function that installs OS dependencies on this system
765# and BOOTSTRAP_VERSION to the unique identifier for the current version of
766# that function. If Bootstrap is set to a function that doesn't install any
767# packages BOOTSTRAP_VERSION is not set.
768if [ -f /etc/debian_version ]; then
769 Bootstrap() {
770 BootstrapMessage "Debian-based OSes"
771 BootstrapDebCommon
772 }
773 BOOTSTRAP_VERSION="BootstrapDebCommon $BOOTSTRAP_DEB_COMMON_VERSION"
774elif [ -f /etc/mageia-release ]; then
775 # Mageia has both /etc/mageia-release and /etc/redhat-release
776 Bootstrap() {
777 ExperimentalBootstrap "Mageia" BootstrapMageiaCommon
778 }
779 BOOTSTRAP_VERSION="BootstrapMageiaCommon $BOOTSTRAP_MAGEIA_COMMON_VERSION"
780elif [ -f /etc/redhat-release ]; then
781 # Run DeterminePythonVersion to decide on the basis of available Python versions
782 # whether to use 2.x or 3.x on RedHat-like systems.
783 # Then, revert LE_PYTHON to its previous state.
784 prev_le_python="$LE_PYTHON"
785 unset LE_PYTHON
786 DeterminePythonVersion "NOCRASH"
787 if [ "$PYVER" -eq 26 ]; then
788 Bootstrap() {
789 BootstrapMessage "RedHat-based OSes that will use Python3"
790 BootstrapRpmPython3
791 }
792 USE_PYTHON_3=1
793 BOOTSTRAP_VERSION="BootstrapRpmPython3 $BOOTSTRAP_RPM_PYTHON3_VERSION"
794 else
795 Bootstrap() {
796 BootstrapMessage "RedHat-based OSes"
797 BootstrapRpmCommon
798 }
799 BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"
800 fi
801 LE_PYTHON="$prev_le_python"
802elif [ -f /etc/os-release ] && `grep -q openSUSE /etc/os-release` ; then
803 Bootstrap() {
804 BootstrapMessage "openSUSE-based OSes"
805 BootstrapSuseCommon
806 }
807 BOOTSTRAP_VERSION="BootstrapSuseCommon $BOOTSTRAP_SUSE_COMMON_VERSION"
808elif [ -f /etc/arch-release ]; then
809 Bootstrap() {
810 if [ "$DEBUG" = 1 ]; then
811 BootstrapMessage "Archlinux"
812 BootstrapArchCommon
813 else
814 error "Please use pacman to install letsencrypt packages:"
815 error "# pacman -S certbot certbot-apache"
816 error
817 error "If you would like to use the virtualenv way, please run the script again with the"
818 error "--debug flag."
819 exit 1
820 fi
821 }
822 BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION"
823elif [ -f /etc/manjaro-release ]; then
824 Bootstrap() {
825 ExperimentalBootstrap "Manjaro Linux" BootstrapArchCommon
826 }
827 BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION"
828elif [ -f /etc/gentoo-release ]; then
829 Bootstrap() {
830 DeprecationBootstrap "Gentoo" BootstrapGentooCommon
831 }
832 BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION"
833elif uname | grep -iq FreeBSD ; then
834 Bootstrap() {
835 DeprecationBootstrap "FreeBSD" BootstrapFreeBsd
836 }
837 BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION"
838elif uname | grep -iq Darwin ; then
839 Bootstrap() {
840 DeprecationBootstrap "macOS" BootstrapMac
841 }
842 BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION"
843elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
844 Bootstrap() {
845 ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
846 }
847 BOOTSTRAP_VERSION="BootstrapRpmCommon $BOOTSTRAP_RPM_COMMON_VERSION"
848elif [ -f /etc/product ] && grep -q "Joyent Instance" /etc/product ; then
849 Bootstrap() {
850 ExperimentalBootstrap "Joyent SmartOS Zone" BootstrapSmartOS
851 }
852 BOOTSTRAP_VERSION="BootstrapSmartOS $BOOTSTRAP_SMARTOS_VERSION"
853else
854 Bootstrap() {
855 error "Sorry, I don't know how to bootstrap Certbot on your operating system!"
856 error
857 error "You will need to install OS dependencies, configure virtualenv, and run pip install manually."
858 error "Please see https://letsencrypt.readthedocs.org/en/latest/contributing.html#prerequisites"
859 error "for more info."
860 exit 1
861 }
862fi
863
864# We handle this case after determining the normal bootstrap version to allow
865# variables like USE_PYTHON_3 to be properly set. As described above, if the
866# Bootstrap function doesn't install any packages, BOOTSTRAP_VERSION should not
867# be set so we unset it here.
868if [ "$NO_BOOTSTRAP" = 1 ]; then
869 Bootstrap() {
870 :
871 }
872 unset BOOTSTRAP_VERSION
873fi
874
875# Sets PREV_BOOTSTRAP_VERSION to the identifier for the bootstrap script used
876# to install OS dependencies on this system. PREV_BOOTSTRAP_VERSION isn't set
877# if it is unknown how OS dependencies were installed on this system.
878SetPrevBootstrapVersion() {
879 if [ -f $BOOTSTRAP_VERSION_PATH ]; then
880 PREV_BOOTSTRAP_VERSION=$(cat "$BOOTSTRAP_VERSION_PATH")
881 # The list below only contains bootstrap version strings that existed before
882 # we started writing them to disk.
883 #
884 # DO NOT MODIFY THIS LIST UNLESS YOU KNOW WHAT YOU'RE DOING!
885 elif grep -Fqx "$BOOTSTRAP_VERSION" << "UNLIKELY_EOF"
886BootstrapDebCommon 1
887BootstrapMageiaCommon 1
888BootstrapRpmCommon 1
889BootstrapSuseCommon 1
890BootstrapArchCommon 1
891BootstrapGentooCommon 1
892BootstrapFreeBsd 1
893BootstrapMac 1
894BootstrapSmartOS 1
895UNLIKELY_EOF
896 then
897 # If there's no bootstrap version saved to disk, but the currently selected
898 # bootstrap script is from before we started saving the version number,
899 # return the currently selected version to prevent us from rebootstrapping
900 # unnecessarily.
901 PREV_BOOTSTRAP_VERSION="$BOOTSTRAP_VERSION"
902 fi
903}
904
905TempDir() {
906 mktemp -d 2>/dev/null || mktemp -d -t 'le' # Linux || macOS
907}
908
909# Returns 0 if a letsencrypt installation exists at $OLD_VENV_PATH, otherwise,
910# returns a non-zero number.
911OldVenvExists() {
912 [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ]
913}
914
915if [ "$1" = "--le-auto-phase2" ]; then
916 # Phase 2: Create venv, install LE, and run.
917
918 shift 1 # the --le-auto-phase2 arg
919 SetPrevBootstrapVersion
920
921 if [ -z "$PHASE_1_VERSION" -a "$USE_PYTHON_3" = 1 ]; then
922 unset LE_PYTHON
923 fi
924
925 INSTALLED_VERSION="none"
926 if [ -d "$VENV_PATH" ] || OldVenvExists; then
927 # If the selected Bootstrap function isn't a noop and it differs from the
928 # previously used version
929 if [ -n "$BOOTSTRAP_VERSION" -a "$BOOTSTRAP_VERSION" != "$PREV_BOOTSTRAP_VERSION" ]; then
930 # if non-interactive mode or stdin and stdout are connected to a terminal
931 if [ \( "$NONINTERACTIVE" = 1 \) -o \( \( -t 0 \) -a \( -t 1 \) \) ]; then
932 if [ -d "$VENV_PATH" ]; then
933 rm -rf "$VENV_PATH"
934 fi
935 # In the case the old venv was just a symlink to the new one,
936 # OldVenvExists is now false because we deleted the venv at VENV_PATH.
937 if OldVenvExists; then
938 rm -rf "$OLD_VENV_PATH"
939 ln -s "$VENV_PATH" "$OLD_VENV_PATH"
940 fi
941 RerunWithArgs "$@"
942 else
943 error "Skipping upgrade because new OS dependencies may need to be installed."
944 error
945 error "To upgrade to a newer version, please run this script again manually so you can"
946 error "approve changes or with --non-interactive on the command line to automatically"
947 error "install any required packages."
948 # Set INSTALLED_VERSION to be the same so we don't update the venv
949 INSTALLED_VERSION="$LE_AUTO_VERSION"
950 # Continue to use OLD_VENV_PATH if the new venv doesn't exist
951 if [ ! -d "$VENV_PATH" ]; then
952 VENV_BIN="$OLD_VENV_PATH/bin"
953 fi
954 fi
955 elif [ -f "$VENV_BIN/letsencrypt" ]; then
956 # --version output ran through grep due to python-cryptography DeprecationWarnings
957 # grep for both certbot and letsencrypt until certbot and shim packages have been released
958 INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | grep "^certbot\|^letsencrypt" | cut -d " " -f 2)
959 if [ -z "$INSTALLED_VERSION" ]; then
960 error "Error: couldn't get currently installed version for $VENV_BIN/letsencrypt: " 1>&2
961 "$VENV_BIN/letsencrypt" --version
962 exit 1
963 fi
964 fi
965 fi
966
967 if [ "$LE_AUTO_VERSION" != "$INSTALLED_VERSION" ]; then
968 say "Creating virtual environment..."
969 DeterminePythonVersion
970 rm -rf "$VENV_PATH"
971 if [ "$PYVER" -le 27 ]; then
972 if [ "$VERBOSE" = 1 ]; then
973 virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH"
974 else
975 virtualenv --no-site-packages --python "$LE_PYTHON" "$VENV_PATH" > /dev/null
976 fi
977 else
978 if [ "$VERBOSE" = 1 ]; then
979 "$LE_PYTHON" -m venv "$VENV_PATH"
980 else
981 "$LE_PYTHON" -m venv "$VENV_PATH" > /dev/null
982 fi
983 fi
984
985 if [ -n "$BOOTSTRAP_VERSION" ]; then
986 echo "$BOOTSTRAP_VERSION" > "$BOOTSTRAP_VERSION_PATH"
987 elif [ -n "$PREV_BOOTSTRAP_VERSION" ]; then
988 echo "$PREV_BOOTSTRAP_VERSION" > "$BOOTSTRAP_VERSION_PATH"
989 fi
990
991 say "Installing Python packages..."
992 TEMP_DIR=$(TempDir)
993 trap 'rm -rf "$TEMP_DIR"' EXIT
994 # There is no $ interpolation due to quotes on starting heredoc delimiter.
995 # -------------------------------------------------------------------------
996 cat << "UNLIKELY_EOF" > "$TEMP_DIR/letsencrypt-auto-requirements.txt"
997# This is the flattened list of packages certbot-auto installs. To generate
998# this, do
999# `pip install --no-cache-dir -e acme -e . -e certbot-apache -e certbot-nginx`,
1000# and then use `hashin` or a more secure method to gather the hashes.
1001
1002# Hashin example:
1003# pip install hashin
1004# hashin -r dependency-requirements.txt cryptography==1.5.2
1005# sets the new certbot-auto pinned version of cryptography to 1.5.2
1006
1007argparse==1.4.0 \
1008 --hash=sha256:c31647edb69fd3d465a847ea3157d37bed1f95f19760b11a47aa91c04b666314 \
1009 --hash=sha256:62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4
1010
1011# This comes before cffi because cffi will otherwise install an unchecked
1012# version via setup_requires.
1013pycparser==2.14 \
1014 --hash=sha256:7959b4a74abdc27b312fed1c21e6caf9309ce0b29ea86b591fd2e99ecdf27f73 \
1015 --no-binary pycparser
1016
1017asn1crypto==0.22.0 \
1018 --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \
1019 --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a
1020cffi==1.10.0 \
1021 --hash=sha256:446699c10f3c390633d0722bc19edbc7ac4b94761918a4a4f7908a24e86ebbd0 \
1022 --hash=sha256:562326fc7f55a59ef3fef5e82908fe938cdc4bbda32d734c424c7cd9ed73e93a \
1023 --hash=sha256:7f732ad4a30db0b39400c3f7011249f7d0701007d511bf09604729aea222871f \
1024 --hash=sha256:94fb8410c6c4fc48e7ea759d3d1d9ca561171a88d00faddd4aa0306f698ad6a0 \
1025 --hash=sha256:587a5043df4b00a2130e09fed42da02a4ed3c688bd9bf07a3ac89d2271f4fb07 \
1026 --hash=sha256:ec08b88bef627ec1cea210e1608c85d3cf44893bcde74e41b7f7dbdfd2c1bad6 \
1027 --hash=sha256:a41406f6d62abcdf3eef9fd998d8dcff04fd2a7746644143045feeebd76352d1 \
1028 --hash=sha256:b560916546b2f209d74b82bdbc3223cee9a165b0242fa00a06dfc48a2054864a \
1029 --hash=sha256:e74896774e437f4715c57edeb5cf3d3a40d7727f541c2c12156617b5a15d1829 \
1030 --hash=sha256:9a31c18ba4881a116e448c52f3f5d3e14401cf7a9c43cc88f06f2a7f5428da0e \
1031 --hash=sha256:80796ea68e11624a0279d3b802f88a7fe7214122b97a15a6c97189934a2cc776 \
1032 --hash=sha256:f4019826a2dec066c909a1f483ef0dcf9325d6740cc0bd15308942b28b0930f7 \
1033 --hash=sha256:7248506981eeba23888b4140a69a53c4c0c0a386abcdca61ed8dd790a73e64b9 \
1034 --hash=sha256:a8955265d146e86fe2ce116394be4eaf0cb40314a79b19f11c4fa574cd639572 \
1035 --hash=sha256:c49187260043bd4c1d6a52186f9774f17d9b1da0a406798ebf4bfc12da166ade \
1036 --hash=sha256:c1d8b3d8dcb5c23ac1a8bf56422036f3f305a3c5a8bc8c354256579a1e2aa2c1 \
1037 --hash=sha256:9e389615bcecb8c782a87939d752340bb0a3a097e90bae54d7f0915bc12f45bd \
1038 --hash=sha256:d09ff358f75a874f69fa7d1c2b4acecf4282a950293fcfcf89aa606da8a9a500 \
1039 --hash=sha256:b69b4557aae7de18b7c174a917fe19873529d927ac592762d9771661875bbd40 \
1040 --hash=sha256:5de52b081a2775e76b971de9d997d85c4457fc0a09079e12d66849548ae60981 \
1041 --hash=sha256:e7d88fecb7b6250a1fd432e6dc64890342c372fce13dbfe4bb6f16348ad00c14 \
1042 --hash=sha256:1426e67e855ef7f5030c9184f4f1a9f4bfa020c31c962cd41fd129ec5aef4a6a \
1043 --hash=sha256:267dd2c66a5760c5f4d47e2ebcf8eeac7ef01e1ae6ae7a6d0d241a290068bc38 \
1044 --hash=sha256:e553eb489511cacf19eda6e52bc9e151316f0d721724997dda2c4d3079b778db \
1045 --hash=sha256:98b89b2c57f97ce2db7aeba60db173c84871d73b40e41a11ea95de1500ddc57e \
1046 --hash=sha256:e2b7e090188833bc58b2ae03fb864c22688654ebd2096bcf38bc860c4f38a3d8 \
1047 --hash=sha256:afa7d8b8d38ad40db8713ee053d41b36d87d6ae5ec5ad36f9210b548a18dc214 \
1048 --hash=sha256:4fc9c2ff7924b3a1fa326e1799e5dd58cac585d7fb25fe53ccaa1333b0453d65 \
1049 --hash=sha256:937db39a1ec5af3003b16357b2042bba67c88d43bc11aaa203fa8a5924524209 \
1050 --hash=sha256:ab22285797631df3b513b2cd3ecdc51cd8e3d36788e3991d93d0759d6883b027 \
1051 --hash=sha256:96e599b924ef009aa867f725b3249ee51d76489f484d3a45b4bd219c5ec6ed59 \
1052 --hash=sha256:bea842a0512be6a8007e585790bccd5d530520fc025ce63b03e139be373b0063 \
1053 --hash=sha256:e7175287f7fe7b1cc203bb958b17db40abd732690c1e18e700f10e0843a58598 \
1054 --hash=sha256:285ab352552f52f1398c912556d4d36d4ea9b8450e5c65d03809bf9886755533 \
1055 --hash=sha256:5576644b859197da7bbd8f8c7c2fb5dcc6cd505cadb42992d5f104c013f8a214 \
1056 --hash=sha256:b3b02911eb1f6ada203b0763ba924234629b51586f72a21faacc638269f4ced5
1057ConfigArgParse==0.12.0 \
1058 --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \
1059 --no-binary ConfigArgParse
1060configobj==5.0.6 \
1061 --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 \
1062 --no-binary configobj
1063cryptography==2.2.2 \
1064 --hash=sha256:3f3b65d5a16e6b52fba63dc860b62ca9832f51f1a2ae5083c78b6840275f12dd \
1065 --hash=sha256:5251e7de0de66810833606439ca65c9b9e45da62196b0c88bfadf27740aac09f \
1066 --hash=sha256:551a3abfe0c8c6833df4192a63371aa2ff43afd8f570ed345d31f251d78e7e04 \
1067 --hash=sha256:5cb990056b7cadcca26813311187ad751ea644712022a3976443691168781b6f \
1068 --hash=sha256:60bda7f12ecb828358be53095fc9c6edda7de8f1ef571f96c00b2363643fa3cd \
1069 --hash=sha256:64b5c67acc9a7c83fbb4b69166f3105a0ab722d27934fac2cb26456718eec2ba \
1070 --hash=sha256:6fef51ec447fe9f8351894024e94736862900d3a9aa2961528e602eb65c92bdb \
1071 --hash=sha256:77d0ad229d47a6e0272d00f6bf8ac06ce14715a9fd02c9a97f5a2869aab3ccb2 \
1072 --hash=sha256:808fe471b1a6b777f026f7dc7bd9a4959da4bfab64972f2bbe91e22527c1c037 \
1073 --hash=sha256:9b62fb4d18529c84b961efd9187fecbb48e89aa1a0f9f4161c61b7fc42a101bd \
1074 --hash=sha256:9e5bed45ec6b4f828866ac6a6bedf08388ffcfa68abe9e94b34bb40977aba531 \
1075 --hash=sha256:9fc295bf69130a342e7a19a39d7bbeb15c0bcaabc7382ec33ef3b2b7d18d2f63 \
1076 --hash=sha256:abd070b5849ed64e6d349199bef955ee0ad99aefbad792f0c587f8effa681a5e \
1077 --hash=sha256:ba6a774749b6e510cffc2fb98535f717e0e5fd91c7c99a61d223293df79ab351 \
1078 --hash=sha256:c332118647f084c983c6a3e1dba0f3bcb051f69d12baccac68db8d62d177eb8a \
1079 --hash=sha256:d6f46e862ee36df81e6342c2177ba84e70f722d9dc9c6c394f9f1f434c4a5563 \
1080 --hash=sha256:db6013746f73bf8edd9c3d1d3f94db635b9422f503db3fc5ef105233d4c011ab \
1081 --hash=sha256:f57008eaff597c69cf692c3518f6d4800f0309253bb138b526a37fe9ef0c7471 \
1082 --hash=sha256:f6c821ac253c19f2ad4c8691633ae1d1a17f120d5b01ea1d256d7b602bc59887
1083enum34==1.1.2 ; python_version < '3.4' \
1084 --hash=sha256:2475d7fcddf5951e92ff546972758802de5260bf409319a9f1934e6bbc8b1dc7 \
1085 --hash=sha256:35907defb0f992b75ab7788f65fedc1cf20ffa22688e0e6f6f12afc06b3ea501
1086funcsigs==1.0.2 \
1087 --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \
1088 --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50
1089idna==2.5 \
1090 --hash=sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70 \
1091 --hash=sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab
1092ipaddress==1.0.16 \
1093 --hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \
1094 --hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0
1095josepy==1.1.0 \
1096 --hash=sha256:1309a25aac3caeff5239729c58ff9b583f7d022ffdb1553406ddfc8e5b52b76e \
1097 --hash=sha256:fb5c62c77d26e04df29cb5ecd01b9ce69b6fcc9e521eb1ca193b7faa2afa7086
1098linecache2==1.0.0 \
1099 --hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \
1100 --hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c
1101# Using an older version of mock here prevents regressions of #5276.
1102mock==1.3.0 \
1103 --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
1104 --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
1105ordereddict==1.1 \
1106 --hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f \
1107 --no-binary ordereddict
1108packaging==16.8 \
1109 --hash=sha256:99276dc6e3a7851f32027a68f1095cd3f77c148091b092ea867a351811cfe388 \
1110 --hash=sha256:5d50835fdf0a7edf0b55e311b7c887786504efea1177abd7e69329a8e5ea619e
1111parsedatetime==2.1 \
1112 --hash=sha256:ce9d422165cf6e963905cd5f74f274ebf7cc98c941916169178ef93f0e557838 \
1113 --hash=sha256:17c578775520c99131634e09cfca5a05ea9e1bd2a05cd06967ebece10df7af2d
1114pbr==1.8.1 \
1115 --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \
1116 --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649
1117pyOpenSSL==16.2.0 \
1118 --hash=sha256:26ca380ddf272f7556e48064bbcd5bd71f83dfc144f3583501c7ddbd9434ee17 \
1119 --hash=sha256:7779a3bbb74e79db234af6a08775568c6769b5821faecf6e2f4143edb227516e
1120pyparsing==2.1.8 \
1121 --hash=sha256:2f0f5ceb14eccd5aef809d6382e87df22ca1da583c79f6db01675ce7d7f49c18 \
1122 --hash=sha256:03a4869b9f3493807ee1f1cb405e6d576a1a2ca4d81a982677c0c1ad6177c56b \
1123 --hash=sha256:ab09aee814c0241ff0c503cff30018219fe1fc14501d89f406f4664a0ec9fbcd \
1124 --hash=sha256:6e9a7f052f8e26bcf749e4033e3115b6dc7e3c85aafcb794b9a88c9d9ef13c97 \
1125 --hash=sha256:9f463a6bcc4eeb6c08f1ed84439b17818e2085937c0dee0d7674ac127c67c12b \
1126 --hash=sha256:3626b4d81cfb300dad57f52f2f791caaf7b06c09b368c0aa7b868e53a5775424 \
1127 --hash=sha256:367b90cc877b46af56d4580cd0ae278062903f02b8204ab631f5a2c0f50adfd0 \
1128 --hash=sha256:9f1ea360086cd68681e7f4ca8f1f38df47bf81942a0d76a9673c2d23eff35b13
1129pyRFC3339==1.0 \
1130 --hash=sha256:eea31835c56e2096af4363a5745a784878a61d043e247d3a6d6a0a32a9741f56 \
1131 --hash=sha256:8dfbc6c458b8daba1c0f3620a8c78008b323a268b27b7359e92a4ae41325f535
1132python-augeas==0.5.0 \
1133 --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 \
1134 --no-binary python-augeas
1135pytz==2015.7 \
1136 --hash=sha256:3abe6a6d3fc2fbbe4c60144211f45da2edbe3182a6f6511af6bbba0598b1f992 \
1137 --hash=sha256:939ef9c1e1224d980405689a97ffcf7828c56d1517b31d73464356c1f2b7769e \
1138 --hash=sha256:ead4aefa7007249e05e51b01095719d5a8dd95760089f5730aac5698b1932918 \
1139 --hash=sha256:3cca0df08bd0ed98432390494ce3ded003f5e661aa460be7a734bffe35983605 \
1140 --hash=sha256:3ede470d3d17ba3c07638dfa0d10452bc1b6e5ad326127a65ba77e6aaeb11bec \
1141 --hash=sha256:68c47964f7186eec306b13629627722b9079cd4447ed9e5ecaecd4eac84ca734 \
1142 --hash=sha256:dd5d3991950aae40a6c81de1578942e73d629808cefc51d12cd157980e6cfc18 \
1143 --hash=sha256:a77c52062c07eb7c7b30545dbc73e32995b7e117eea750317b5cb5c7a4618f14 \
1144 --hash=sha256:81af9aec4bc960a9a0127c488f18772dae4634689233f06f65443e7b11ebeb51 \
1145 --hash=sha256:e079b1dadc5c06246cc1bb6fe1b23a50b1d1173f2edd5104efd40bb73a28f406 \
1146 --hash=sha256:fbd26746772c24cb93c8b97cbdad5cb9e46c86bbdb1b9d8a743ee00e2fb1fc5d \
1147 --hash=sha256:99266ef30a37e43932deec2b7ca73e83c8dbc3b9ff703ec73eca6b1dae6befea \
1148 --hash=sha256:8b6ce1c993909783bc96e0b4f34ea223bff7a4df2c90bdb9c4e0f1ac928689e3
1149requests==2.12.1 \
1150 --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \
1151 --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e
1152six==1.10.0 \
1153 --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \
1154 --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a
1155traceback2==1.4.0 \
1156 --hash=sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23 \
1157 --hash=sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030
1158unittest2==1.1.0 \
1159 --hash=sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8 \
1160 --hash=sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579
1161zope.component==4.2.2 \
1162 --hash=sha256:282c112b55dd8e3c869a3571f86767c150ab1284a9ace2bdec226c592acaf81a \
1163 --no-binary zope.component
1164zope.event==4.1.0 \
1165 --hash=sha256:dc7a59a2fd91730d3793131a5d261b29e93ec4e2a97f1bc487ce8defee2fe786 \
1166 --no-binary zope.event
1167zope.interface==4.1.3 \
1168 --hash=sha256:f07b631f7a601cd8cbd3332d54f43142c7088a83299f859356f08d1d4d4259b3 \
1169 --hash=sha256:de5cca083b9439d8002fb76bbe6b4998c5a5a721fab25b84298967f002df4c94 \
1170 --hash=sha256:6788416f7ea7f5b8a97be94825377aa25e8bdc73463e07baaf9858b29e737077 \
1171 --hash=sha256:6f3230f7254518201e5a3708cbb2de98c848304f06e3ded8bfb39e5825cba2e1 \
1172 --hash=sha256:5fa575a5240f04200c3088427d0d4b7b737f6e9018818a51d8d0f927a6a2517a \
1173 --hash=sha256:522194ad6a545735edd75c8a83f48d65d1af064e432a7d320d64f56bafc12e99 \
1174 --hash=sha256:e8c7b2d40943f71c99148c97f66caa7f5134147f57423f8db5b4825099ce9a09 \
1175 --hash=sha256:279024f0208601c3caa907c53876e37ad88625f7eaf1cb3842dbe360b2287017 \
1176 --hash=sha256:2e221a9eec7ccc58889a278ea13dcfed5ef939d80b07819a9a8b3cb1c681484f \
1177 --hash=sha256:69118965410ec86d44dc6b9017ee3ddbd582e0c0abeef62b3a19dbf6c8ad132b \
1178 --hash=sha256:d04df8686ec864d0cade8cf199f7f83aecd416109a20834d568f8310ded12dea \
1179 --hash=sha256:e75a947e15ee97e7e71e02ea302feb2fc62d3a2bb4668bf9dfbed43a506ac7e7 \
1180 --hash=sha256:4e45d22fb883222a5ab9f282a116fec5ee2e8d1a568ccff6a2d75bbd0eb6bcfc \
1181 --hash=sha256:bce9339bb3c7a55e0803b63d21c5839e8e479bc85c4adf42ae415b72f94facb2 \
1182 --hash=sha256:928138365245a0e8869a5999fbcc2a45475a0a6ed52a494d60dbdc540335fedd \
1183 --hash=sha256:0d841ba1bb840eea0e6489dc5ecafa6125554971f53b5acb87764441e61bceba \
1184 --hash=sha256:b09c8c1d47b3531c400e0195697f1414a63221de6ef478598a4f1460f7d9a392
1185requests-toolbelt==0.8.0 \
1186 --hash=sha256:42c9c170abc2cacb78b8ab23ac957945c7716249206f90874651971a4acff237 \
1187 --hash=sha256:f6a531936c6fa4c6cfce1b9c10d5c4f498d16528d2a54a22ca00011205a187b5
1188
1189# Contains the requirements for the letsencrypt package.
1190#
1191# Since the letsencrypt package depends on certbot and using pip with hashes
1192# requires that all installed packages have hashes listed, this allows
1193# dependency-requirements.txt to be used without requiring a hash for a
1194# (potentially unreleased) Certbot package.
1195
1196letsencrypt==0.7.0 \
1197 --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
1198 --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
1199
1200certbot==0.26.1 \
1201 --hash=sha256:4e2ffdeebb7f5097600bcb1ca19131441fa021f952b443ca7454a279337af609 \
1202 --hash=sha256:4983513d63f7f36e24a07873ca2d6ea1c0101aa6cb1cd825cda02ed520f6ca66
1203acme==0.26.1 \
1204 --hash=sha256:d47841e66adc1336ecca2f0d41a247c1b62307c981be6d07996bbf3f95af1dc5 \
1205 --hash=sha256:86e7b5f4654cb19215f16c0e6225750db7421f68ef6a0a040a61796f24e690be
1206certbot-apache==0.26.1 \
1207 --hash=sha256:c16acb49bd4f84fff25bcbb7eaf74412145efe9b68ce46e1803be538894f2ce3 \
1208 --hash=sha256:b7fa327e987b892d64163e7519bdeaf9723d78275ef6c438272848894ace6d87
1209certbot-nginx==0.26.1 \
1210 --hash=sha256:c0048dc83672dc90805a8ddf513be3e48c841d6e91607e91e8657c1785d65660 \
1211 --hash=sha256:d0c95a32625e0f1612d7fcf9021e6e050ba3d879823489d1edd2478a78ae6624
1212
1213UNLIKELY_EOF
1214 # -------------------------------------------------------------------------
1215 cat << "UNLIKELY_EOF" > "$TEMP_DIR/pipstrap.py"
1216#!/usr/bin/env python
1217"""A small script that can act as a trust root for installing pip >=8
1218
1219Embed this in your project, and your VCS checkout is all you have to trust. In
1220a post-peep era, this lets you claw your way to a hash-checking version of pip,
1221with which you can install the rest of your dependencies safely. All it assumes
1222is Python 2.6 or better and *some* version of pip already installed. If
1223anything goes wrong, it will exit with a non-zero status code.
1224
1225"""
1226# This is here so embedded copies are MIT-compliant:
1227# Copyright (c) 2016 Erik Rose
1228#
1229# Permission is hereby granted, free of charge, to any person obtaining a copy
1230# of this software and associated documentation files (the "Software"), to
1231# deal in the Software without restriction, including without limitation the
1232# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1233# sell copies of the Software, and to permit persons to whom the Software is
1234# furnished to do so, subject to the following conditions:
1235#
1236# The above copyright notice and this permission notice shall be included in
1237# all copies or substantial portions of the Software.
1238from __future__ import print_function
1239from distutils.version import StrictVersion
1240from hashlib import sha256
1241from os import environ
1242from os.path import join
1243from pipes import quote
1244from shutil import rmtree
1245try:
1246 from subprocess import check_output
1247except ImportError:
1248 from subprocess import CalledProcessError, PIPE, Popen
1249
1250 def check_output(*popenargs, **kwargs):
1251 if 'stdout' in kwargs:
1252 raise ValueError('stdout argument not allowed, it will be '
1253 'overridden.')
1254 process = Popen(stdout=PIPE, *popenargs, **kwargs)
1255 output, unused_err = process.communicate()
1256 retcode = process.poll()
1257 if retcode:
1258 cmd = kwargs.get("args")
1259 if cmd is None:
1260 cmd = popenargs[0]
1261 raise CalledProcessError(retcode, cmd)
1262 return output
1263from sys import exit, version_info
1264from tempfile import mkdtemp
1265try:
1266 from urllib2 import build_opener, HTTPHandler, HTTPSHandler
1267except ImportError:
1268 from urllib.request import build_opener, HTTPHandler, HTTPSHandler
1269try:
1270 from urlparse import urlparse
1271except ImportError:
1272 from urllib.parse import urlparse # 3.4
1273
1274
1275__version__ = 1, 5, 1
1276PIP_VERSION = '9.0.1'
1277DEFAULT_INDEX_BASE = 'https://pypi.python.org'
1278
1279
1280# wheel has a conditional dependency on argparse:
1281maybe_argparse = (
1282 [('18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
1283 'argparse-1.4.0.tar.gz',
1284 '62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')]
1285 if version_info < (2, 7, 0) else [])
1286
1287
1288PACKAGES = maybe_argparse + [
1289 # Pip has no dependencies, as it vendors everything:
1290 ('11/b6/abcb525026a4be042b486df43905d6893fb04f05aac21c32c638e939e447/'
1291 'pip-{0}.tar.gz'.format(PIP_VERSION),
1292 '09f243e1a7b461f654c26a725fa373211bb7ff17a9300058b205c61658ca940d'),
1293 # This version of setuptools has only optional dependencies:
1294 ('59/88/2f3990916931a5de6fa9706d6d75eb32ee8b78627bb2abaab7ed9e6d0622/'
1295 'setuptools-29.0.1.tar.gz',
1296 'b539118819a4857378398891fa5366e090690e46b3e41421a1e07d6e9fd8feb0'),
1297 ('c9/1d/bd19e691fd4cfe908c76c429fe6e4436c9e83583c4414b54f6c85471954a/'
1298 'wheel-0.29.0.tar.gz',
1299 '1ebb8ad7e26b448e9caa4773d2357849bf80ff9e313964bcaf79cbf0201a1648')
1300]
1301
1302
1303class HashError(Exception):
1304 def __str__(self):
1305 url, path, actual, expected = self.args
1306 return ('{url} did not match the expected hash {expected}. Instead, '
1307 'it was {actual}. The file (left at {path}) may have been '
1308 'tampered with.'.format(**locals()))
1309
1310
1311def hashed_download(url, temp, digest):
1312 """Download ``url`` to ``temp``, make sure it has the SHA-256 ``digest``,
1313 and return its path."""
1314 # Based on pip 1.4.1's URLOpener but with cert verification removed. Python
1315 # >=2.7.9 verifies HTTPS certs itself, and, in any case, the cert
1316 # authenticity has only privacy (not arbitrary code execution)
1317 # implications, since we're checking hashes.
1318 def opener(using_https=True):
1319 opener = build_opener(HTTPSHandler())
1320 if using_https:
1321 # Strip out HTTPHandler to prevent MITM spoof:
1322 for handler in opener.handlers:
1323 if isinstance(handler, HTTPHandler):
1324 opener.handlers.remove(handler)
1325 return opener
1326
1327 def read_chunks(response, chunk_size):
1328 while True:
1329 chunk = response.read(chunk_size)
1330 if not chunk:
1331 break
1332 yield chunk
1333
1334 parsed_url = urlparse(url)
1335 response = opener(using_https=parsed_url.scheme == 'https').open(url)
1336 path = join(temp, parsed_url.path.split('/')[-1])
1337 actual_hash = sha256()
1338 with open(path, 'wb') as file:
1339 for chunk in read_chunks(response, 4096):
1340 file.write(chunk)
1341 actual_hash.update(chunk)
1342
1343 actual_digest = actual_hash.hexdigest()
1344 if actual_digest != digest:
1345 raise HashError(url, path, actual_digest, digest)
1346 return path
1347
1348
1349def get_index_base():
1350 """Return the URL to the dir containing the "packages" folder.
1351
1352 Try to wring something out of PIP_INDEX_URL, if set. Hack "/simple" off the
1353 end if it's there; that is likely to give us the right dir.
1354
1355 """
1356 env_var = environ.get('PIP_INDEX_URL', '').rstrip('/')
1357 if env_var:
1358 SIMPLE = '/simple'
1359 if env_var.endswith(SIMPLE):
1360 return env_var[:-len(SIMPLE)]
1361 else:
1362 return env_var
1363 else:
1364 return DEFAULT_INDEX_BASE
1365
1366
1367def main():
1368 pip_version = StrictVersion(check_output(['pip', '--version'])
1369 .decode('utf-8').split()[1])
1370 min_pip_version = StrictVersion(PIP_VERSION)
1371 if pip_version >= min_pip_version:
1372 return 0
1373 has_pip_cache = pip_version >= StrictVersion('6.0')
1374 index_base = get_index_base()
1375 temp = mkdtemp(prefix='pipstrap-')
1376 try:
1377 downloads = [hashed_download(index_base + '/packages/' + path,
1378 temp,
1379 digest)
1380 for path, digest in PACKAGES]
1381 check_output('pip install --no-index --no-deps -U ' +
1382 # Disable cache since we're not using it and it otherwise
1383 # sometimes throws permission warnings:
1384 ('--no-cache-dir ' if has_pip_cache else '') +
1385 ' '.join(quote(d) for d in downloads),
1386 shell=True)
1387 except HashError as exc:
1388 print(exc)
1389 except Exception:
1390 rmtree(temp)
1391 raise
1392 else:
1393 rmtree(temp)
1394 return 0
1395 return 1
1396
1397
1398if __name__ == '__main__':
1399 exit(main())
1400
1401UNLIKELY_EOF
1402 # -------------------------------------------------------------------------
1403 # Set PATH so pipstrap upgrades the right (v)env:
1404 PATH="$VENV_BIN:$PATH" "$VENV_BIN/python" "$TEMP_DIR/pipstrap.py"
1405 set +e
1406 if [ "$VERBOSE" = 1 ]; then
1407 "$VENV_BIN/pip" install --disable-pip-version-check --no-cache-dir --require-hashes -r "$TEMP_DIR/letsencrypt-auto-requirements.txt"
1408 else
1409 PIP_OUT=`"$VENV_BIN/pip" install --disable-pip-version-check --no-cache-dir --require-hashes -r "$TEMP_DIR/letsencrypt-auto-requirements.txt" 2>&1`
1410 fi
1411 PIP_STATUS=$?
1412 set -e
1413 if [ "$PIP_STATUS" != 0 ]; then
1414 # Report error. (Otherwise, be quiet.)
1415 error "Had a problem while installing Python packages."
1416 if [ "$VERBOSE" != 1 ]; then
1417 error
1418 error "pip prints the following errors: "
1419 error "====================================================="
1420 error "$PIP_OUT"
1421 error "====================================================="
1422 error
1423 error "Certbot has problem setting up the virtual environment."
1424
1425 if `echo $PIP_OUT | grep -q Killed` || `echo $PIP_OUT | grep -q "allocate memory"` ; then
1426 error
1427 error "Based on your pip output, the problem can likely be fixed by "
1428 error "increasing the available memory."
1429 else
1430 error
1431 error "We were not be able to guess the right solution from your pip "
1432 error "output."
1433 fi
1434
1435 error
1436 error "Consult https://certbot.eff.org/docs/install.html#problems-with-python-virtual-environment"
1437 error "for possible solutions."
1438 error "You may also find some support resources at https://certbot.eff.org/support/ ."
1439 fi
1440 rm -rf "$VENV_PATH"
1441 exit 1
1442 fi
1443
1444 if [ -d "$OLD_VENV_PATH" -a ! -L "$OLD_VENV_PATH" ]; then
1445 rm -rf "$OLD_VENV_PATH"
1446 ln -s "$VENV_PATH" "$OLD_VENV_PATH"
1447 fi
1448
1449 say "Installation succeeded."
1450 fi
1451
1452 if [ "$INSTALL_ONLY" = 1 ]; then
1453 say "Certbot is installed."
1454 exit 0
1455 fi
1456
1457 "$VENV_BIN/letsencrypt" "$@"
1458
1459else
1460 # Phase 1: Upgrade certbot-auto if necessary, then self-invoke.
1461 #
1462 # Each phase checks the version of only the thing it is responsible for
1463 # upgrading. Phase 1 checks the version of the latest release of
1464 # certbot-auto (which is always the same as that of the certbot
1465 # package). Phase 2 checks the version of the locally installed certbot.
1466 export PHASE_1_VERSION="$LE_AUTO_VERSION"
1467
1468 if [ ! -f "$VENV_BIN/letsencrypt" ]; then
1469 if ! OldVenvExists; then
1470 if [ "$HELP" = 1 ]; then
1471 echo "$USAGE"
1472 exit 0
1473 fi
1474 # If it looks like we've never bootstrapped before, bootstrap:
1475 Bootstrap
1476 fi
1477 fi
1478 if [ "$OS_PACKAGES_ONLY" = 1 ]; then
1479 say "OS packages installed."
1480 exit 0
1481 fi
1482
1483 if [ "$NO_SELF_UPGRADE" != 1 ]; then
1484 TEMP_DIR=$(TempDir)
1485 trap 'rm -rf "$TEMP_DIR"' EXIT
1486 # ---------------------------------------------------------------------------
1487 cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py"
1488"""Do downloading and JSON parsing without additional dependencies. ::
1489
1490 # Print latest released version of LE to stdout:
1491 python fetch.py --latest-version
1492
1493 # Download letsencrypt-auto script from git tag v1.2.3 into the folder I'm
1494 # in, and make sure its signature verifies:
1495 python fetch.py --le-auto-script v1.2.3
1496
1497On failure, return non-zero.
1498
1499"""
1500
1501from __future__ import print_function, unicode_literals
1502
1503from distutils.version import LooseVersion
1504from json import loads
1505from os import devnull, environ
1506from os.path import dirname, join
1507import re
1508import ssl
1509from subprocess import check_call, CalledProcessError
1510from sys import argv, exit
1511try:
1512 from urllib2 import build_opener, HTTPHandler, HTTPSHandler
1513 from urllib2 import HTTPError, URLError
1514except ImportError:
1515 from urllib.request import build_opener, HTTPHandler, HTTPSHandler
1516 from urllib.error import HTTPError, URLError
1517
1518PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
1519MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
1520OzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18
1521xUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp
15229+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij
1523n9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH
1524cXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+
1525CQIDAQAB
1526-----END PUBLIC KEY-----
1527""")
1528
1529class ExpectedError(Exception):
1530 """A novice-readable exception that also carries the original exception for
1531 debugging"""
1532
1533
1534class HttpsGetter(object):
1535 def __init__(self):
1536 """Build an HTTPS opener."""
1537 # Based on pip 1.4.1's URLOpener
1538 # This verifies certs on only Python >=2.7.9, and when NO_CERT_VERIFY isn't set.
1539 if environ.get('NO_CERT_VERIFY') == '1' and hasattr(ssl, 'SSLContext'):
1540 self._opener = build_opener(HTTPSHandler(context=cert_none_context()))
1541 else:
1542 self._opener = build_opener(HTTPSHandler())
1543 # Strip out HTTPHandler to prevent MITM spoof:
1544 for handler in self._opener.handlers:
1545 if isinstance(handler, HTTPHandler):
1546 self._opener.handlers.remove(handler)
1547
1548 def get(self, url):
1549 """Return the document contents pointed to by an HTTPS URL.
1550
1551 If something goes wrong (404, timeout, etc.), raise ExpectedError.
1552
1553 """
1554 try:
1555 # socket module docs say default timeout is None: that is, no
1556 # timeout
1557 return self._opener.open(url, timeout=30).read()
1558 except (HTTPError, IOError) as exc:
1559 raise ExpectedError("Couldn't download %s." % url, exc)
1560
1561
1562def write(contents, dir, filename):
1563 """Write something to a file in a certain directory."""
1564 with open(join(dir, filename), 'wb') as file:
1565 file.write(contents)
1566
1567
1568def latest_stable_version(get):
1569 """Return the latest stable release of letsencrypt."""
1570 metadata = loads(get(
1571 environ.get('LE_AUTO_JSON_URL',
1572 'https://pypi.python.org/pypi/certbot/json')).decode('UTF-8'))
1573 # metadata['info']['version'] actually returns the latest of any kind of
1574 # release release, contrary to https://wiki.python.org/moin/PyPIJSON.
1575 # The regex is a sufficient regex for picking out prereleases for most
1576 # packages, LE included.
1577 return str(max(LooseVersion(r) for r
1578 in metadata['releases'].keys()
1579 if re.match('^[0-9.]+$', r)))
1580
1581
1582def verified_new_le_auto(get, tag, temp_dir):
1583 """Return the path to a verified, up-to-date letsencrypt-auto script.
1584
1585 If the download's signature does not verify or something else goes wrong
1586 with the verification process, raise ExpectedError.
1587
1588 """
1589 le_auto_dir = environ.get(
1590 'LE_AUTO_DIR_TEMPLATE',
1591 'https://raw.githubusercontent.com/certbot/certbot/%s/'
1592 'letsencrypt-auto-source/') % tag
1593 write(get(le_auto_dir + 'letsencrypt-auto'), temp_dir, 'letsencrypt-auto')
1594 write(get(le_auto_dir + 'letsencrypt-auto.sig'), temp_dir, 'letsencrypt-auto.sig')
1595 write(PUBLIC_KEY.encode('UTF-8'), temp_dir, 'public_key.pem')
1596 try:
1597 with open(devnull, 'w') as dev_null:
1598 check_call(['openssl', 'dgst', '-sha256', '-verify',
1599 join(temp_dir, 'public_key.pem'),
1600 '-signature',
1601 join(temp_dir, 'letsencrypt-auto.sig'),
1602 join(temp_dir, 'letsencrypt-auto')],
1603 stdout=dev_null,
1604 stderr=dev_null)
1605 except CalledProcessError as exc:
1606 raise ExpectedError("Couldn't verify signature of downloaded "
1607 "certbot-auto.", exc)
1608
1609
1610def cert_none_context():
1611 """Create a SSLContext object to not check hostname."""
1612 # PROTOCOL_TLS isn't available before 2.7.13 but this code is for 2.7.9+, so use this.
1613 context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
1614 context.verify_mode = ssl.CERT_NONE
1615 return context
1616
1617
1618def main():
1619 get = HttpsGetter().get
1620 flag = argv[1]
1621 try:
1622 if flag == '--latest-version':
1623 print(latest_stable_version(get))
1624 elif flag == '--le-auto-script':
1625 tag = argv[2]
1626 verified_new_le_auto(get, tag, dirname(argv[0]))
1627 except ExpectedError as exc:
1628 print(exc.args[0], exc.args[1])
1629 return 1
1630 else:
1631 return 0
1632
1633
1634if __name__ == '__main__':
1635 exit(main())
1636
1637UNLIKELY_EOF
1638 # ---------------------------------------------------------------------------
1639 DeterminePythonVersion "NOCRASH"
1640 if [ "$PYVER" -lt "$MIN_PYVER" ]; then
1641 error "WARNING: couldn't find Python $MIN_PYTHON_VERSION+ to check for updates."
1642 elif ! REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` ; then
1643 error "WARNING: unable to check for updates."
1644 elif [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then
1645 say "Upgrading certbot-auto $LE_AUTO_VERSION to $REMOTE_VERSION..."
1646
1647 # Now we drop into Python so we don't have to install even more
1648 # dependencies (curl, etc.), for better flow control, and for the option of
1649 # future Windows compatibility.
1650 "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION"
1651
1652 # Install new copy of certbot-auto.
1653 # TODO: Deal with quotes in pathnames.
1654 say "Replacing certbot-auto..."
1655 # Clone permissions with cp. chmod and chown don't have a --reference
1656 # option on macOS or BSD, and stat -c on Linux is stat -f on macOS and BSD:
1657 cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone"
1658 cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone"
1659 # Using mv rather than cp leaves the old file descriptor pointing to the
1660 # original copy so the shell can continue to read it unmolested. mv across
1661 # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the
1662 # cp is unlikely to fail if the rm doesn't.
1663 mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0"
1664 fi # A newer version is available.
1665 fi # Self-upgrading is allowed.
1666
1667 RerunWithArgs --le-auto-phase2 "$@"
1668fi
Note: See TracBrowser for help on using the repository browser.