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 |
|
---|
14 | set -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
|
---|
20 | if [ -z "$HOME" ]; then
|
---|
21 | HOME=~root
|
---|
22 | fi
|
---|
23 | if [ -z "$XDG_DATA_HOME" ]; then
|
---|
24 | XDG_DATA_HOME=~/.local/share
|
---|
25 | fi
|
---|
26 | if [ -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"
|
---|
31 | fi
|
---|
32 | VENV_BIN="$VENV_PATH/bin"
|
---|
33 | BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
|
---|
34 | LE_AUTO_VERSION="0.26.1"
|
---|
35 | BASENAME=$(basename $0)
|
---|
36 | USAGE="Usage: $BASENAME [OPTIONS]
|
---|
37 | A self-updating wrapper script for the Certbot ACME client. When run, updates
|
---|
38 | to both this script and certbot will be downloaded and installed. After
|
---|
39 | ensuring you have the latest versions installed, certbot will be invoked with
|
---|
40 | all arguments you have provided.
|
---|
41 |
|
---|
42 | Help 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 |
|
---|
55 | All arguments are accepted and forwarded to the Certbot client when run."
|
---|
56 | export CERTBOT_AUTO="$0"
|
---|
57 |
|
---|
58 | for 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
|
---|
97 | done
|
---|
98 |
|
---|
99 | if [ $BASENAME = "letsencrypt-auto" ]; then
|
---|
100 | # letsencrypt-auto does not respect --help or --yes for backwards compatibility
|
---|
101 | NONINTERACTIVE=1
|
---|
102 | HELP=0
|
---|
103 | fi
|
---|
104 |
|
---|
105 | # Set ASSUME_YES to 1 if QUIET or NONINTERACTIVE
|
---|
106 | if [ "$QUIET" = 1 -o "$NONINTERACTIVE" = 1 ]; then
|
---|
107 | ASSUME_YES=1
|
---|
108 | fi
|
---|
109 |
|
---|
110 | say() {
|
---|
111 | if [ "$QUIET" != 1 ]; then
|
---|
112 | echo "$@"
|
---|
113 | fi
|
---|
114 | }
|
---|
115 |
|
---|
116 | error() {
|
---|
117 | echo "$@"
|
---|
118 | }
|
---|
119 |
|
---|
120 | # Support for busybox and others where there is no "command",
|
---|
121 | # but "which" instead
|
---|
122 | if command -v command > /dev/null 2>&1 ; then
|
---|
123 | export EXISTS="command -v"
|
---|
124 | elif which which > /dev/null 2>&1 ; then
|
---|
125 | export EXISTS="which"
|
---|
126 | else
|
---|
127 | error "Cannot find command nor which... please install one!"
|
---|
128 | exit 1
|
---|
129 | fi
|
---|
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.
|
---|
142 | SuSudo() {
|
---|
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.
|
---|
165 | SetRootAuthMechanism() {
|
---|
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 |
|
---|
193 | if [ "$1" = "--cb-auto-has-root" ]; then
|
---|
194 | shift 1
|
---|
195 | else
|
---|
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
|
---|
202 | fi
|
---|
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.
|
---|
207 | RerunWithArgs() {
|
---|
208 | "$0" --cb-auto-has-root "$@"
|
---|
209 | exit 0
|
---|
210 | }
|
---|
211 |
|
---|
212 | BootstrapMessage() {
|
---|
213 | # Arguments: Platform name
|
---|
214 | say "Bootstrapping dependencies for $1... (you can skip this with --no-bootstrap)"
|
---|
215 | }
|
---|
216 |
|
---|
217 | ExperimentalBootstrap() {
|
---|
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 |
|
---|
234 | DeprecationBootstrap() {
|
---|
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 |
|
---|
252 | MIN_PYTHON_VERSION="2.7"
|
---|
253 | MIN_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
|
---|
256 | DeterminePythonVersion() {
|
---|
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.
|
---|
293 | BOOTSTRAP_DEB_COMMON_VERSION=1
|
---|
294 |
|
---|
295 | BootstrapDebCommon() {
|
---|
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.
|
---|
417 | InitializeRPMCommonBase() {
|
---|
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 |
|
---|
458 | BootstrapRpmCommonBase() {
|
---|
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.
|
---|
492 | BOOTSTRAP_RPM_COMMON_VERSION=1
|
---|
493 |
|
---|
494 | BootstrapRpmCommon() {
|
---|
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.
|
---|
538 | BOOTSTRAP_RPM_PYTHON3_VERSION=1
|
---|
539 |
|
---|
540 | BootstrapRpmPython3() {
|
---|
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.
|
---|
562 | BOOTSTRAP_SUSE_COMMON_VERSION=1
|
---|
563 |
|
---|
564 | BootstrapSuseCommon() {
|
---|
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.
|
---|
589 | BOOTSTRAP_ARCH_COMMON_VERSION=1
|
---|
590 |
|
---|
591 | BootstrapArchCommon() {
|
---|
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.
|
---|
628 | BOOTSTRAP_GENTOO_COMMON_VERSION=1
|
---|
629 |
|
---|
630 | BootstrapGentooCommon() {
|
---|
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.
|
---|
660 | BOOTSTRAP_FREEBSD_VERSION=1
|
---|
661 |
|
---|
662 | BootstrapFreeBsd() {
|
---|
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.
|
---|
676 | BOOTSTRAP_MAC_VERSION=1
|
---|
677 |
|
---|
678 | BootstrapMac() {
|
---|
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.
|
---|
725 | BOOTSTRAP_SMARTOS_VERSION=1
|
---|
726 |
|
---|
727 | BootstrapSmartOS() {
|
---|
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.
|
---|
734 | BOOTSTRAP_MAGEIA_COMMON_VERSION=1
|
---|
735 |
|
---|
736 | BootstrapMageiaCommon() {
|
---|
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.
|
---|
768 | if [ -f /etc/debian_version ]; then
|
---|
769 | Bootstrap() {
|
---|
770 | BootstrapMessage "Debian-based OSes"
|
---|
771 | BootstrapDebCommon
|
---|
772 | }
|
---|
773 | BOOTSTRAP_VERSION="BootstrapDebCommon $BOOTSTRAP_DEB_COMMON_VERSION"
|
---|
774 | elif [ -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"
|
---|
780 | elif [ -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"
|
---|
802 | elif [ -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"
|
---|
808 | elif [ -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"
|
---|
823 | elif [ -f /etc/manjaro-release ]; then
|
---|
824 | Bootstrap() {
|
---|
825 | ExperimentalBootstrap "Manjaro Linux" BootstrapArchCommon
|
---|
826 | }
|
---|
827 | BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION"
|
---|
828 | elif [ -f /etc/gentoo-release ]; then
|
---|
829 | Bootstrap() {
|
---|
830 | DeprecationBootstrap "Gentoo" BootstrapGentooCommon
|
---|
831 | }
|
---|
832 | BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION"
|
---|
833 | elif uname | grep -iq FreeBSD ; then
|
---|
834 | Bootstrap() {
|
---|
835 | DeprecationBootstrap "FreeBSD" BootstrapFreeBsd
|
---|
836 | }
|
---|
837 | BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION"
|
---|
838 | elif uname | grep -iq Darwin ; then
|
---|
839 | Bootstrap() {
|
---|
840 | DeprecationBootstrap "macOS" BootstrapMac
|
---|
841 | }
|
---|
842 | BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION"
|
---|
843 | elif [ -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"
|
---|
848 | elif [ -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"
|
---|
853 | else
|
---|
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 | }
|
---|
862 | fi
|
---|
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.
|
---|
868 | if [ "$NO_BOOTSTRAP" = 1 ]; then
|
---|
869 | Bootstrap() {
|
---|
870 | :
|
---|
871 | }
|
---|
872 | unset BOOTSTRAP_VERSION
|
---|
873 | fi
|
---|
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.
|
---|
878 | SetPrevBootstrapVersion() {
|
---|
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"
|
---|
886 | BootstrapDebCommon 1
|
---|
887 | BootstrapMageiaCommon 1
|
---|
888 | BootstrapRpmCommon 1
|
---|
889 | BootstrapSuseCommon 1
|
---|
890 | BootstrapArchCommon 1
|
---|
891 | BootstrapGentooCommon 1
|
---|
892 | BootstrapFreeBsd 1
|
---|
893 | BootstrapMac 1
|
---|
894 | BootstrapSmartOS 1
|
---|
895 | UNLIKELY_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 |
|
---|
905 | TempDir() {
|
---|
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.
|
---|
911 | OldVenvExists() {
|
---|
912 | [ -n "$OLD_VENV_PATH" -a -f "$OLD_VENV_PATH/bin/letsencrypt" ]
|
---|
913 | }
|
---|
914 |
|
---|
915 | if [ "$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 |
|
---|
1007 | argparse==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.
|
---|
1013 | pycparser==2.14 \
|
---|
1014 | --hash=sha256:7959b4a74abdc27b312fed1c21e6caf9309ce0b29ea86b591fd2e99ecdf27f73 \
|
---|
1015 | --no-binary pycparser
|
---|
1016 |
|
---|
1017 | asn1crypto==0.22.0 \
|
---|
1018 | --hash=sha256:d232509fefcfcdb9a331f37e9c9dc20441019ad927c7d2176cf18ed5da0ba097 \
|
---|
1019 | --hash=sha256:cbbadd640d3165ab24b06ef25d1dca09a3441611ac15f6a6b452474fdf0aed1a
|
---|
1020 | cffi==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
|
---|
1057 | ConfigArgParse==0.12.0 \
|
---|
1058 | --hash=sha256:28cd7d67669651f2a4518367838c49539457504584a139709b2b8f6c208ef339 \
|
---|
1059 | --no-binary ConfigArgParse
|
---|
1060 | configobj==5.0.6 \
|
---|
1061 | --hash=sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902 \
|
---|
1062 | --no-binary configobj
|
---|
1063 | cryptography==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
|
---|
1083 | enum34==1.1.2 ; python_version < '3.4' \
|
---|
1084 | --hash=sha256:2475d7fcddf5951e92ff546972758802de5260bf409319a9f1934e6bbc8b1dc7 \
|
---|
1085 | --hash=sha256:35907defb0f992b75ab7788f65fedc1cf20ffa22688e0e6f6f12afc06b3ea501
|
---|
1086 | funcsigs==1.0.2 \
|
---|
1087 | --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \
|
---|
1088 | --hash=sha256:a7bb0f2cf3a3fd1ab2732cb49eba4252c2af4240442415b4abce3b87022a8f50
|
---|
1089 | idna==2.5 \
|
---|
1090 | --hash=sha256:cc19709fd6d0cbfed39ea875d29ba6d4e22c0cebc510a76d6302a28385e8bb70 \
|
---|
1091 | --hash=sha256:3cb5ce08046c4e3a560fc02f138d0ac63e00f8ce5901a56b32ec8b7994082aab
|
---|
1092 | ipaddress==1.0.16 \
|
---|
1093 | --hash=sha256:935712800ce4760701d89ad677666cd52691fd2f6f0b340c8b4239a3c17988a5 \
|
---|
1094 | --hash=sha256:5a3182b322a706525c46282ca6f064d27a02cffbd449f9f47416f1dc96aa71b0
|
---|
1095 | josepy==1.1.0 \
|
---|
1096 | --hash=sha256:1309a25aac3caeff5239729c58ff9b583f7d022ffdb1553406ddfc8e5b52b76e \
|
---|
1097 | --hash=sha256:fb5c62c77d26e04df29cb5ecd01b9ce69b6fcc9e521eb1ca193b7faa2afa7086
|
---|
1098 | linecache2==1.0.0 \
|
---|
1099 | --hash=sha256:e78be9c0a0dfcbac712fe04fbf92b96cddae80b1b842f24248214c8496f006ef \
|
---|
1100 | --hash=sha256:4b26ff4e7110db76eeb6f5a7b64a82623839d595c2038eeda662f2a2db78e97c
|
---|
1101 | # Using an older version of mock here prevents regressions of #5276.
|
---|
1102 | mock==1.3.0 \
|
---|
1103 | --hash=sha256:3f573a18be94de886d1191f27c168427ef693e8dcfcecf95b170577b2eb69cbb \
|
---|
1104 | --hash=sha256:1e247dbecc6ce057299eb7ee019ad68314bb93152e81d9a6110d35f4d5eca0f6
|
---|
1105 | ordereddict==1.1 \
|
---|
1106 | --hash=sha256:1c35b4ac206cef2d24816c89f89cf289dd3d38cf7c449bb3fab7bf6d43f01b1f \
|
---|
1107 | --no-binary ordereddict
|
---|
1108 | packaging==16.8 \
|
---|
1109 | --hash=sha256:99276dc6e3a7851f32027a68f1095cd3f77c148091b092ea867a351811cfe388 \
|
---|
1110 | --hash=sha256:5d50835fdf0a7edf0b55e311b7c887786504efea1177abd7e69329a8e5ea619e
|
---|
1111 | parsedatetime==2.1 \
|
---|
1112 | --hash=sha256:ce9d422165cf6e963905cd5f74f274ebf7cc98c941916169178ef93f0e557838 \
|
---|
1113 | --hash=sha256:17c578775520c99131634e09cfca5a05ea9e1bd2a05cd06967ebece10df7af2d
|
---|
1114 | pbr==1.8.1 \
|
---|
1115 | --hash=sha256:46c8db75ae75a056bd1cc07fa21734fe2e603d11a07833ecc1eeb74c35c72e0c \
|
---|
1116 | --hash=sha256:e2127626a91e6c885db89668976db31020f0af2da728924b56480fc7ccf09649
|
---|
1117 | pyOpenSSL==16.2.0 \
|
---|
1118 | --hash=sha256:26ca380ddf272f7556e48064bbcd5bd71f83dfc144f3583501c7ddbd9434ee17 \
|
---|
1119 | --hash=sha256:7779a3bbb74e79db234af6a08775568c6769b5821faecf6e2f4143edb227516e
|
---|
1120 | pyparsing==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
|
---|
1129 | pyRFC3339==1.0 \
|
---|
1130 | --hash=sha256:eea31835c56e2096af4363a5745a784878a61d043e247d3a6d6a0a32a9741f56 \
|
---|
1131 | --hash=sha256:8dfbc6c458b8daba1c0f3620a8c78008b323a268b27b7359e92a4ae41325f535
|
---|
1132 | python-augeas==0.5.0 \
|
---|
1133 | --hash=sha256:67d59d66cdba8d624e0389b87b2a83a176f21f16a87553b50f5703b23f29bac2 \
|
---|
1134 | --no-binary python-augeas
|
---|
1135 | pytz==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
|
---|
1149 | requests==2.12.1 \
|
---|
1150 | --hash=sha256:3f3f27a9d0f9092935efc78054ef324eb9f8166718270aefe036dfa1e4f68e1e \
|
---|
1151 | --hash=sha256:2109ecea94df90980be040490ff1d879971b024861539abb00054062388b612e
|
---|
1152 | six==1.10.0 \
|
---|
1153 | --hash=sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1 \
|
---|
1154 | --hash=sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a
|
---|
1155 | traceback2==1.4.0 \
|
---|
1156 | --hash=sha256:8253cebec4b19094d67cc5ed5af99bf1dba1285292226e98a31929f87a5d6b23 \
|
---|
1157 | --hash=sha256:05acc67a09980c2ecfedd3423f7ae0104839eccb55fc645773e1caa0951c3030
|
---|
1158 | unittest2==1.1.0 \
|
---|
1159 | --hash=sha256:13f77d0875db6d9b435e1d4f41e74ad4cc2eb6e1d5c824996092b3430f088bb8 \
|
---|
1160 | --hash=sha256:22882a0e418c284e1f718a822b3b022944d53d2d908e1690b319a9d3eb2c0579
|
---|
1161 | zope.component==4.2.2 \
|
---|
1162 | --hash=sha256:282c112b55dd8e3c869a3571f86767c150ab1284a9ace2bdec226c592acaf81a \
|
---|
1163 | --no-binary zope.component
|
---|
1164 | zope.event==4.1.0 \
|
---|
1165 | --hash=sha256:dc7a59a2fd91730d3793131a5d261b29e93ec4e2a97f1bc487ce8defee2fe786 \
|
---|
1166 | --no-binary zope.event
|
---|
1167 | zope.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
|
---|
1185 | requests-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 |
|
---|
1196 | letsencrypt==0.7.0 \
|
---|
1197 | --hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
|
---|
1198 | --hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
|
---|
1199 |
|
---|
1200 | certbot==0.26.1 \
|
---|
1201 | --hash=sha256:4e2ffdeebb7f5097600bcb1ca19131441fa021f952b443ca7454a279337af609 \
|
---|
1202 | --hash=sha256:4983513d63f7f36e24a07873ca2d6ea1c0101aa6cb1cd825cda02ed520f6ca66
|
---|
1203 | acme==0.26.1 \
|
---|
1204 | --hash=sha256:d47841e66adc1336ecca2f0d41a247c1b62307c981be6d07996bbf3f95af1dc5 \
|
---|
1205 | --hash=sha256:86e7b5f4654cb19215f16c0e6225750db7421f68ef6a0a040a61796f24e690be
|
---|
1206 | certbot-apache==0.26.1 \
|
---|
1207 | --hash=sha256:c16acb49bd4f84fff25bcbb7eaf74412145efe9b68ce46e1803be538894f2ce3 \
|
---|
1208 | --hash=sha256:b7fa327e987b892d64163e7519bdeaf9723d78275ef6c438272848894ace6d87
|
---|
1209 | certbot-nginx==0.26.1 \
|
---|
1210 | --hash=sha256:c0048dc83672dc90805a8ddf513be3e48c841d6e91607e91e8657c1785d65660 \
|
---|
1211 | --hash=sha256:d0c95a32625e0f1612d7fcf9021e6e050ba3d879823489d1edd2478a78ae6624
|
---|
1212 |
|
---|
1213 | UNLIKELY_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 |
|
---|
1219 | Embed this in your project, and your VCS checkout is all you have to trust. In
|
---|
1220 | a post-peep era, this lets you claw your way to a hash-checking version of pip,
|
---|
1221 | with which you can install the rest of your dependencies safely. All it assumes
|
---|
1222 | is Python 2.6 or better and *some* version of pip already installed. If
|
---|
1223 | anything 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.
|
---|
1238 | from __future__ import print_function
|
---|
1239 | from distutils.version import StrictVersion
|
---|
1240 | from hashlib import sha256
|
---|
1241 | from os import environ
|
---|
1242 | from os.path import join
|
---|
1243 | from pipes import quote
|
---|
1244 | from shutil import rmtree
|
---|
1245 | try:
|
---|
1246 | from subprocess import check_output
|
---|
1247 | except 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
|
---|
1263 | from sys import exit, version_info
|
---|
1264 | from tempfile import mkdtemp
|
---|
1265 | try:
|
---|
1266 | from urllib2 import build_opener, HTTPHandler, HTTPSHandler
|
---|
1267 | except ImportError:
|
---|
1268 | from urllib.request import build_opener, HTTPHandler, HTTPSHandler
|
---|
1269 | try:
|
---|
1270 | from urlparse import urlparse
|
---|
1271 | except ImportError:
|
---|
1272 | from urllib.parse import urlparse # 3.4
|
---|
1273 |
|
---|
1274 |
|
---|
1275 | __version__ = 1, 5, 1
|
---|
1276 | PIP_VERSION = '9.0.1'
|
---|
1277 | DEFAULT_INDEX_BASE = 'https://pypi.python.org'
|
---|
1278 |
|
---|
1279 |
|
---|
1280 | # wheel has a conditional dependency on argparse:
|
---|
1281 | maybe_argparse = (
|
---|
1282 | [('18/dd/e617cfc3f6210ae183374cd9f6a26b20514bbb5a792af97949c5aacddf0f/'
|
---|
1283 | 'argparse-1.4.0.tar.gz',
|
---|
1284 | '62b089a55be1d8949cd2bc7e0df0bddb9e028faefc8c32038cc84862aefdd6e4')]
|
---|
1285 | if version_info < (2, 7, 0) else [])
|
---|
1286 |
|
---|
1287 |
|
---|
1288 | PACKAGES = 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 |
|
---|
1303 | class 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 |
|
---|
1311 | def 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 |
|
---|
1349 | def 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 |
|
---|
1367 | def 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 |
|
---|
1398 | if __name__ == '__main__':
|
---|
1399 | exit(main())
|
---|
1400 |
|
---|
1401 | UNLIKELY_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 |
|
---|
1459 | else
|
---|
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 |
|
---|
1497 | On failure, return non-zero.
|
---|
1498 |
|
---|
1499 | """
|
---|
1500 |
|
---|
1501 | from __future__ import print_function, unicode_literals
|
---|
1502 |
|
---|
1503 | from distutils.version import LooseVersion
|
---|
1504 | from json import loads
|
---|
1505 | from os import devnull, environ
|
---|
1506 | from os.path import dirname, join
|
---|
1507 | import re
|
---|
1508 | import ssl
|
---|
1509 | from subprocess import check_call, CalledProcessError
|
---|
1510 | from sys import argv, exit
|
---|
1511 | try:
|
---|
1512 | from urllib2 import build_opener, HTTPHandler, HTTPSHandler
|
---|
1513 | from urllib2 import HTTPError, URLError
|
---|
1514 | except ImportError:
|
---|
1515 | from urllib.request import build_opener, HTTPHandler, HTTPSHandler
|
---|
1516 | from urllib.error import HTTPError, URLError
|
---|
1517 |
|
---|
1518 | PUBLIC_KEY = environ.get('LE_AUTO_PUBLIC_KEY', """-----BEGIN PUBLIC KEY-----
|
---|
1519 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6MR8W/galdxnpGqBsYbq
|
---|
1520 | OzQb2eyW15YFjDDEMI0ZOzt8f504obNs920lDnpPD2/KqgsfjOgw2K7xWDJIj/18
|
---|
1521 | xUvWPk3LDkrnokNiRkA3KOx3W6fHycKL+zID7zy+xZYBuh2fLyQtWV1VGQ45iNRp
|
---|
1522 | 9+Zo7rH86cdfgkdnWTlNSHyTLW9NbXvyv/E12bppPcEvgCTAQXgnDVJ0/sqmeiij
|
---|
1523 | n9tTFh03aM+R2V/21h8aTraAS24qiPCz6gkmYGC8yr6mglcnNoYbsLNYZ69zF1XH
|
---|
1524 | cXPduCPdPdfLlzVlKK1/U7hkA28eG3BIAMh6uJYBRJTpiGgaGdPd7YekUB8S6cy+
|
---|
1525 | CQIDAQAB
|
---|
1526 | -----END PUBLIC KEY-----
|
---|
1527 | """)
|
---|
1528 |
|
---|
1529 | class ExpectedError(Exception):
|
---|
1530 | """A novice-readable exception that also carries the original exception for
|
---|
1531 | debugging"""
|
---|
1532 |
|
---|
1533 |
|
---|
1534 | class 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 |
|
---|
1562 | def 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 |
|
---|
1568 | def 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 |
|
---|
1582 | def 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 |
|
---|
1610 | def 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 |
|
---|
1618 | def 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 |
|
---|
1634 | if __name__ == '__main__':
|
---|
1635 | exit(main())
|
---|
1636 |
|
---|
1637 | UNLIKELY_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 "$@"
|
---|
1668 | fi
|
---|