Compare commits

...

36 Commits

Author SHA1 Message Date
Brad Warren
fcb85becb9 only test apache 2020-06-04 10:15:09 -07:00
Alex Zorin
ca1573ea32 Merge remote-tracking branch 'upstream/master' into apache_static_ssl_module 2020-06-04 08:59:33 +10:00
ohemorange
8c8d3fab91 Merge pull request #8040 from certbot/candidate-1.5.0
Release 1.5.0
2020-06-02 12:19:39 -07:00
Brad Warren
baf69d210b Bump version to 1.6.0 2020-06-02 10:32:41 -07:00
Brad Warren
beea2d2208 Add contents to certbot/CHANGELOG.md for next version 2020-06-02 10:32:40 -07:00
Brad Warren
4938273e0f Release 1.5.0 2020-06-02 10:32:38 -07:00
Brad Warren
466b4fbf71 Update changelog for 1.5.0 release 2020-06-02 10:12:33 -07:00
Brad Warren
95ae5f69f5 Make rebuild_dependencies.py executable (#8039) 2020-06-02 19:11:47 +02:00
ohemorange
2acc1dcc89 Fix TLS-ALPN tests with newer versions of OpenSSL (#8026)
Fixes #7988. As described there, the steps involved are:

1. Update our tests so they fail due to this problem.
2. Update the keys used in the tests so they pass with the new changes.

For 1, see a [failing travis run](https://travis-ci.com/github/certbot/certbot/jobs/340710511) with the included change. And for the full output to confirm that this is what is failing, see a [run on debian 10](https://github.com/certbot/certbot/files/4692350/debian_run_log.txt).

This PR adds `rsa4096_key.pem` and `rsa4096_cert.pem`, updates the `TLS-ALPN` test to use those keys in place of the 1024-bit versions, and fixes the README in that `testdata` folder with correct instructions to generate these files.

* export PIP_NO_BINARY in pip install subshell in test_sdists.sh

* set environment variable on the line that installs most packages

* Generate 4096-bit rsa key and cert, and fix README instructions to do so.

* Update TLS_ALPN test to use 4096-bit key instead of 1024-bit key.

* Update changelog

* Older versions of Python have an error when both VIRTUAL_NO_DOWNLOAD and PIP_NO_BINARY are set, so only apply the latter at the install phase.

* Add enum34 constraint manually, since rebuild_dependencies.py seems to be broken.

* only delete key if it exists

* Check OpenSSL version before trying to set PIP_NO_BINARY

* Add comment explaining why we only set PIP_NO_BINARY at the install step
2020-06-01 15:18:38 -07:00
Brad Warren
fa55b468c8 Revert "Upgrade pinned certbot dependencies (#8012)" (#8035)
This reverts commit 6b97ac3344.
2020-06-01 20:17:26 +02:00
Brad Warren
cd27dcc32c Add the content interface to Certbot (#8009)
* Add the content interface to Certbot

This commit contains a subset of the changes from 7076a55fd82116d068e2aca7239209b7203917d2.

* Normalise slot parameters

(cherry picked from commit 810941979bcf609c1e0be18e9263abf046b90e82)

Co-authored-by: Robie Basak <robie.basak@canonical.com>
2020-05-27 13:59:08 -07:00
Adrien Ferrand
6b97ac3344 Upgrade pinned certbot dependencies (#8012)
* Upgrade certbot dependencies

* Rebuild letsencrypt-auto
2020-05-26 15:19:10 -07:00
ohemorange
332def46da Require explicit confirmation of snap plugin permissions before connecting (#8013)
Fixes #7667.

Implements the plan described in #7667.

Here's a terminal log showing that it does so:

```
# sudo snap connect certbot:plugin certbot-dns-dnsimple
error: cannot perform the following tasks:
- Run hook prepare-plug-plugin of snap "certbot" (run hook "prepare-plug-plugin": 
-----
Only connect this interface if you trust the plugin author to have root on the system
Run `snap set certbot trust-plugin-with-root=ok` to acknowledge this and then run this command again to perform the connection
-----)
# snap set certbot trust-plugin-with-root=ok
# sudo snap connect certbot:plugin certbot-dns-dnsimple
# sudo snap disconnect certbot:plugin certbot-dns-dnsimple:certbot
# sudo snap connect certbot:plugin certbot-dns-dnsimple
error: cannot perform the following tasks:
- Run hook prepare-plug-plugin of snap "certbot" (run hook "prepare-plug-plugin": 
-----
Only connect this interface if you trust the plugin author to have root on the system
Run `snap set certbot trust-plugin-with-root=ok` to acknowledge this and then run this command again to perform the connection
-----)
```

* Add plugin connection hook to accept root trust

* snapctl requires a configure hook to set options

* Add sh notice

* Update changelog
2020-05-26 12:02:33 -07:00
Adrien Ferrand
b42e24178a Consistent directory mode apply when makedirs is called (#8010)
Fixes #7993 

This PR uses `os.umask()` during `certbot.compat.filesystem.makedirs()` call to ensure that all directories, and not only the leaf one, have the provided `mode` when created. This ensures a safe and consistent behavior independently from the Python version, since the behavior of `os.makedirs` changed on that matter with Python 3.7.

* Implement logic to apply the same permission on all dirs created by makedirs

* Add a test

* Add comment

* Update certbot/certbot/compat/filesystem.py

Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
2020-05-21 15:29:06 -07:00
Alex Zorin
8af28d83a6 apache: handle statically linked mod_ssl
In #7771, the Apache configurator gained the ability to identify what
version of OpenSSL Apache's ssl_module is linked against. However, the
detection was only functional if the module was built as a DSO (which is
almost always the case).

This commit covers the case where the ssl_module is statically linked
within the Apache binary. It requires the user to specify the path to
the binary (with --apache-bin) and emits a warning if static linking is
detected but no path has been provided.
2020-05-20 21:00:53 +10:00
ohemorange
3ea5170647 Error out earlier in apache installer when mod_ssl is not available (#7984)
* Error out in apache installer when mod_ssl is not available

* Update to MisconfigurationError and add/fix tests

* Remove error cases we no longer hit and associated test

* mock out function to have consistent error across machines

* improve changelog message

* only check key in modules list, not value
2020-05-19 15:34:21 -07:00
schoen
0b53c0d476 Merge pull request #7952 from ntkme/allow-empty-existing-dir
Allow existing but empty archive and live dir to be used when creating new lineage
2020-05-19 15:25:32 -07:00
Brad Warren
4eb9a71a4c remove quay cruft (#8003)
Our README still has links to our old quay.io builds which we shutdown a while ago. See #4343. This PR simply removes the old stray links.
2020-05-19 14:29:28 -07:00
Brad Warren
96e003d1a3 mention python3-venv in docs (#8006)
The error message from `python3 -m venv` when you don't have `python3-venv` installed is pretty good, but lets skip the failure and make sure it is installed the first time.
2020-05-19 14:28:41 -07:00
schoen
7a7c6737cc Merge pull request #8000 from certbot/make-exit-message-red
Print cause of exit in red text
2020-05-18 17:13:03 -07:00
Brad Warren
0e59c6ba1b handle more cases 2020-05-18 10:17:32 -07:00
Brad Warren
d230dcafeb Print cause of exit in red text. 2020-05-18 09:31:15 -07:00
alexzorin
bcf33c6659 ocsp: add support for public key hash ResponderIDs (#7989)
For both cases where the the response is signed by the issuer, or by a
delegated OCSP signer.

Resolves #7986
2020-05-13 15:55:35 -07:00
Brad Warren
71e3d82e47 Remove passthrough because its no longer needed (#7956) 2020-05-06 14:28:15 -07:00
Adrien Ferrand
bb6a660b21 Platform-agnostic method to copy owner and permissions between files (#7968)
Related to #7649 since @joohoi needs a method to copy owner and permissions together from a source file to a destination file.

This PR creates the method `copy_ownership_and_mode()` in `certbot.compat.filesystem` module to achieve this goal. Its behavior is consistent across Linux and Windows in respect to the security model that have been defined for Certbot on Windows.

The method behaves globally the same than `copy_ownership_and_apply_mode`, but this time the permissions are extracted from the source file. For Windows it means that the DACL is copied from the source to the destination with the same content.

* Create copy_ownership_and_mode to copy both owner and mode from src to dst

* Update certbot/tests/compat/filesystem_test.py

Co-authored-by: Brad Warren <bmw@users.noreply.github.com>

* Fix docstring

Co-authored-by: Brad Warren <bmw@users.noreply.github.com>
2020-05-06 12:33:50 -07:00
Brad Warren
c35054fd11 Merge pull request #7974 from certbot/candidate-1.4.0
Release 1.4.0
2020-05-05 17:06:31 -07:00
Erica Portnoy
b224b49986 Bump version to 1.5.0 2020-05-05 13:44:23 -07:00
Erica Portnoy
1a72cdecf2 Add contents to certbot/CHANGELOG.md for next version 2020-05-05 13:44:23 -07:00
Erica Portnoy
5586ae071a Release 1.4.0 2020-05-05 13:44:21 -07:00
Erica Portnoy
ca60ad52b9 Update changelog for 1.4.0 release 2020-05-05 12:37:33 -07:00
Brad Warren
9154e7965f drop min certbot coverage (#7972)
`tox -e cover` fails for me on macOS. This is due to the differences in the code that is run when on Linux vs. other platforms in `certbot.util` and its tests. Diffing my local coverage with Travis, the only difference in lines missing test coverage is:
```
$ diff travis.txt local.txt
< certbot/certbot/util.py                                        238     24    90%   132-134, 210, 275-281, 318, 330-340, 347, 381-382
> certbot/certbot/util.py                                        239     34    86%   30, 132-134, 210, 275-281, 301, 305, 316-318, 330-340, 347, 367-373, 381-382
< certbot/tests/util_test.py                                     392      0   100%
> certbot/tests/util_test.py                                     375     26    93%   483-487, 492-502, 507-514, 548-550, 555-557
```
I think tests on `master` should not be failing locally for people.

While there would be other ways to fix this by adding `# pragma: no cover` lines or writing mocked out tests for other platforms, I personally just think dropping the minimum coverage one percentage point is fine at least for now.
2020-05-05 09:38:20 -07:00
Brad Warren
ac2d691ade Add warning about ignoring our own warnings (#7971)
Coming out of the conversation at #7863 in the linked Google Doc, we should always have at least 1 release between updating one of our plugins to stop using a deprecated acme/certbot API and removing it from acme/certbot. Doing this gives the plugin changes time to propagate rather than potentially having the plugin break because Certbot was updated before the plugin had made the necessary changes.

This comment here should help ensure this.

* Add pytest warnings warning.

* clarify comment
2020-05-04 16:54:09 -07:00
schoen
5536c91223 Merge pull request #7938 from taixx046/1618-awkward-language-during-email-problems
Fixed #1618 awkward language during email problems
2020-04-27 18:33:07 -07:00
なつき
db6de76b11 Allow existing but empty archive and live dir 2020-04-25 01:47:30 -07:00
taixx046
e5cde2c598 updated changelog.md 2020-04-23 15:29:38 -05:00
taixx046
84b6c3cebb reorganized error message when a user entered an invalid email address 2020-04-23 15:20:32 -05:00
64 changed files with 532 additions and 454 deletions

View File

@@ -41,240 +41,11 @@ extended-test-suite: &extended-test-suite
matrix:
include:
# Main test suite
- stage: "Test"
python: "2.7"
env: ACME_SERVER=pebble TOXENV=integration
<<: *not-on-master
# As documented at
# https://docs.travis-ci.com/user/build-stages/#how-to-define-build-stages,
# the previous stage will be automatically applied to all subsequent jobs
# until a new stage is defined.
# This job is always executed, including on master
- python: "3.8"
env: TOXENV=py38-cover FYI="py38 tests + code coverage"
- python: "3.7"
env: TOXENV=lint
<<: *not-on-master
- python: "3.5"
env: TOXENV=mypy
<<: *not-on-master
- python: "2.7"
# Ubuntu Trusty or older must be used because the oldest version of
# cryptography we support cannot be compiled against the version of
# OpenSSL in Xenial or newer.
dist: trusty
env: TOXENV='py27-{acme,apache,apache-v2,certbot,dns,nginx}-oldest'
<<: *not-on-master
- python: "2.7"
env: TOXENV=py27
<<: *not-on-master
- python: "3.5"
env: TOXENV=py35
<<: *not-on-master
- sudo: required
env: TOXENV=apache_compat
services: docker
addons:
<<: *not-on-master
- sudo: required
env: TOXENV=le_auto_xenial
services: docker
<<: *not-on-master
- python: "2.7"
env: TOXENV=apacheconftest-with-pebble
<<: *not-on-master
- python: "2.7"
env: TOXENV=nginxroundtrip
<<: *not-on-master
# Extended test suite on cron jobs and pushes to tested branches other than master
- sudo: required
env: TOXENV=nginx_compat
services: docker
addons:
<<: *extended-test-suite
- python: "3.7"
env:
- TOXENV=travis-test-farm-apache2
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "3.7"
env:
- TOXENV=travis-test-farm-leauto-upgrades
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
git:
depth: false # This is needed to have the history to checkout old versions of certbot-auto.
<<: *extended-test-suite
- python: "3.7"
env:
- TOXENV=travis-test-farm-certonly-standalone
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "3.7"
env:
- TOXENV=travis-test-farm-sdists
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "3.7"
env: TOXENV=py37 CERTBOT_NO_PIN=1
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v2 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration-certbot-oldest
# Ubuntu Trusty or older must be used because the oldest version of
# cryptography we support cannot be compiled against the version of
# OpenSSL in Xenial or newer.
dist: trusty
sudo: required
services: docker
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v2 TOXENV=integration-certbot-oldest
# Ubuntu Trusty or older must be used because the oldest version of
# cryptography we support cannot be compiled against the version of
# OpenSSL in Xenial or newer.
dist: trusty
sudo: required
services: docker
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration-nginx-oldest
# Ubuntu Trusty or older must be used because the oldest version of
# cryptography we support cannot be compiled against the version of
# OpenSSL in Xenial or newer.
dist: trusty
sudo: required
services: docker
<<: *extended-test-suite
- python: "2.7"
env: ACME_SERVER=boulder-v2 TOXENV=integration-nginx-oldest
# Ubuntu Trusty or older must be used because the oldest version of
# cryptography we support cannot be compiled against the version of
# OpenSSL in Xenial or newer.
dist: trusty
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.6"
env: TOXENV=py36
<<: *extended-test-suite
- python: "3.7"
env: TOXENV=py37
<<: *extended-test-suite
- python: "3.5"
env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.5"
env: ACME_SERVER=boulder-v2 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.6"
env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.6"
env: ACME_SERVER=boulder-v2 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.7"
env: ACME_SERVER=boulder-v2 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.8"
env: ACME_SERVER=boulder-v1 TOXENV=integration
<<: *extended-test-suite
- python: "3.8"
env: ACME_SERVER=boulder-v2 TOXENV=integration
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_jessie
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_centos6
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_oraclelinux6
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=docker_dev
services: docker
addons:
apt:
packages: # don't install nginx and apache
- libaugeas0
<<: *extended-test-suite
- stage: "Snap"
sudo: required
env: SNAP=true TOXENV=integration-external,apacheconftest-external-with-pebble
addons:
apt:
packages:
- nginx-light
snaps:
- name: snapcraft
channel: stable
confinement: classic
- name: lxd
channel: stable
git:
# By default, Travis clones the repo to a depth of 50 commits which can
# break the ability to use `git describe` to set the version of the
# snap. This setting removes the --depth flag from git commands solving
# this problem. See
# https://docs.travis-ci.com/user/customizing-the-build#git-clone-depth
# for more info.
depth: false
deploy:
# This section relies on credentials stored in a SNAP_TOKEN environment
# variable in Travis. See
# https://docs.travis-ci.com/user/deployment/snaps/ for more info.
# This credential has a maximum lifetime of 1 year and the current
# credential will expire on 4/22/2021. The value of SNAP_TOKEN will
# need to be updated to use a new credential before then to prevent
# automated deploys from breaking. Remembering to do this is also
# tracked by https://github.com/certbot/certbot/issues/7931.
'on':
# Deploy on release tags or nightly runs from any branch. We only try
# to deploy from the certbot/certbot repo to prevent errors if forks
# of this repo try to run tests.
all_branches: true
condition: -n $TRAVIS_TAG || $TRAVIS_EVENT_TYPE = cron
repo: certbot/certbot
provider: snap
snap: certbot_*.snap
channel: edge
# skip_cleanup is needed to prevent Travis from deleting the snaps we
# just built and tested. See
# https://docs.travis-ci.com/user/deployment#uploading-files-and-skip_cleanup.
skip_cleanup: true
<<: *extended-test-suite
# container-based infrastructure
sudo: false

View File

@@ -237,6 +237,7 @@ Authors
* [Stefan Weil](https://github.com/stweil)
* [Steve Desmond](https://github.com/stevedesmond-ca)
* [sydneyli](https://github.com/sydneyli)
* [taixx046](https://github.com/taixx046)
* [Tan Jay Jun](https://github.com/jayjun)
* [Tapple Gao](https://github.com/tapple)
* [Telepenin Nikolay](https://github.com/telepenin)

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -122,8 +122,8 @@ class TLSALPN01ServerTest(unittest.TestCase):
)}
# Use different certificate for challenge.
self.challenge_certs = {b'localhost': (
test_util.load_pyopenssl_private_key('rsa1024_key.pem'),
test_util.load_cert('rsa1024_cert.pem'),
test_util.load_pyopenssl_private_key('rsa4096_key.pem'),
test_util.load_cert('rsa4096_cert.pem'),
)}
from acme.standalone import TLSALPN01Server
self.server = TLSALPN01Server(("localhost", 0), certs=self.certs,

View File

@@ -4,7 +4,7 @@ to use appropriate extension for vector filenames: .pem for PEM and
The following command has been used to generate test keys:
for x in 256 512 1024 2048; do openssl genrsa -out rsa${k}_key.pem $k; done
for k in 256 512 1024 2048 4096; do openssl genrsa -out rsa${k}_key.pem $k; done
and for the CSR:

30
acme/tests/testdata/rsa4096_cert.pem vendored Normal file
View File

@@ -0,0 +1,30 @@
-----BEGIN CERTIFICATE-----
MIIFDTCCAvWgAwIBAgIUImqDrP53V69vFROsjP/gL0YtoA4wDQYJKoZIhvcNAQEL
BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjAwNTI3MjMyNDE0WhcNMjAw
NjI2MjMyNDE0WjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBANY9LKLk9Dxn0MUMQFHwBoTN4ehDSWBws2KcytpF
mc8m9Mfk1wmb4fQSKYtK3wIFMfIyo9HQu0nKqMkkUw52o3ZXyOv+oWwF5qNy2BKu
lh5OMSkaZ0o13zoPpW42e+IUnyxvg70+0urD+sUue4cyTHh/nBIUjrM/05ZJ/ac8
HR0RK3H41YoqBjq69JjMZczZZhbNFit3s6p0R1TbVAgc3ckqbtX5BDyQMQQCP4Ed
m4DgbAFVqdcPUCC5W3F3fmuQiPKHiADzONZnXpy6lUvLDWqcd6loKp+nKHM6OkXX
8hmD7pE1PYMQo4hqOfhBR2IgMjAShwd5qUFjl1m2oo0Qm3PFXOk6i2ZQdS6AA/yd
B5/mX0RnM2oIdFZPb6UZFSmtEgs9sTzn+hMUyNSZQRE54px1ur1xws2R+vbsCyM5
+KoFVxDjVjU9TlZx3GvDvnqz/tbHjji6l8VHZYOBMBUXbKHu2U6pJFZ5Zp7k68/z
a3Fb9Pjtn3iRkXEyC0N5kLgqO4QTlExnxebV8aMvQpWd/qefnMn9qPYIZPEXSQAR
mEBIahkcACb60s+acG0WFFluwBPtBqEr8Q67XlSF0Ibf4iBiRzpPobhlWta1nrFg
4IWHMSoZ0PE75bhIGBEkhrpcXQCAxXmAfxfjKDH7jdJ1fRdnZ/9+OzwYGVX5GH/l
0QDtAgMBAAGjUzBRMB0GA1UdDgQWBBQh3xiz/o1nEU2ySylZ9gxCXvIPGzAfBgNV
HSMEGDAWgBQh3xiz/o1nEU2ySylZ9gxCXvIPGzAPBgNVHRMBAf8EBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4ICAQAELoXz31oR9pdAwidlv9ZBOKiC7KBWy8VMqXNVkfTn
bVRxAUex7zleLFIOkWnqadsMesU9sIwrbLzBcZ8Q/vBY+z2xOPdXcgcAoAmdKWoq
YBQNiqng9r54sqlzB/77QZCf5fdktESe7NTxhCifgx5SAWq7IUQs/lm3tnMUSAfE
5ctuN6M+w8K54y3WDprcfMHpnc3ZHeSPhVQApHM0h/bDvXq0bRS7kmq27Hb153Qm
nH3TwYB5pPSWW38NbUc+s/a7mItO7S8ly8yGbA0j9c/IbN5lM+OCdk06asz3+c8E
uo8nuCBoYO5+6AqC2N7WJ3Tdr/pFA8jTbd6VNVlgCWTIR8ZosL5Fgkfv+4fUBrHt
zdVUqMUzvga5rvZnwnJ5Qfu/drHeAAo9MTNFQNe2QgDlYfWBh5GweolgmFSwrpkY
v/5wLtIyv/ASHKswybbqMIlpttcLTXjx5yuh8swttT6Wh+FQqqQ32KSRB3StiwyK
oH0ZhrwYHiFYNlPxecGX6XUta6rFtTlEdkBGSnXzgiTzL2l+Nc0as0V5B9RninZG
qJ+VOChSQ0OFvg1riSXv7tMvbLdGQnxwTRL3t6BMS8I4LA2m3ZfWUcuXT783ODTH
16f1Q1AgXd2csstTWO9cv+N/0fpX31nqrm6+CrGduSr2u4HjYYnlLIUhmdTvK3fX
Fg==
-----END CERTIFICATE-----

51
acme/tests/testdata/rsa4096_key.pem vendored Normal file
View File

@@ -0,0 +1,51 @@
-----BEGIN RSA PRIVATE KEY-----
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
-----END RSA PRIVATE KEY-----

View File

@@ -115,6 +115,7 @@ class ApacheConfigurator(common.Installer):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/apache2",
bin=None
)
def option(self, key):
@@ -145,7 +146,7 @@ class ApacheConfigurator(common.Installer):
"""
opts = ["enmod", "dismod", "le_vhost_ext", "server_root", "vhost_root",
"logs_root", "challenge_location", "handle_modules", "handle_sites",
"ctl"]
"ctl", "bin"]
for o in opts:
# Config options use dashes instead of underscores
if self.conf(o.replace("_", "-")) is not None:
@@ -194,6 +195,8 @@ class ApacheConfigurator(common.Installer):
"(Only Ubuntu/Debian currently)")
add("ctl", default=DEFAULTS["ctl"],
help="Full path to Apache control script")
add("bin", default=DEFAULTS["bin"],
help="Full path to apache2/httpd binary")
def __init__(self, *args, **kwargs):
"""Initialize an Apache Configurator.
@@ -269,18 +272,25 @@ class ApacheConfigurator(common.Installer):
"""
if self._openssl_version:
return self._openssl_version
# Step 1. Check for LoadModule directive
# Step 1. Determine the location of ssl_module
try:
ssl_module_location = self.parser.modules['ssl_module']
except KeyError:
if warn_on_no_mod_ssl:
logger.warning("Could not find ssl_module; not disabling session tickets.")
return None
if not ssl_module_location:
logger.warning("Could not find ssl_module; not disabling session tickets.")
return None
ssl_module_location = self.parser.standard_path_from_server_root(ssl_module_location)
# Step 2. Grep in the .so for openssl version
if ssl_module_location:
# Possibility A: ssl_module is a DSO
ssl_module_location = self.parser.standard_path_from_server_root(ssl_module_location)
else:
# Possibility B: ssl_module is statically linked into Apache
if self.option("bin"):
ssl_module_location = self.option("bin")
else:
logger.warning("ssl_module is statically linked but --apache-bin is "
"missing; not disabling session tickets.")
return None
# Step 2. Grep in the binary for openssl version
contents = self._open_module_file(ssl_module_location)
if not contents:
logger.warning("Unable to read ssl_module file; not disabling session tickets.")
@@ -595,6 +605,11 @@ class ApacheConfigurator(common.Installer):
# cert_key... can all be parsed appropriately
self.prepare_server_https("443")
# If we haven't managed to enable mod_ssl by this point, error out
if "ssl_module" not in self.parser.modules:
raise errors.MisconfigurationError("Could not find ssl_module; "
"not installing certificate.")
# Add directives and remove duplicates
self._add_dummy_ssl_directives(vhost.path)
self._clean_vhost(vhost)
@@ -609,21 +624,6 @@ class ApacheConfigurator(common.Installer):
path["chain_path"] = self.parser.find_dir(
"SSLCertificateChainFile", None, vhost.path)
# Handle errors when certificate/key directives cannot be found
if not path["cert_path"]:
logger.warning(
"Cannot find an SSLCertificateFile directive in %s. "
"VirtualHost was not modified", vhost.path)
raise errors.PluginError(
"Unable to find an SSLCertificateFile directive")
elif not path["cert_key"]:
logger.warning(
"Cannot find an SSLCertificateKeyFile directive for "
"certificate in %s. VirtualHost was not modified", vhost.path)
raise errors.PluginError(
"Unable to find an SSLCertificateKeyFile directive for "
"certificate")
logger.info("Deploying Certificate to VirtualHost %s", vhost.filep)
if self.version < (2, 4, 8) or (chain_path and not fullchain_path):

View File

@@ -24,4 +24,5 @@ class ArchConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/httpd/conf",
bin=None,
)

View File

@@ -35,6 +35,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/httpd/conf.d",
bin=None,
)
def config_test(self):

View File

@@ -24,4 +24,5 @@ class DarwinConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/apache2/other",
bin=None,
)

View File

@@ -33,6 +33,7 @@ class DebianConfigurator(configurator.ApacheConfigurator):
handle_modules=True,
handle_sites=True,
challenge_location="/etc/apache2",
bin=None,
)
def enable_site(self, vhost):

View File

@@ -29,6 +29,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/httpd/conf.d",
bin=None,
)
def config_test(self):

View File

@@ -27,6 +27,7 @@ class GentooConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
bin=None,
)
def _prepare_options(self):

View File

@@ -24,4 +24,5 @@ class OpenSUSEConfigurator(configurator.ApacheConfigurator):
handle_modules=False,
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
bin=None,
)

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -455,41 +455,6 @@ class MultipleVhostsTest(util.ApacheTest):
"SSLCertificateChainFile", "two/cert_chain.pem",
self.vh_truth[1].path))
def test_deploy_cert_invalid_vhost(self):
"""For test cases where the `ApacheConfigurator` class' `_deploy_cert`
method is called with an invalid vhost parameter. Currently this tests
that a PluginError is appropriately raised when important directives
are missing in an SSL module."""
self.config.parser.modules["ssl_module"] = None
self.config.parser.modules["mod_ssl.c"] = None
self.config.parser.modules["socache_shmcb_module"] = None
def side_effect(*args):
"""Mocks case where an SSLCertificateFile directive can be found
but an SSLCertificateKeyFile directive is missing."""
if "SSLCertificateFile" in args:
return ["example/cert.pem"]
return []
mock_find_dir = mock.MagicMock(return_value=[])
mock_find_dir.side_effect = side_effect
self.config.parser.find_dir = mock_find_dir
# Get the default 443 vhost
self.config.assoc["random.demo"] = self.vh_truth[1]
self.assertRaises(
errors.PluginError, self.config.deploy_cert, "random.demo",
"example/cert.pem", "example/key.pem", "example/cert_chain.pem")
# Remove side_effect to mock case where both SSLCertificateFile
# and SSLCertificateKeyFile directives are missing
self.config.parser.find_dir.side_effect = None
self.assertRaises(
errors.PluginError, self.config.deploy_cert, "random.demo",
"example/cert.pem", "example/key.pem", "example/cert_chain.pem")
def test_is_name_vhost(self):
addr = obj.Addr.fromstring("*:80")
self.assertTrue(self.config.is_name_vhost(addr))
@@ -1349,6 +1314,16 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertTrue(mock_add.called)
shutil.rmtree(tmp_path)
def test_deploy_cert_no_mod_ssl(self):
# Create
ssl_vhost = self.config.make_vhost_ssl(self.vh_truth[0])
self.config.parser.modules["socache_shmcb_module"] = None
self.config.prepare_server_https = mock.Mock()
self.assertRaises(errors.MisconfigurationError, self.config.deploy_cert,
"encryption-example.demo", "example/cert.pem", "example/key.pem",
"example/cert_chain.pem", "example/fullchain.pem")
@mock.patch("certbot_apache._internal.parser.ApacheParser.parsed_in_original")
def test_choose_vhost_and_servername_addition_parsed(self, mock_parsed):
ret_vh = self.vh_truth[8]
@@ -1797,12 +1772,22 @@ class InstallSslOptionsConfTest(util.ApacheTest):
AH02556: "SSLOpenSSLConfCmd %s %s" applied to %s
OpenSSL 1.0.2g 1 Mar 2016
"""
# ssl_module as a DSO
self.config.parser.modules['ssl_module'] = '/fake/path'
with mock.patch("certbot_apache._internal.configurator."
"ApacheConfigurator._open_module_file") as mock_omf:
mock_omf.return_value = some_string_contents
self.assertEqual(self.config.openssl_version(), "1.0.2g")
# ssl_module statically linked
self.config._openssl_version = None
self.config.parser.modules['ssl_module'] = None
self.config.options['bin'] = '/fake/path/to/httpd'
with mock.patch("certbot_apache._internal.configurator."
"ApacheConfigurator._open_module_file") as mock_omf:
mock_omf.return_value = some_string_contents
self.assertEqual(self.config.openssl_version(), "1.0.2g")
def test_current_version(self):
self.config.version = (2, 4, 10)
self.config._openssl_version = '1.0.2m'
@@ -1824,12 +1809,21 @@ class InstallSslOptionsConfTest(util.ApacheTest):
self.assertEqual(self.config.openssl_version(), None)
self.assertTrue("Could not find ssl_module" in mock_log.call_args[0][0])
# When no ssl_module is present at all
self.config._openssl_version = None
self.config.parser.modules['ssl_module'] = None
self.assertTrue("ssl_module" not in self.config.parser.modules)
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
self.assertEqual(self.config.openssl_version(), None)
self.assertTrue("Could not find ssl_module" in mock_log.call_args[0][0])
# When ssl_module is statically linked but --apache-bin not provided
self.config._openssl_version = None
self.config.options['bin'] = None
self.config.parser.modules['ssl_module'] = None
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
self.assertEqual(self.config.openssl_version(), None)
self.assertTrue("ssl_module is statically linked but" in mock_log.call_args[0][0])
self.config.parser.modules['ssl_module'] = "/fake/path"
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
# Check that correct logger.warning was printed

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="1.3.0"
LE_AUTO_VERSION="1.5.0"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -910,20 +910,11 @@ elif [ -f /etc/manjaro-release ]; then
}
BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION"
elif [ -f /etc/gentoo-release ]; then
Bootstrap() {
DeprecationBootstrap "Gentoo" BootstrapGentooCommon
}
BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION"
DEPRECATED_OS=1
elif uname | grep -iq FreeBSD ; then
Bootstrap() {
DeprecationBootstrap "FreeBSD" BootstrapFreeBsd
}
BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION"
DEPRECATED_OS=1
elif uname | grep -iq Darwin ; then
Bootstrap() {
DeprecationBootstrap "macOS" BootstrapMac
}
BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION"
DEPRECATED_OS=1
elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
Bootstrap() {
ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
@@ -1343,7 +1334,9 @@ cryptography==2.8 \
distro==1.4.0 \
--hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \
--hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4
enum34==1.1.6 \
# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid
# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456.
enum34==1.1.6 ; python_version < '3.4' \
--hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \
--hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \
--hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \
@@ -1540,18 +1533,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==1.3.0 \
--hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \
--hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8
acme==1.3.0 \
--hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \
--hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d
certbot-apache==1.3.0 \
--hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \
--hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52
certbot-nginx==1.3.0 \
--hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \
--hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b
certbot==1.5.0 \
--hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \
--hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf
acme==1.5.0 \
--hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \
--hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0
certbot-apache==1.5.0 \
--hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \
--hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764
certbot-nginx==1.5.0 \
--hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \
--hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -5,7 +5,7 @@ from setuptools import __version__ as setuptools_version
from setuptools import find_packages
from setuptools import setup
version = '1.4.0.dev0'
version = '1.6.0.dev0'
install_requires = [
'certbot',

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -7,7 +7,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.

View File

@@ -6,7 +6,7 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

View File

@@ -1,3 +1,3 @@
# Remember to update setup.py to match the package versions below.
-e acme[dev]
-e certbot[dev]
acme[dev]==1.4.0
certbot[dev]==1.4.0

View File

@@ -6,13 +6,13 @@ from setuptools import find_packages
from setuptools import setup
from setuptools.command.test import test as TestCommand
version = '1.4.0.dev0'
version = '1.6.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.
install_requires = [
'acme>=1.4.0.dev0',
'certbot>=1.4.0.dev0',
'acme>=1.4.0',
'certbot>=1.4.0',
'PyOpenSSL',
'pyparsing>=1.5.5', # Python3 support
'setuptools',

View File

@@ -2,7 +2,41 @@
Certbot adheres to [Semantic Versioning](https://semver.org/).
## 1.4.0 - master
## 1.6.0 - master
### Added
*
### Changed
* Allow session tickets to be disabled in Apache when mod_ssl is statically linked.
### Fixed
*
More details about these changes can be found on our GitHub repo.
## 1.5.0 - 2020-06-02
### Added
* Require explicit confirmation of snap plugin permissions before connecting.
### Changed
* Improved error message in apache installer when mod_ssl is not available.
### Fixed
* Add support for OCSP responses which use a public key hash ResponderID, fixing
interoperability with Sectigo CAs.
* Fix TLS-ALPN test that fails when run with newer versions of OpenSSL.
More details about these changes can be found on our GitHub repo.
## 1.4.0 - 2020-05-05
### Added
@@ -20,9 +54,11 @@ Certbot adheres to [Semantic Versioning](https://semver.org/).
### Changed
* Reorganized error message when a user entered an invalid email address.
* Stop asking interactively if the user would like to add a redirect.
* `mock` dependency is now conditional on Python 2 in all of our packages.
* Deprecate certbot-auto on Gentoo, macOS, and FreeBSD.
* Allow existing but empty archive and live dir to be used when creating new lineage.
### Fixed

View File

@@ -71,16 +71,12 @@ ACME spec: http://ietf-wg-acme.github.io/acme/
ACME working area in github: https://github.com/ietf-wg-acme/acme
|build-status| |container|
|build-status|
.. |build-status| image:: https://travis-ci.com/certbot/certbot.svg?branch=master
:target: https://travis-ci.com/certbot/certbot
:alt: Travis CI status
.. |container| image:: https://quay.io/repository/letsencrypt/letsencrypt/status
:target: https://quay.io/repository/letsencrypt/letsencrypt
:alt: Docker Repository on Quay.io
.. Do not modify this comment unless you know what you're doing. tag:links-end
System Requirements

View File

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

View File

@@ -322,15 +322,23 @@ def post_arg_parse_except_hook(exc_type, exc_value, trace, debug, log_path):
logger.error('Exiting abnormally:', exc_info=exc_info)
else:
logger.debug('Exiting abnormally:', exc_info=exc_info)
# Use logger to print the error message to take advantage of
# our logger printing warnings and errors in red text.
if issubclass(exc_type, errors.Error):
sys.exit(exc_value)
logger.error(str(exc_value))
sys.exit(1)
logger.error('An unexpected error occurred:')
if messages.is_acme_error(exc_value):
# Remove the ACME error prefix from the exception
_, _, exc_str = str(exc_value).partition(':: ')
logger.error(exc_str)
else:
traceback.print_exception(exc_type, exc_value, None)
output = traceback.format_exception_only(exc_type, exc_value)
# format_exception_only returns a list of strings each
# terminated by a newline. We combine them into one string
# and remove the final newline before passing it to
# logger.error.
logger.error(''.join(output).rstrip())
exit_with_log_path(log_path)

View File

@@ -1007,18 +1007,18 @@ class RenewableCert(interfaces.RenewableCert):
lineagename = lineagename_for_filename(config_filename)
archive = full_archive_path(None, cli_config, lineagename)
live_dir = _full_live_path(cli_config, lineagename)
if os.path.exists(archive):
if os.path.exists(archive) and (not os.path.isdir(archive) or os.listdir(archive)):
config_file.close()
raise errors.CertStorageError(
"archive directory exists for " + lineagename)
if os.path.exists(live_dir):
if os.path.exists(live_dir) and (not os.path.isdir(live_dir) or os.listdir(live_dir)):
config_file.close()
raise errors.CertStorageError(
"live directory exists for " + lineagename)
filesystem.mkdir(archive)
filesystem.mkdir(live_dir)
logger.debug("Archive directory %s and live "
"directory %s created.", archive, live_dir)
for i in (archive, live_dir):
if not os.path.exists(i):
filesystem.makedirs(i)
logger.debug("Creating directory %s.", i)
# Put the data into the appropriate files on disk
target = {kind: os.path.join(live_dir, kind + ".pem") for kind in ALL_FOUR}

View File

@@ -78,6 +78,35 @@ def copy_ownership_and_apply_mode(src, dst, mode, copy_user, copy_group):
chmod(dst, mode)
# Quite similar to copy_ownership_and_apply_mode, but this time the DACL is copied from
# the source file on Windows. The DACL stays consistent with the dynamic rights of the
# equivalent POSIX mode, because ownership and mode are copied altogether on the destination
# file, so no recomputing of the DACL against the new owner is needed, as it would be
# for a copy_ownership alone method.
def copy_ownership_and_mode(src, dst, copy_user=True, copy_group=True):
# type: (str, str, bool, bool) -> None
"""
Copy ownership (user and optionally group on Linux) and mode/DACL
from the source to the destination.
:param str src: Path of the source file
:param str dst: Path of the destination file
:param bool copy_user: Copy user if `True`
:param bool copy_group: Copy group if `True` on Linux (has no effect on Windows)
"""
if POSIX_MODE:
# On Linux, we just delegate to chown and chmod.
stats = os.stat(src)
user_id = stats.st_uid if copy_user else -1
group_id = stats.st_gid if copy_group else -1
os.chown(dst, user_id, group_id)
chmod(dst, stats.st_mode)
else:
if copy_user:
# There is no group handling in Windows
_copy_win_ownership(src, dst)
_copy_win_mode(src, dst)
def check_mode(file_path, mode):
# type: (str, int) -> bool
"""
@@ -208,8 +237,19 @@ def makedirs(file_path, mode=0o777):
will be applied if ``None``
"""
if POSIX_MODE:
return os.makedirs(file_path, mode)
# Since Python 3.7, os.makedirs does not set the given mode to the intermediate directories
# that could be created in the process. To keep things safe and consistent on all
# Python versions, we set the umask accordingly to have all directories (intermediate and
# leaf) created with the given mode.
current_umask = os.umask(0)
try:
os.umask(current_umask | 0o777 ^ mode)
return os.makedirs(file_path, mode)
finally:
os.umask(current_umask)
# TODO: Windows does not support umask. A specific PR (#7967) is handling this, and will need
# to add appropriate umask call for the Windows part of the logic below.
orig_mkdir_fn = os.mkdir
try:
# As we know that os.mkdir is called internally by os.makedirs, we will swap the function in
@@ -515,6 +555,9 @@ def _analyze_mode(mode):
def _copy_win_ownership(src, dst):
# Resolve symbolic links
src = realpath(src)
security_src = win32security.GetFileSecurity(src, win32security.OWNER_SECURITY_INFORMATION)
user_src = security_src.GetSecurityDescriptorOwner()
@@ -526,6 +569,19 @@ def _copy_win_ownership(src, dst):
win32security.SetFileSecurity(dst, win32security.OWNER_SECURITY_INFORMATION, security_dst)
def _copy_win_mode(src, dst):
# Resolve symbolic links
src = realpath(src)
# Copy the DACL from src to dst.
security_src = win32security.GetFileSecurity(src, win32security.DACL_SECURITY_INFORMATION)
dacl = security_src.GetSecurityDescriptorDacl()
security_dst = win32security.GetFileSecurity(dst, win32security.DACL_SECURITY_INFORMATION)
security_dst.SetSecurityDescriptorDacl(1, dacl, 0)
win32security.SetFileSecurity(dst, win32security.DACL_SECURITY_INFORMATION, security_dst)
def _generate_windows_flags(rights_desc):
# Some notes about how each POSIX right is interpreted.
#

View File

@@ -30,7 +30,7 @@ def get_email(invalid=False, optional=True):
"""
invalid_prefix = "There seem to be problems with that address. "
msg = "Enter email address (used for urgent renewal and security notices)"
msg = "Enter email address (used for urgent renewal and security notices)\n"
unsafe_suggestion = ("\n\nIf you really want to skip this, you can run "
"the client with --register-unsafely-without-email "
"but make sure you then backup your account key from "
@@ -64,7 +64,7 @@ def get_email(invalid=False, optional=True):
if util.safe_email(email):
return email
if suggest_unsafe:
msg += unsafe_suggestion
msg = unsafe_suggestion + msg
suggest_unsafe = False # add this message at most once
invalid = bool(email)

View File

@@ -256,7 +256,11 @@ def _check_ocsp_response(response_ocsp, request_ocsp, issuer_cert, cert_path):
def _check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path):
"""Verify an OCSP response signature against certificate issuer or responder"""
if response_ocsp.responder_name == issuer_cert.subject:
def _key_hash(cert):
return x509.SubjectKeyIdentifier.from_public_key(cert.public_key()).digest
if response_ocsp.responder_name == issuer_cert.subject or \
response_ocsp.responder_key_hash == _key_hash(issuer_cert):
# Case where the OCSP responder is also the certificate issuer
logger.debug('OCSP response for certificate %s is signed by the certificate\'s issuer.',
cert_path)
@@ -267,7 +271,8 @@ def _check_ocsp_response_signature(response_ocsp, issuer_cert, cert_path):
cert_path)
responder_certs = [cert for cert in response_ocsp.certificates
if cert.subject == response_ocsp.responder_name]
if response_ocsp.responder_name == cert.subject or \
response_ocsp.responder_key_hash == _key_hash(cert)]
if not responder_certs:
raise AssertionError('no matching responder certificate could be found')

View File

@@ -113,7 +113,7 @@ optional arguments:
case, and to know when to deprecate support for past
Python versions and flags. If you wish to hide this
information from the Let's Encrypt server, set this to
"". (default: CertbotACMEClient/1.3.0 (certbot(-auto);
"". (default: CertbotACMEClient/1.5.0 (certbot(-auto);
OS_NAME OS_VERSION) Authenticator/XXX Installer/YYY
(SUBCOMMAND; flags: FLAGS) Py/major.minor.patchlevel).
The flags encoded in the user agent are: --duplicate,
@@ -188,10 +188,12 @@ security:
supported setups (Apache version >= 2.3.3 ). (default:
False)
--redirect Automatically redirect all HTTP traffic to HTTPS for
the newly authenticated vhost. (default: Ask)
the newly authenticated vhost. (default: redirect
enabled for install and run, disabled for enhance)
--no-redirect Do not automatically redirect all HTTP traffic to
HTTPS for the newly authenticated vhost. (default:
Ask)
redirect enabled for install and run, disabled for
enhance)
--hsts Add the Strict-Transport-Security header to every HTTP
response. Forcing browser to always use SSL for the
domain. Defends against SSL Stripping. (default: None)
@@ -213,8 +215,8 @@ testing:
--test-cert, --staging
Use the staging server to obtain or revoke test
(invalid) certificates; equivalent to --server https
://acme-staging-v02.api.letsencrypt.org/directory
(invalid) certificates; equivalent to --server
https://acme-staging-v02.api.letsencrypt.org/directory
(default: False)
--debug Show tracebacks in case of errors, and allow certbot-
auto execution on experimental platforms (default:
@@ -319,8 +321,8 @@ renew:
of renewed certificate domains (for example,
"example.com www.example.com" (default: None)
--disable-hook-validation
Ordinarily the commands specified for --pre-hook
/--post-hook/--deploy-hook will be checked for
Ordinarily the commands specified for --pre-
hook/--post-hook/--deploy-hook will be checked for
validity, to see if the programs being run are in the
$PATH, so that mistakes can be caught early, even when
the hooks aren't being run just yet. The validation is
@@ -669,7 +671,11 @@ manual:
requested when performing an HTTP-01 challenge. An additional cleanup
script can also be provided and can use the additional variable
$CERTBOT_AUTH_OUTPUT which contains the stdout output from the auth
script.
script.For both authenticator and cleanup script, on HTTP-01 and DNS-01
challenges,$CERTBOT_REMAINING_CHALLENGES will be equal to the number of
challenges that remain after the current one, and $CERTBOT_ALL_DOMAINS
contains a comma-separated list of all domains that are challenged for the
current certificate.
--manual-auth-hook MANUAL_AUTH_HOOK
Path or command to execute for the authentication

View File

@@ -1,2 +1,2 @@
# Remember to update setup.py to match the package versions below.
-e acme[dev]
acme[dev]==1.4.0

View File

@@ -36,7 +36,7 @@ version = meta['version']
# specified here to avoid masking the more specific request requirements in
# acme. See https://github.com/pypa/pip/issues/988 for more info.
install_requires = [
'acme>=1.4.0.dev0',
'acme>=1.4.0',
# We technically need ConfigArgParse 0.10.0 for Python 2.6 support, but
# saying so here causes a runtime error against our temporary fork of 0.9.3
# in which we added 2.6 support (see #2243), so we relax the requirement.

View File

@@ -1,6 +1,7 @@
"""Tests for certbot.compat.filesystem"""
import contextlib
import errno
import stat
import unittest
try:
@@ -280,14 +281,34 @@ class WindowsMkdirTests(test_util.TempDirTestCase):
self.assertEqual(original_mkdir, std_os.mkdir)
class OwnershipTest(test_util.TempDirTestCase):
"""Tests about copy_ownership_and_apply_mode and has_same_ownership"""
# TODO: This test can be used both by Linux and Windows once on #7967
@unittest.skipUnless(POSIX_MODE, reason='Needs umask to succeed, and Windows does not have it')
class LinuxMkdirTests(test_util.TempDirTestCase):
"""Unit tests for Linux mkdir + makedirs functions in filesystem module"""
def test_makedirs_correct_permissions(self):
path = os.path.join(self.tempdir, 'dir')
subpath = os.path.join(path, 'subpath')
previous_umask = os.umask(0o022)
try:
filesystem.makedirs(subpath, 0o700)
import os as std_os # pylint: disable=os-module-forbidden
assert stat.S_IMODE(std_os.stat(path).st_mode) == 0o700
assert stat.S_IMODE(std_os.stat(subpath).st_mode) == 0o700
finally:
os.umask(previous_umask)
class CopyOwnershipAndModeTest(test_util.TempDirTestCase):
"""Tests about copy_ownership_and_apply_mode, copy_ownership_and_mode and has_same_ownership"""
def setUp(self):
super(OwnershipTest, self).setUp()
super(CopyOwnershipAndModeTest, self).setUp()
self.probe_path = _create_probe(self.tempdir)
@unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security')
def test_copy_ownership_windows(self):
def test_copy_ownership_and_apply_mode_windows(self):
system = win32security.ConvertStringSidToSid(SYSTEM_SID)
security = win32security.SECURITY_ATTRIBUTES().SECURITY_DESCRIPTOR
security.SetSecurityDescriptorOwner(system, False)
@@ -313,7 +334,7 @@ class OwnershipTest(test_util.TempDirTestCase):
if dacl.GetAce(index)[2] == everybody])
@unittest.skipUnless(POSIX_MODE, reason='Test specific to Linux security')
def test_copy_ownership_linux(self):
def test_copy_ownership_and_apply_mode_linux(self):
with mock.patch('os.chown') as mock_chown:
with mock.patch('os.chmod') as mock_chmod:
with mock.patch('os.stat') as mock_stat:
@@ -334,6 +355,24 @@ class OwnershipTest(test_util.TempDirTestCase):
self.assertTrue(filesystem.has_same_ownership(path1, path2))
@unittest.skipIf(POSIX_MODE, reason='Test specific to Windows security')
def test_copy_ownership_and_mode_windows(self):
src = self.probe_path
dst = _create_probe(self.tempdir, name='dst')
filesystem.chmod(src, 0o700)
self.assertTrue(filesystem.check_mode(src, 0o700))
self.assertTrue(filesystem.check_mode(dst, 0o744))
# Checking an actual change of owner is tricky during a unit test, since we do not know
# if any user exists beside the current one. So we mock _copy_win_ownership. It's behavior
# have been checked theoretically with test_copy_ownership_and_apply_mode_windows.
with mock.patch('certbot.compat.filesystem._copy_win_ownership') as mock_copy_owner:
filesystem.copy_ownership_and_mode(src, dst)
mock_copy_owner.assert_called_once_with(src, dst)
self.assertTrue(filesystem.check_mode(dst, 0o700))
class CheckPermissionsTest(test_util.TempDirTestCase):
"""Tests relative to functions that check modes."""
@@ -537,9 +576,9 @@ def _set_owner(target, security_owner, user):
target, win32security.OWNER_SECURITY_INFORMATION, security_owner)
def _create_probe(tempdir):
def _create_probe(tempdir, name='probe'):
filesystem.chmod(tempdir, 0o744)
probe_path = os.path.join(tempdir, 'probe')
probe_path = os.path.join(tempdir, name)
util.safe_open(probe_path, 'w', chmod=0o744).close()
return probe_path

View File

@@ -182,13 +182,23 @@ class OSCPTestCryptography(unittest.TestCase):
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
# OCSP response with ResponseID as Name
mocks['mock_response'].return_value.responder_name = issuer.subject
mocks['mock_response'].return_value.responder_key_hash = None
self.checker.ocsp_revoked(self.cert_obj)
# OCSP response with ResponseID as KeyHash
key_hash = x509.SubjectKeyIdentifier.from_public_key(issuer.public_key()).digest
mocks['mock_response'].return_value.responder_name = None
mocks['mock_response'].return_value.responder_key_hash = key_hash
self.checker.ocsp_revoked(self.cert_obj)
# Here responder and issuer are the same. So only the signature of the OCSP
# response is checked (using the issuer/responder public key).
self.assertEqual(mocks['mock_check'].call_count, 1)
self.assertEqual(mocks['mock_check'].call_args[0][0].public_numbers(),
issuer.public_key().public_numbers())
self.assertEqual(mocks['mock_check'].call_count, 2)
self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(),
issuer.public_key().public_numbers())
self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(),
issuer.public_key().public_numbers())
def test_responder_is_authorized_delegate(self):
issuer = x509.load_pem_x509_certificate(
@@ -198,15 +208,28 @@ class OSCPTestCryptography(unittest.TestCase):
with _ocsp_mock(ocsp_lib.OCSPCertStatus.REVOKED,
ocsp_lib.OCSPResponseStatus.SUCCESSFUL) as mocks:
# OCSP response with ResponseID as Name
mocks['mock_response'].return_value.responder_name = responder.subject
mocks['mock_response'].return_value.responder_key_hash = None
self.checker.ocsp_revoked(self.cert_obj)
# OCSP response with ResponseID as KeyHash
key_hash = x509.SubjectKeyIdentifier.from_public_key(responder.public_key()).digest
mocks['mock_response'].return_value.responder_name = None
mocks['mock_response'].return_value.responder_key_hash = key_hash
self.checker.ocsp_revoked(self.cert_obj)
# Here responder and issuer are not the same. Two signatures will be checked then,
# first to verify the responder cert (using the issuer public key), second to
# to verify the OCSP response itself (using the responder public key).
self.assertEqual(mocks['mock_check'].call_count, 2)
self.assertEqual(mocks['mock_check'].call_count, 4)
self.assertEqual(mocks['mock_check'].call_args_list[0][0][0].public_numbers(),
issuer.public_key().public_numbers())
self.assertEqual(mocks['mock_check'].call_args_list[1][0][0].public_numbers(),
responder.public_key().public_numbers())
self.assertEqual(mocks['mock_check'].call_args_list[2][0][0].public_numbers(),
issuer.public_key().public_numbers())
self.assertEqual(mocks['mock_check'].call_args_list[3][0][0].public_numbers(),
responder.public_key().public_numbers())
def test_revoke_resiliency(self):
# Server return an invalid HTTP response

View File

@@ -610,17 +610,25 @@ class RenewableCertTests(BaseRenewableCertTest):
self.config.renewal_configs_dir, "the-lineage.com-0001.conf")))
self.assertTrue(os.path.exists(os.path.join(
self.config.live_dir, "the-lineage.com-0001", "README")))
# Allow write to existing but empty dir
filesystem.mkdir(os.path.join(self.config.default_archive_dir, "the-lineage.com-0002"))
result = storage.RenewableCert.new_lineage(
"the-lineage.com", b"cert3", b"privkey3", b"chain3", self.config)
self.assertTrue(os.path.exists(os.path.join(
self.config.live_dir, "the-lineage.com-0002", "README")))
self.assertTrue(filesystem.check_mode(result.key_path, 0o600))
# Now trigger the detection of already existing files
filesystem.mkdir(os.path.join(
self.config.live_dir, "the-lineage.com-0002"))
shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"),
os.path.join(self.config.live_dir, "the-lineage.com-0003"))
self.assertRaises(errors.CertStorageError,
storage.RenewableCert.new_lineage, "the-lineage.com",
b"cert3", b"privkey3", b"chain3", self.config)
filesystem.mkdir(os.path.join(self.config.default_archive_dir, "other-example.com"))
b"cert4", b"privkey4", b"chain4", self.config)
shutil.copytree(os.path.join(self.config.live_dir, "the-lineage.com"),
os.path.join(self.config.live_dir, "other-example.com"))
self.assertRaises(errors.CertStorageError,
storage.RenewableCert.new_lineage,
"other-example.com", b"cert4",
b"privkey4", b"chain4", self.config)
"other-example.com", b"cert5",
b"privkey5", b"chain5", self.config)
# Make sure it can accept renewal parameters
result = storage.RenewableCert.new_lineage(
"the-lineage.com", b"cert2", b"privkey2", b"chain2", self.config)

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="1.3.0"
LE_AUTO_VERSION="1.5.0"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -910,20 +910,11 @@ elif [ -f /etc/manjaro-release ]; then
}
BOOTSTRAP_VERSION="BootstrapArchCommon $BOOTSTRAP_ARCH_COMMON_VERSION"
elif [ -f /etc/gentoo-release ]; then
Bootstrap() {
DeprecationBootstrap "Gentoo" BootstrapGentooCommon
}
BOOTSTRAP_VERSION="BootstrapGentooCommon $BOOTSTRAP_GENTOO_COMMON_VERSION"
DEPRECATED_OS=1
elif uname | grep -iq FreeBSD ; then
Bootstrap() {
DeprecationBootstrap "FreeBSD" BootstrapFreeBsd
}
BOOTSTRAP_VERSION="BootstrapFreeBsd $BOOTSTRAP_FREEBSD_VERSION"
DEPRECATED_OS=1
elif uname | grep -iq Darwin ; then
Bootstrap() {
DeprecationBootstrap "macOS" BootstrapMac
}
BOOTSTRAP_VERSION="BootstrapMac $BOOTSTRAP_MAC_VERSION"
DEPRECATED_OS=1
elif [ -f /etc/issue ] && grep -iq "Amazon Linux" /etc/issue ; then
Bootstrap() {
ExperimentalBootstrap "Amazon Linux" BootstrapRpmCommon
@@ -1343,7 +1334,9 @@ cryptography==2.8 \
distro==1.4.0 \
--hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \
--hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4
enum34==1.1.6 \
# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid
# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456.
enum34==1.1.6 ; python_version < '3.4' \
--hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \
--hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \
--hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \
@@ -1540,18 +1533,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==1.3.0 \
--hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \
--hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8
acme==1.3.0 \
--hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \
--hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d
certbot-apache==1.3.0 \
--hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \
--hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52
certbot-nginx==1.3.0 \
--hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \
--hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b
certbot==1.5.0 \
--hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \
--hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf
acme==1.5.0 \
--hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \
--hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0
certbot-apache==1.5.0 \
--hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \
--hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764
certbot-nginx==1.5.0 \
--hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \
--hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -1,11 +1,11 @@
-----BEGIN PGP SIGNATURE-----
iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl5ewVUACgkQTRfJlc2X
dfJnZAf+KmxYl1YoP/FlTG5Npb64qaDdxm59SeEVJez6fZh15xq71tRPYR+4xszE
XTeyGt7uAxjYqeiBJU5xBvGC1Veprhj5AbflVOTP+5yiBr9iNWC35zmgaE63UlZ/
V94sfL0pkax7wLngil7a0OuzUjikzK3gXOqrY8LoUdr4mAA9AhSjajWHmyY3tpDR
84GKrVhybIt0sjy/172VuPPbXZKno/clztkKMZHXNrDeL5jgJ15Va4Ts5FK0j9VT
HQvuazbGkYVCuvlp8Np5ESDje69LCJfPZxl34htoa8WNJoVIOsQWZpoXp5B5huSP
vGrh4LabZ5UDsl+k11ikHBRUpO7E5w==
=IgRH
iQEzBAABCAAdFiEEos+1H6J1pyhiNOeyTRfJlc2XdfIFAl7WjTUACgkQTRfJlc2X
dfI9pQf/bqfbpHAkO6iRd/LcnEXujICG4CIfJxZUlhh7HoMnmtFmWLp9k3pN6iRZ
LKpl8gbKTek6yGnYuNQjp2/C87WyY9w06niCkg/D2W14ii/MuHGA99OVhc0M99dv
ZG5Vh6Qu3WAXP4sHADmMHjM8CKsG//SrFfE2ZQ6kCg20l3h4MaaKaN85JwNO0RpO
OKOj1LF29OlZ2G8HKGi0VmeO/++Z8QSDwKAYdimS3B/5DTGUciR/7BgR8a90goPl
BOhDR00MHdRuBRuAj3siZUVTxNT3xLgxaa6QYZf6by/Bb6+A02VzW0oF6XYJPdEK
TtSiQzKrmaoOkXz/4WF99W9HAxYpyw==
=WVyF
-----END PGP SIGNATURE-----

View File

@@ -31,7 +31,7 @@ if [ -z "$VENV_PATH" ]; then
fi
VENV_BIN="$VENV_PATH/bin"
BOOTSTRAP_VERSION_PATH="$VENV_PATH/certbot-auto-bootstrap-version.txt"
LE_AUTO_VERSION="1.4.0.dev0"
LE_AUTO_VERSION="1.6.0.dev0"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -1334,7 +1334,9 @@ cryptography==2.8 \
distro==1.4.0 \
--hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \
--hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4
enum34==1.1.6 \
# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid
# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456.
enum34==1.1.6 ; python_version < '3.4' \
--hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \
--hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \
--hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \
@@ -1531,18 +1533,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==1.3.0 \
--hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \
--hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8
acme==1.3.0 \
--hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \
--hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d
certbot-apache==1.3.0 \
--hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \
--hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52
certbot-nginx==1.3.0 \
--hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \
--hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b
certbot==1.5.0 \
--hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \
--hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf
acme==1.5.0 \
--hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \
--hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0
certbot-apache==1.5.0 \
--hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \
--hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764
certbot-nginx==1.5.0 \
--hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \
--hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -1,12 +1,12 @@
certbot==1.3.0 \
--hash=sha256:979793b36151be26c159f1946d065a0cbbcaed3e9ac452c19a142b0d2d2b42e3 \
--hash=sha256:bc2091cbbc2f432872ed69309046e79771d9c81cd441bde3e6a6553ecd04b1d8
acme==1.3.0 \
--hash=sha256:b888757c750e393407a3cdf0eb5c2d06036951e10c41db4c83537617568561b6 \
--hash=sha256:c0de9e1fbcb4a28509825a4d19ab5455910862b23fa338acebc7bbe7c0abd20d
certbot-apache==1.3.0 \
--hash=sha256:1050cd262bcc598957c45a6fa1febdf5e41e87176c0aebad3a1ab7268b0d82d9 \
--hash=sha256:4a6bb818a7a70803127590a54bb25c1e79810761c9d4c92cf9f16a56b518bd52
certbot-nginx==1.3.0 \
--hash=sha256:46106b96429d1aaf3765635056352d2372941027a3bc26bbf964e4329202adc7 \
--hash=sha256:9aa0869c1250b7ea0a1eb1df6bdb5d0d6190d6ca0400da1033a8decc0df6f65b
certbot==1.5.0 \
--hash=sha256:ec1f01af06b52a6f079f5b02cb70e88f0671a7b13ecb3e45b040563e32c6e53a \
--hash=sha256:c52017a4f84137e1312c898d6ae69c5f7977d79d2bd4c2df013cbbf39b6539bf
acme==1.5.0 \
--hash=sha256:66de67b394bb7606f97f2c21507e6eb6a88936db2a940f5c4893025f87e3852a \
--hash=sha256:b051ff7dd3935b2032c2f8c8386e905d9b658eba9f3455e352650d85bea9c8f0
certbot-apache==1.5.0 \
--hash=sha256:d2c28be6dcd6c56a8040c8c733e72c1341238b1b47fb59f544eb832b9d5c81ba \
--hash=sha256:3eec5a49ae4fcf86213f962eb1e11d8a725b65e7dcee18f9b92c7aa73f821764
certbot-nginx==1.5.0 \
--hash=sha256:3d27fd02ebe15b07ce5fa9525ceeda82aa5fdc45aa064729434faff0442d1f91 \
--hash=sha256:b38f101588af6d2b8ea7c2e3334f249afbe14461a85add2f1420091d860df983

View File

@@ -78,7 +78,9 @@ cryptography==2.8 \
distro==1.4.0 \
--hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \
--hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4
enum34==1.1.6 \
# Package enum34 needs to be explicitly limited to Python2.x, in order to avoid
# certbot-auto failures on Python 3.6+ which enum34 doesn't support. See #5456.
enum34==1.1.6 ; python_version < '3.4' \
--hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \
--hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \
--hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \

0
letsencrypt-auto-source/rebuild_dependencies.py Normal file → Executable file
View File

View File

@@ -4,6 +4,13 @@
[pytest]
# In general, all warnings are treated as errors. Here are the exceptions:
# 1- decodestring: https://github.com/rthalley/dnspython/issues/338
# Warnings being triggered by our plugins using deprecated features in
# acme/certbot should be fixed by having our plugins no longer using the
# deprecated code rather than adding them to the list of ignored warnings here.
# Fixing things in this way prevents us from shipping packages raising our own
# deprecation warnings and gives time for plugins that don't use the deprecated
# API to propagate, especially for plugins packaged as an external snap, before
# we release breaking changes.
filterwarnings =
error
ignore:decodestring:DeprecationWarning

3
snap/hooks/configure vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/bin/bash -e
exit 0

View File

@@ -0,0 +1,11 @@
#!/bin/bash -e
if [ "$(snapctl get trust-plugin-with-root)" = "ok" ]; then
# allow the connection, but reset config to allow for other slots to go through this auth flow
snapctl unset trust-plugin-with-root
exit 0
else
echo "Only connect this interface if you trust the plugin author to have root on the system"
echo "Run \`snap set $SNAP_NAME trust-plugin-with-root=ok\` to acknowledge this and then run this command again to perform the connection"
exit 1
fi

View File

@@ -32,9 +32,8 @@ apps:
PATH: "$SNAP/bin:$SNAP/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
AUGEAS_LENS_LIB: $SNAP/usr/share/augeas/lenses/dist
LD_LIBRARY_PATH: "$SNAP/usr/lib/x86_64-linux-gnu/:$LD_LIBRARY_PATH"
passthrough:
# Run approximately twice a day with randomization
timer: 00:00~24:00/2
# Run approximately twice a day with randomization
timer: 00:00~24:00/2
parts:
python-augeas:
@@ -86,3 +85,9 @@ parts:
# After certbot-apache to not rebuild duplicates (essentially sharing what was already staged,
# like zope)
after: [certbot-apache]
plugs:
plugin:
interface: content
content: certbot-1
target: $SNAP/certbot-plugin

View File

@@ -15,9 +15,10 @@ Simple AWS testfarm scripts for certbot client testing
are needed, they need to be requested via online webform.
## Installation and configuration
These tests require Python 3, awscli, boto3, PyYAML, and fabric 2.0+. If you
have Python 3 installed, you can use requirements.txt to create a virtual
environment with a known set of dependencies by running:
These tests require Python 3, awscli, boto3, PyYAML, and fabric 2.0+. If you're
on a Debian based system, make sure you also have the python3-venv package
installed. If you have Python 3 installed, you can use requirements.txt to
create a virtual environment with a known set of dependencies by running:
```
python3 -m venv venv3
. ./venv3/bin/activate

View File

@@ -34,7 +34,7 @@ fi
VERSION=$("$PYTHON_NAME" letsencrypt-auto-source/version.py)
# setup venv
"$VENV_SCRIPT" --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt
CERTBOT_PIP_NO_BINARY=":all:" "$VENV_SCRIPT" --requirement letsencrypt-auto-source/pieces/dependency-requirements.txt
. "$VENV_PATH/bin/activate"
# pytest is needed to run tests on some of our packages so we install a pinned version here.
tools/pip_install.py pytest

View File

@@ -12,6 +12,7 @@ VENV_NAME.
from __future__ import print_function
from distutils.version import LooseVersion
import glob
import os
import re
@@ -131,6 +132,13 @@ def subprocess_with_print(cmd, env=None, shell=False):
subprocess.check_call(cmd, env=env, shell=shell)
def subprocess_output_with_print(cmd, env=None, shell=False):
if env is None:
env = os.environ
print('+ {0}'.format(subprocess.list2cmdline(cmd)) if isinstance(cmd, list) else cmd)
return subprocess.check_output(cmd, env=env, shell=shell)
def get_venv_python_path(venv_path):
python_linux = os.path.join(venv_path, 'bin/python')
if os.path.isfile(python_linux):
@@ -191,9 +199,31 @@ def install_packages(venv_name, pip_args):
# Using the python executable from venv, we ensure to execute following commands in this venv.
py_venv = get_venv_python_path(venv_name)
subprocess_with_print([py_venv, os.path.abspath('letsencrypt-auto-source/pieces/pipstrap.py')])
# We only use this value during pip install because:
# 1) We're really only adding it for installing cryptography, which happens here, and
# 2) There are issues with calling it along with VIRTUALENV_NO_DOWNLOAD, which applies at the
# steps above, not during pip install.
env_pip_no_binary = os.environ.get('CERTBOT_PIP_NO_BINARY')
if env_pip_no_binary:
# Check OpenSSL version. If it's too low, don't apply the env variable.
openssl_version_string = str(subprocess_output_with_print(['openssl', 'version']))
matches = re.findall(r'OpenSSL ([^ ]+) ', openssl_version_string)
if not matches:
print('Could not find OpenSSL version, not setting PIP_NO_BINARY.')
else:
openssl_version = matches[0]
if LooseVersion(openssl_version) >= LooseVersion('1.0.2'):
print('Setting PIP_NO_BINARY to {0}'
' as specified in CERTBOT_PIP_NO_BINARY'.format(env_pip_no_binary))
os.environ['PIP_NO_BINARY'] = env_pip_no_binary
else:
print('Not setting PIP_NO_BINARY, as OpenSSL version is too old.')
command = [py_venv, os.path.abspath('tools/pip_install.py')]
command.extend(pip_args)
subprocess_with_print(command)
if 'PIP_NO_BINARY' in os.environ:
del os.environ['PIP_NO_BINARY']
if os.path.isdir(os.path.join(venv_name, 'bin')):
# Linux/OSX specific

View File

@@ -14,7 +14,7 @@ DEFAULT_PACKAGES = [
'certbot_dns_sakuracloud', 'certbot_nginx']
COVER_THRESHOLDS = {
'certbot': {'linux': 96, 'windows': 96},
'certbot': {'linux': 95, 'windows': 96},
'acme': {'linux': 100, 'windows': 99},
'certbot_apache': {'linux': 100, 'windows': 100},
'certbot_dns_cloudflare': {'linux': 98, 'windows': 98},