Compare commits

..

20 Commits

Author SHA1 Message Date
Adrien Ferrand
4dddb8f060 Merge branch 'master-uptsream' into apache-integration-tests
# Conflicts:
#	.travis.yml
#	tox.ini
2019-09-25 19:59:54 +02:00
Adrien Ferrand
b1f3c6f859 Set trusty distribution 2019-08-29 15:04:52 +02:00
Adrien Ferrand
d0c6be244f Simplify Travis config. Fix docker-dev 2019-08-29 15:02:10 +02:00
Adrien Ferrand
3c572b84ab Avoid installing APT packages on OSX ... 2019-08-29 01:05:15 +02:00
Adrien Ferrand
d4f47e920b Fix cleanup 2019-08-28 21:51:22 +02:00
Adrien Ferrand
e1bae626f1 Fixing 2019-08-28 21:28:29 +02:00
Adrien Ferrand
df40057bcc Reconfigure apt install, totally remove sudo that is not used by travis anymore 2019-08-28 19:54:51 +02:00
Adrien Ferrand
95f9ed247a Update packages 2019-08-28 17:47:07 +02:00
Adrien Ferrand
3a411c092f Real path 2019-08-28 17:46:04 +02:00
Adrien Ferrand
3163801123 Merge branch 'master' into apache-integration-tests
# Conflicts:
#	certbot-ci/certbot_integration_tests/utils/certbot_call.py
2019-08-28 17:43:10 +02:00
Adrien Ferrand
a68de55696 Update coverage 2019-08-28 17:27:13 +02:00
Adrien Ferrand
4bc473a2db Finish isolation and toxenv 2019-08-28 17:16:58 +02:00
Adrien Ferrand
23ec9afdb4 Working implementation 2019-08-28 16:05:34 +02:00
Adrien Ferrand
f401750b43 Copy symlinks 2019-08-28 14:13:12 +02:00
Adrien Ferrand
3ef88a68ed Fix various paths 2019-08-28 13:03:54 +02:00
Adrien Ferrand
e6b2689dcb Fix escape characters 2019-08-28 12:56:06 +02:00
Adrien Ferrand
26aae00c36 Setup apache2.conf 2019-08-28 12:53:10 +02:00
Adrien Ferrand
0eeae8196d Continue logic 2019-08-28 12:46:18 +02:00
Adrien Ferrand
11d9107c95 Add logic 2019-08-28 12:23:24 +02:00
Adrien Ferrand
3becf7be16 Create base config 2019-08-28 12:13:25 +02:00
530 changed files with 8326 additions and 5038 deletions

View File

@@ -1,119 +0,0 @@
# Configuring Azure Pipelines with Certbot
Let's begin. All pipelines are defined in `.azure-pipelines`. Currently there are two:
* `.azure-pipelines/main.yml` is the main one, executed on PRs for master, and pushes to master,
* `.azure-pipelines/advanced.yml` add installer testing on top of the main pipeline, and is executed for `test-*` branches, release branches, and nightly run for master.
Several templates are defined in `.azure-pipelines/templates`. These YAML files aggregate common jobs configuration that can be reused in several pipelines.
Unlike Travis, where CodeCov is working without any action required, CodeCov supports Azure Pipelines
using the coverage-bash utility (not python-coverage for now) only if you provide the Codecov repo token
using the `CODECOV_TOKEN` environment variable. So `CODECOV_TOKEN` needs to be set as a secured
environment variable to allow the main pipeline to publish coverage reports to CodeCov.
This INSTALL.md file explains how to configure Azure Pipelines with Certbot in order to execute the CI/CD logic defined in `.azure-pipelines` folder with it.
During this installation step, warnings describing user access and legal comitments will be displayed like this:
```
!!! ACCESS REQUIRED !!!
```
This document suppose that the Azure DevOps organization is named _certbot_, and the Azure DevOps project is also _certbot_.
## Useful links
* https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema
* https://www.azuredevopslabs.com/labs/azuredevops/github-integration/
* https://docs.microsoft.com/en-us/azure/devops/pipelines/ecosystems/python?view=azure-devops
## Prerequisites
### Having a GitHub account
Use your GitHub user for a normal GitHub account, or a user that has administrative rights to the GitHub organization if relevant.
### Having an Azure DevOps account
- Go to https://dev.azure.com/, click "Start free with GitHub"
- Login to GitHub
```
!!! ACCESS REQUIRED !!!
Personal user data (email + profile info, in read-only)
```
- Microsoft will create a Live account using the email referenced for the GitHub account. This account is also linked to GitHub account (meaning you can log it using GitHub authentication)
- Proceed with account registration (birth date, country), add details about name and email contact
```
!!! ACCESS REQUIRED !!!
Microsoft proposes to send commercial links to this mail
Azure DevOps terms of service need to be accepted
```
_Logged to Azure DevOps, account is ready._
### Installing Azure Pipelines to GitHub
- On GitHub, go to Marketplace
- Select Azure Pipeline, and "Set up a plan"
- Select Free, then "Install it for free"
- Click "Complete order and begin installation"
```
!!! ACCESS !!!
Azure Pipeline needs RW on code, RO on metadata, RW on checks, commit statuses, deployments, issues, pull requests.
RW access here is required to allow update of the pipelines YAML files from Azure DevOps interface, and to
update the status of builds and PRs on GitHub side when Azure Pipelines are triggered.
Note however that no admin access is defined here: this means that Azure Pipelines cannot do anything with
protected branches, like master, and cannot modify the security context around this on GitHub.
Access can be defined for all or only selected repositories, which is nice.
```
- Redirected to Azure DevOps, select the account created in _Having an Azure DevOps account_ section.
- Select the organization, and click "Create a new project" (let's name it the same than the targetted github repo)
- The Visibility is public, to profit from 10 parallel jobs
```
!!! ACCESS !!!
Azure Pipelines needs access to the GitHub account (in term of beeing able to check it is valid), and the Resources shared between the GitHub account and Azure Pipelines.
```
_Done. We can move to pipelines configuration._
## Import an existing pipelines from `.azure-pipelines` folder
- On Azure DevOps, go to your organization (eg. _certbot_) then your project (eg. _certbot_)
- Click "Pipelines" tab
- Click "New pipeline"
- Where is your code?: select "__Use the classic editor__"
__Warning: Do not choose the GitHub option in Where is your code? section. Indeed, this option will trigger an OAuth
grant permissions from Azure Pipelines to GitHub in order to setup a GitHub OAuth Application. The permissions asked
then are way too large (admin level on almost everything), while the classic approach does not add any more
permissions, and works perfectly well.__
- Select GitHub in "Select your repository section", choose certbot/certbot in Repository, master in default branch.
- Click on YAML option for "Select a template"
- Choose a name for the pipeline (eg. test-pipeline), and browse to the actual pipeline YAML definition in the
"YAML file path" input (eg. `.azure-pipelines/test-pipeline.yml`)
- Click "Save & queue", choose the master branch to build the first pipeline, and click "Save and run" button.
_Done. Pipeline is operational. Repeat to add more pipelines from existing YAML files in `.azure-pipelines`._
## Add a secret variable to a pipeline (like `CODECOV_TOKEN`)
__NB: Following steps suppose that you already setup the YAML pipeline file to
consume the secret variable that these steps will create as an environment variable.
For a variable named `CODECOV_TOKEN` consuming the variable `codecov_token`,
in the YAML file this setup would take the form of the following:
```
steps:
- script: ./do_something_that_consumes_CODECOV_TOKEN # Eg. `codecov -F windows`
env:
CODECOV_TOKEN: $(codecov_token)
```
To set up a variable that is shared between pipelines, follow the instructions
at
https://docs.microsoft.com/en-us/azure/devops/pipelines/library/variable-groups.
When adding variables to a group, don't forget to tick "Keep this value secret"
if it shouldn't be shared publcily.

View File

@@ -1,20 +0,0 @@
# Advanced pipeline for isolated checks and release purpose
trigger:
- test-*
- '*.x'
pr:
- test-*
# This pipeline is also nightly run on master
schedules:
- cron: "0 4 * * *"
displayName: Nightly build
branches:
include:
- master
always: true
jobs:
# Any addition here should be reflected in the release pipeline.
# It is advised to declare all jobs here as templates to improve maintainability.
- template: templates/tests-suite.yml
- template: templates/installer-tests.yml

View File

@@ -1,12 +0,0 @@
trigger:
# apache-parser-v2 is a temporary branch for doing work related to
# rewriting the parser in the Apache plugin.
- apache-parser-v2
- master
pr:
- apache-parser-v2
- master
- '*.x'
jobs:
- template: templates/tests-suite.yml

View File

@@ -1,13 +0,0 @@
# Release pipeline to build and deploy Certbot for Windows for GitHub release tags
trigger:
tags:
include:
- v*
pr: none
jobs:
# Any addition here should be reflected in the advanced pipeline.
# It is advised to declare all jobs here as templates to improve maintainability.
- template: templates/tests-suite.yml
- template: templates/installer-tests.yml
- template: templates/changelog.yml

View File

@@ -1,14 +0,0 @@
jobs:
- job: changelog
pool:
vmImage: vs2017-win2016
steps:
- bash: |
CERTBOT_VERSION="$(cd certbot && python -c "import certbot; print(certbot.__version__)" && cd ~-)"
"${BUILD_REPOSITORY_LOCALPATH}\tools\extract_changelog.py" "${CERTBOT_VERSION}" >> "${BUILD_ARTIFACTSTAGINGDIRECTORY}/release_notes.md"
displayName: Prepare changelog
- task: PublishPipelineArtifact@1
inputs:
path: $(Build.ArtifactStagingDirectory)
artifact: changelog
displayName: Publish changelog

View File

@@ -1,32 +0,0 @@
jobs:
- job: installer
pool:
vmImage: vs2017-win2016
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: 3.7
architecture: x86
addToPath: true
- script: python windows-installer/construct.py
displayName: Build Certbot installer
- task: CopyFiles@2
inputs:
sourceFolder: $(System.DefaultWorkingDirectory)/windows-installer/build/nsis
contents: '*.exe'
targetFolder: $(Build.ArtifactStagingDirectory)
- task: PublishPipelineArtifact@1
inputs:
path: $(Build.ArtifactStagingDirectory)
artifact: windows-installer
displayName: Publish Windows installer
- script: $(Build.ArtifactStagingDirectory)\certbot-beta-installer-win32.exe /S
displayName: Install Certbot
- script: |
python -m venv venv
venv\Scripts\python tools\pip_install.py -e certbot-ci
displayName: Prepare Certbot-CI
- script: |
set PATH=%ProgramFiles(x86)%\Certbot\bin;%PATH%
venv\Scripts\python -m pytest certbot-ci\certbot_integration_tests\certbot_tests -n 4
displayName: Run integration tests

View File

@@ -1,38 +0,0 @@
jobs:
- job: test
pool:
vmImage: vs2017-win2016
strategy:
matrix:
py35:
PYTHON_VERSION: 3.5
TOXENV: py35
py37-cover:
PYTHON_VERSION: 3.7
TOXENV: py37-cover
integration-certbot:
PYTHON_VERSION: 3.7
TOXENV: integration-certbot
PYTEST_ADDOPTS: --numprocesses 4
variables:
- group: certbot-common
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: $(PYTHON_VERSION)
addToPath: true
- script: python tools/pip_install.py -U tox coverage
displayName: Install dependencies
- script: python -m tox
displayName: Run tox
# We do not require codecov report upload to succeed. So to avoid to break the pipeline if
# something goes wrong, each command is suffixed with a command that hides any non zero exit
# codes and echoes an informative message instead.
- bash: |
curl -s https://codecov.io/bash -o codecov-bash || echo "Failed to download codecov-bash"
chmod +x codecov-bash || echo "Failed to apply execute permissions on codecov-bash"
./codecov-bash -F windows || echo "Codecov did not collect coverage reports"
condition: in(variables['TOXENV'], 'py37-cover', 'integration-certbot')
env:
CODECOV_TOKEN: $(codecov_token)
displayName: Publish coverage

View File

@@ -13,6 +13,6 @@ coverage:
flags: windows
# Fixed target instead of auto set by #7173, can
# be removed when flags in Codecov are added back.
target: 97.4
target: 97.7
threshold: 0.1
base: auto

View File

@@ -41,7 +41,7 @@ load-plugins=linter_plugin
# --enable=similarities". If you want to run only the classes checker, but have
# no Warning level messages displayed, use"--disable=all --enable=classes
# --disable=W"
disable=fixme,locally-disabled,locally-enabled,abstract-class-not-used,abstract-class-little-used,bad-continuation,no-self-use,invalid-name,cyclic-import,duplicate-code,design
disable=fixme,locally-disabled,locally-enabled,abstract-class-not-used,abstract-class-little-used,bad-continuation,too-few-public-methods,no-self-use,invalid-name,too-many-instance-attributes,cyclic-import,duplicate-code
# abstract-class-not-used cannot be disabled locally (at least in
# pylint 1.4.1), same for abstract-class-little-used
@@ -297,6 +297,40 @@ valid-classmethod-first-arg=cls
valid-metaclass-classmethod-first-arg=mcs
[DESIGN]
# Maximum number of arguments for function / method
max-args=6
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=(unused)?_.*|dummy
# Maximum number of locals for function / method body
max-locals=15
# Maximum number of return / yield for function / method body
max-returns=6
# Maximum number of branch for function / method body
max-branches=12
# Maximum number of statements in function / method body
max-statements=50
# Maximum number of parents for a class (see R0901).
max-parents=12
# Maximum number of attributes for a class (see R0902).
max-attributes=7
# Minimum number of public methods for a class (see R0903).
min-public-methods=2
# Maximum number of public methods for a class (see R0904).
max-public-methods=20
[EXCEPTIONS]
# Exceptions that will emit a warning when being caught. Defaults to

View File

@@ -6,6 +6,16 @@ cache:
- $HOME/.cache/pip
before_script:
# Install required apt packages
- |
if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then
./certbot-auto --non-interactive --os-packages-only
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install nginx-light
sudo -E /etc/init.d/nginx stop
sudo -E apt-get -yq --no-install-suggests --no-install-recommends install apache2
sudo -E /etc/init.d/apache2 stop
sudo -E chmod 777 -R /var/lib/apache2/module
fi
- 'if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ulimit -n 1024 ; fi'
# On Travis, the fastest parallelization for integration tests has proved to be 4.
- 'if [[ "$TOXENV" == *"integration"* ]]; then export PYTEST_ADDOPTS="--numprocesses 4"; fi'
@@ -68,18 +78,12 @@ matrix:
- python: "3.7"
env: TOXENV=py37
<<: *not-on-master
- python: "3.8"
- python: "3.8-dev"
env: TOXENV=py38
<<: *not-on-master
- sudo: required
env: TOXENV=apache_compat
services: docker
before_install:
addons:
- env: TOXENV=apache_compat
<<: *not-on-master
- sudo: required
env: TOXENV=le_auto_xenial
services: docker
- env: TOXENV=le_auto_xenial
<<: *not-on-master
- python: "2.7"
env: TOXENV=apacheconftest-with-pebble
@@ -89,11 +93,7 @@ matrix:
<<: *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
before_install:
addons:
- env: TOXENV=nginx_compat
<<: *extended-test-suite
- python: "2.7"
env:
@@ -122,13 +122,9 @@ matrix:
<<: *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
@@ -136,8 +132,6 @@ matrix:
# 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
@@ -145,8 +139,6 @@ matrix:
# 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
@@ -154,8 +146,6 @@ matrix:
# 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
@@ -163,8 +153,6 @@ matrix:
# 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.4"
env: TOXENV=py34
@@ -183,43 +171,27 @@ matrix:
<<: *extended-test-suite
- python: "3.4"
env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required
services: docker
<<: *extended-test-suite
- python: "3.4"
env: ACME_SERVER=boulder-v2 TOXENV=integration
sudo: required
services: docker
<<: *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-dev"
env: ACME_SERVER=boulder-v1 TOXENV=integration
@@ -227,21 +199,11 @@ matrix:
- python: "3.8-dev"
env: ACME_SERVER=boulder-v2 TOXENV=integration
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_jessie
services: docker
- env: TOXENV=le_auto_jessie
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_centos6
services: docker
- env: TOXENV=le_auto_centos6
<<: *extended-test-suite
- sudo: required
env: TOXENV=docker_dev
services: docker
addons:
apt:
packages: # don't install nginx and apache
- libaugeas0
- env: TOXENV=docker_dev
<<: *extended-test-suite
- language: generic
env: TOXENV=py27
@@ -268,22 +230,6 @@ matrix:
- python3
<<: *extended-test-suite
# container-based infrastructure
sudo: false
addons:
apt:
packages: # Keep in sync with letsencrypt-auto-source/pieces/bootstrappers/deb_common.sh and Boulder.
- python-dev
- gcc
- libaugeas0
- libssl-dev
- libffi-dev
- ca-certificates
# For certbot-nginx integration testing
- nginx-light
- openssl
# tools/pip_install.py is used to pin packages to a known working version
# except in tests where the environment variable CERTBOT_NO_PIN is set.
# virtualenv is listed here explicitly to make sure it is upgraded when

View File

@@ -18,7 +18,6 @@ Authors
* [Alex Zorin](https://github.com/alexzorin)
* [Amjad Mashaal](https://github.com/TheNavigat)
* [Andrew Murray](https://github.com/radarhere)
* [Andrzej Górski](https://github.com/andrzej3393)
* [Anselm Levskaya](https://github.com/levskaya)
* [Antoine Jacoutot](https://github.com/ajacoutot)
* [asaph](https://github.com/asaph)
@@ -128,7 +127,6 @@ Authors
* [Joubin Jabbari](https://github.com/joubin)
* [Juho Juopperi](https://github.com/jkjuopperi)
* [Kane York](https://github.com/riking)
* [Kenichi Maehashi](https://github.com/kmaehashi)
* [Kenneth Skovhede](https://github.com/kenkendk)
* [Kevin Burke](https://github.com/kevinburke)
* [Kevin London](https://github.com/kevinlondon)
@@ -167,7 +165,6 @@ Authors
* [Michael Watters](https://github.com/blackknight36)
* [Michal Moravec](https://github.com/https://github.com/Majkl578)
* [Michal Papis](https://github.com/mpapis)
* [Mickaël Schoentgen](https://github.com/BoboTiG)
* [Minn Soe](https://github.com/MinnSoe)
* [Min RK](https://github.com/minrk)
* [Miquel Ruiz](https://github.com/miquelruiz)
@@ -231,7 +228,6 @@ Authors
* [Stavros Korokithakis](https://github.com/skorokithakis)
* [Stefan Weil](https://github.com/stweil)
* [Steve Desmond](https://github.com/stevedesmond-ca)
* [sydneyli](https://github.com/sydneyli)
* [Tan Jay Jun](https://github.com/jayjun)
* [Tapple Gao](https://github.com/tapple)
* [Telepenin Nikolay](https://github.com/telepenin)

View File

@@ -1 +0,0 @@
certbot/CHANGELOG.md

1769
CHANGELOG.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
include README.rst
include CHANGELOG.md
include CONTRIBUTING.md
include LICENSE.txt
include linter_plugin.py
recursive-include docs *
recursive-include examples *
recursive-include certbot/tests/testdata *
recursive-include tests *.py
include certbot/ssl-dhparams.pem

View File

@@ -1 +0,0 @@
certbot/README.rst

131
README.rst Normal file
View File

@@ -0,0 +1,131 @@
.. This file contains a series of comments that are used to include sections of this README in other files. Do not modify these comments unless you know what you are doing. tag:intro-begin
Certbot is part of EFFs effort to encrypt the entire Internet. Secure communication over the Web relies on HTTPS, which requires the use of a digital certificate that lets browsers verify the identity of web servers (e.g., is that really google.com?). Web servers obtain their certificates from trusted third parties called certificate authorities (CAs). Certbot is an easy-to-use client that fetches a certificate from Lets Encrypt—an open certificate authority launched by the EFF, Mozilla, and others—and deploys it to a web server.
Anyone who has gone through the trouble of setting up a secure website knows what a hassle getting and maintaining a certificate is. Certbot and Lets Encrypt can automate away the pain and let you turn on and manage HTTPS with simple commands. Using Certbot and Let's Encrypt is free, so theres no need to arrange payment.
How you use Certbot depends on the configuration of your web server. The best way to get started is to use our `interactive guide <https://certbot.eff.org>`_. It generates instructions based on your configuration settings. In most cases, youll need `root or administrator access <https://certbot.eff.org/faq/#does-certbot-require-root-administrator-privileges>`_ to your web server to run Certbot.
Certbot is meant to be run directly on your web server, not on your personal computer. If youre using a hosted service and dont have direct access to your web server, you might not be able to use Certbot. Check with your hosting provider for documentation about uploading certificates or using certificates issued by Lets Encrypt.
Certbot is a fully-featured, extensible client for the Let's
Encrypt CA (or any other CA that speaks the `ACME
<https://github.com/ietf-wg-acme/acme/blob/master/draft-ietf-acme-acme.md>`_
protocol) that can automate the tasks of obtaining certificates and
configuring webservers to use them. This client runs on Unix-based operating
systems.
To see the changes made to Certbot between versions please refer to our
`changelog <https://github.com/certbot/certbot/blob/master/CHANGELOG.md>`_.
Until May 2016, Certbot was named simply ``letsencrypt`` or ``letsencrypt-auto``,
depending on install method. Instructions on the Internet, and some pieces of the
software, may still refer to this older name.
Contributing
------------
If you'd like to contribute to this project please read `Developer Guide
<https://certbot.eff.org/docs/contributing.html>`_.
This project is governed by `EFF's Public Projects Code of Conduct <https://www.eff.org/pages/eppcode>`_.
.. _installation:
How to run the client
---------------------
The easiest way to install and run Certbot is by visiting `certbot.eff.org`_,
where you can find the correct instructions for many web server and OS
combinations. For more information, see `Get Certbot
<https://certbot.eff.org/docs/install.html>`_.
.. _certbot.eff.org: https://certbot.eff.org/
Understanding the client in more depth
--------------------------------------
To understand what the client is doing in detail, it's important to
understand the way it uses plugins. Please see the `explanation of
plugins <https://certbot.eff.org/docs/using.html#plugins>`_ in
the User Guide.
Links
=====
.. Do not modify this comment unless you know what you're doing. tag:links-begin
Documentation: https://certbot.eff.org/docs
Software project: https://github.com/certbot/certbot
Notes for developers: https://certbot.eff.org/docs/contributing.html
Main Website: https://certbot.eff.org
Let's Encrypt Website: https://letsencrypt.org
Community: https://community.letsencrypt.org
ACME spec: http://ietf-wg-acme.github.io/acme/
ACME working area in github: https://github.com/ietf-wg-acme/acme
|build-status| |coverage| |docs| |container|
.. |build-status| image:: https://travis-ci.com/certbot/certbot.svg?branch=master
:target: https://travis-ci.com/certbot/certbot
:alt: Travis CI status
.. |coverage| image:: https://codecov.io/gh/certbot/certbot/branch/master/graph/badge.svg
:target: https://codecov.io/gh/certbot/certbot
:alt: Coverage status
.. |docs| image:: https://readthedocs.org/projects/letsencrypt/badge/
:target: https://readthedocs.org/projects/letsencrypt/
:alt: Documentation 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
===================
See https://certbot.eff.org/docs/install.html#system-requirements.
.. Do not modify this comment unless you know what you're doing. tag:intro-end
.. Do not modify this comment unless you know what you're doing. tag:features-begin
Current Features
=====================
* Supports multiple web servers:
- apache/2.x
- nginx/0.8.48+
- webroot (adds files to webroot directories in order to prove control of
domains and obtain certs)
- standalone (runs its own simple webserver to prove you control a domain)
- other server software via `third party plugins <https://certbot.eff.org/docs/using.html#third-party-plugins>`_
* The private key is generated locally on your system.
* Can talk to the Let's Encrypt CA or optionally to other ACME
compliant services.
* Can get domain-validated (DV) certificates.
* Can revoke certificates.
* Adjustable RSA key bit-length (2048 (default), 4096, ...).
* Can optionally install a http -> https redirect, so your site effectively
runs https only (Apache only)
* Fully automated.
* Configuration changes are logged and can be reverted.
* Supports an interactive text UI, or can be driven entirely from the
command line.
* Free and Open Source Software, made with Python.
.. Do not modify this comment unless you know what you're doing. tag:features-end
For extensive documentation on using and contributing to Certbot, go to https://certbot.eff.org/docs. If you would like to contribute to the project or run the latest code from git, you should read our `developer guide <https://certbot.eff.org/docs/contributing.html>`_.

View File

@@ -21,3 +21,30 @@ for mod in list(sys.modules):
# preserved (acme.jose.* is josepy.*)
if mod == 'josepy' or mod.startswith('josepy.'):
sys.modules['acme.' + mod.replace('josepy', 'jose', 1)] = sys.modules[mod]
# This class takes a similar approach to the cryptography project to deprecate attributes
# in public modules. See the _ModuleWithDeprecation class here:
# https://github.com/pyca/cryptography/blob/91105952739442a74582d3e62b3d2111365b0dc7/src/cryptography/utils.py#L129
class _TLSSNI01DeprecationModule(object):
"""
Internal class delegating to a module, and displaying warnings when
attributes related to TLS-SNI-01 are accessed.
"""
def __init__(self, module):
self.__dict__['_module'] = module
def __getattr__(self, attr):
if 'TLSSNI01' in attr:
warnings.warn('{0} attribute is deprecated, and will be removed soon.'.format(attr),
DeprecationWarning, stacklevel=2)
return getattr(self._module, attr)
def __setattr__(self, attr, value): # pragma: no cover
setattr(self._module, attr, value)
def __delattr__(self, attr): # pragma: no cover
delattr(self._module, attr)
def __dir__(self): # pragma: no cover
return ['_module'] + dir(self._module)

View File

@@ -3,13 +3,19 @@ import abc
import functools
import hashlib
import logging
import socket
import sys
from cryptography.hazmat.primitives import hashes # type: ignore
import josepy as jose
import OpenSSL
import requests
import six
from acme import errors
from acme import crypto_util
from acme import fields
from acme import _TLSSNI01DeprecationModule
logger = logging.getLogger(__name__)
@@ -231,7 +237,7 @@ class DNS01Response(KeyAuthorizationChallengeResponse):
return verified
@Challenge.register
@Challenge.register # pylint: disable=too-many-ancestors
class DNS01(KeyAuthorizationChallenge):
"""ACME dns-01 challenge."""
response_cls = DNS01Response
@@ -321,7 +327,7 @@ class HTTP01Response(KeyAuthorizationChallengeResponse):
return True
@Challenge.register
@Challenge.register # pylint: disable=too-many-ancestors
class HTTP01(KeyAuthorizationChallenge):
"""ACME http-01 challenge."""
response_cls = HTTP01Response
@@ -361,6 +367,148 @@ class HTTP01(KeyAuthorizationChallenge):
return self.key_authorization(account_key)
@ChallengeResponse.register
class TLSSNI01Response(KeyAuthorizationChallengeResponse):
"""ACME tls-sni-01 challenge response."""
typ = "tls-sni-01"
DOMAIN_SUFFIX = b".acme.invalid"
"""Domain name suffix."""
PORT = 443
"""Verification port as defined by the protocol.
You can override it (e.g. for testing) by passing ``port`` to
`simple_verify`.
"""
@property
def z(self): # pylint: disable=invalid-name
"""``z`` value used for verification.
:rtype bytes:
"""
return hashlib.sha256(
self.key_authorization.encode("utf-8")).hexdigest().lower().encode()
@property
def z_domain(self):
"""Domain name used for verification, generated from `z`.
:rtype bytes:
"""
return self.z[:32] + b'.' + self.z[32:] + self.DOMAIN_SUFFIX
def gen_cert(self, key=None, bits=2048):
"""Generate tls-sni-01 certificate.
:param OpenSSL.crypto.PKey key: Optional private key used in
certificate generation. If not provided (``None``), then
fresh key will be generated.
:param int bits: Number of bits for newly generated key.
:rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey`
"""
if key is None:
key = OpenSSL.crypto.PKey()
key.generate_key(OpenSSL.crypto.TYPE_RSA, bits)
return crypto_util.gen_ss_cert(key, [
# z_domain is too big to fit into CN, hence first dummy domain
'dummy', self.z_domain.decode()], force_san=True), key
def probe_cert(self, domain, **kwargs):
"""Probe tls-sni-01 challenge certificate.
:param unicode domain:
"""
# TODO: domain is not necessary if host is provided
if "host" not in kwargs:
host = socket.gethostbyname(domain)
logger.debug('%s resolved to %s', domain, host)
kwargs["host"] = host
kwargs.setdefault("port", self.PORT)
kwargs["name"] = self.z_domain
# TODO: try different methods?
return crypto_util.probe_sni(**kwargs)
def verify_cert(self, cert):
"""Verify tls-sni-01 challenge certificate.
:param OpensSSL.crypto.X509 cert: Challenge certificate.
:returns: Whether the certificate was successfully verified.
:rtype: bool
"""
# pylint: disable=protected-access
sans = crypto_util._pyopenssl_cert_or_req_san(cert)
logger.debug('Certificate %s. SANs: %s', cert.digest('sha256'), sans)
return self.z_domain.decode() in sans
def simple_verify(self, chall, domain, account_public_key,
cert=None, **kwargs):
"""Simple verify.
Verify ``validation`` using ``account_public_key``, optionally
probe tls-sni-01 certificate and check using `verify_cert`.
:param .challenges.TLSSNI01 chall: Corresponding challenge.
:param str domain: Domain name being validated.
:param JWK account_public_key:
:param OpenSSL.crypto.X509 cert: Optional certificate. If not
provided (``None``) certificate will be retrieved using
`probe_cert`.
:param int port: Port used to probe the certificate.
:returns: ``True`` iff client's control of the domain has been
verified.
:rtype: bool
"""
if not self.verify(chall, account_public_key):
logger.debug("Verification of key authorization in response failed")
return False
if cert is None:
try:
cert = self.probe_cert(domain=domain, **kwargs)
except errors.Error as error:
logger.debug(str(error), exc_info=True)
return False
return self.verify_cert(cert)
@Challenge.register # pylint: disable=too-many-ancestors
class TLSSNI01(KeyAuthorizationChallenge):
"""ACME tls-sni-01 challenge."""
response_cls = TLSSNI01Response
typ = response_cls.typ
# boulder#962, ietf-wg-acme#22
#n = jose.Field("n", encoder=int, decoder=int)
def validation(self, account_key, **kwargs):
"""Generate validation.
:param JWK account_key:
:param OpenSSL.crypto.PKey cert_key: Optional private key used
in certificate generation. If not provided (``None``), then
fresh key will be generated.
:rtype: `tuple` of `OpenSSL.crypto.X509` and `OpenSSL.crypto.PKey`
"""
return self.response(account_key).gen_cert(key=kwargs.get('cert_key'))
@ChallengeResponse.register
class TLSALPN01Response(KeyAuthorizationChallengeResponse):
"""ACME TLS-ALPN-01 challenge response.
@@ -372,7 +520,7 @@ class TLSALPN01Response(KeyAuthorizationChallengeResponse):
typ = "tls-alpn-01"
@Challenge.register
@Challenge.register # pylint: disable=too-many-ancestors
class TLSALPN01(KeyAuthorizationChallenge):
"""ACME tls-alpn-01 challenge.
@@ -469,3 +617,7 @@ class DNSResponse(ChallengeResponse):
"""
return chall.check_validation(self.validation, account_public_key)
# Patching ourselves to warn about TLS-SNI challenge deprecation and removal.
sys.modules[__name__] = _TLSSNI01DeprecationModule(sys.modules[__name__])

View File

@@ -3,10 +3,12 @@ import unittest
import josepy as jose
import mock
import OpenSSL
import requests
from six.moves.urllib import parse as urllib_parse # pylint: disable=relative-import
from acme import errors
from acme import test_util
CERT = test_util.load_comparable_cert('cert.pem')
@@ -75,6 +77,7 @@ class KeyAuthorizationChallengeResponseTest(unittest.TestCase):
class DNS01ResponseTest(unittest.TestCase):
# pylint: disable=too-many-instance-attributes
def setUp(self):
from acme.challenges import DNS01Response
@@ -146,6 +149,7 @@ class DNS01Test(unittest.TestCase):
class HTTP01ResponseTest(unittest.TestCase):
# pylint: disable=too-many-instance-attributes
def setUp(self):
from acme.challenges import HTTP01Response
@@ -255,7 +259,152 @@ class HTTP01Test(unittest.TestCase):
self.msg.update(token=b'..').good_token)
class TLSSNI01ResponseTest(unittest.TestCase):
# pylint: disable=too-many-instance-attributes
def setUp(self):
from acme.challenges import TLSSNI01
self.chall = TLSSNI01(
token=jose.b64decode(b'a82d5ff8ef740d12881f6d3c2277ab2e'))
self.response = self.chall.response(KEY)
self.jmsg = {
'resource': 'challenge',
'type': 'tls-sni-01',
'keyAuthorization': self.response.key_authorization,
}
# pylint: disable=invalid-name
label1 = b'dc38d9c3fa1a4fdcc3a5501f2d38583f'
label2 = b'b7793728f084394f2a1afd459556bb5c'
self.z = label1 + label2
self.z_domain = label1 + b'.' + label2 + b'.acme.invalid'
self.domain = 'foo.com'
def test_z_and_domain(self):
self.assertEqual(self.z, self.response.z)
self.assertEqual(self.z_domain, self.response.z_domain)
def test_to_partial_json(self):
self.assertEqual({k: v for k, v in self.jmsg.items() if k != 'keyAuthorization'},
self.response.to_partial_json())
def test_from_json(self):
from acme.challenges import TLSSNI01Response
self.assertEqual(self.response, TLSSNI01Response.from_json(self.jmsg))
def test_from_json_hashable(self):
from acme.challenges import TLSSNI01Response
hash(TLSSNI01Response.from_json(self.jmsg))
@mock.patch('acme.challenges.socket.gethostbyname')
@mock.patch('acme.challenges.crypto_util.probe_sni')
def test_probe_cert(self, mock_probe_sni, mock_gethostbyname):
mock_gethostbyname.return_value = '127.0.0.1'
self.response.probe_cert('foo.com')
mock_gethostbyname.assert_called_once_with('foo.com')
mock_probe_sni.assert_called_once_with(
host='127.0.0.1', port=self.response.PORT,
name=self.z_domain)
self.response.probe_cert('foo.com', host='8.8.8.8')
mock_probe_sni.assert_called_with(
host='8.8.8.8', port=mock.ANY, name=mock.ANY)
self.response.probe_cert('foo.com', port=1234)
mock_probe_sni.assert_called_with(
host=mock.ANY, port=1234, name=mock.ANY)
self.response.probe_cert('foo.com', bar='baz')
mock_probe_sni.assert_called_with(
host=mock.ANY, port=mock.ANY, name=mock.ANY, bar='baz')
self.response.probe_cert('foo.com', name=b'xxx')
mock_probe_sni.assert_called_with(
host=mock.ANY, port=mock.ANY,
name=self.z_domain)
def test_gen_verify_cert(self):
key1 = test_util.load_pyopenssl_private_key('rsa512_key.pem')
cert, key2 = self.response.gen_cert(key1)
self.assertEqual(key1, key2)
self.assertTrue(self.response.verify_cert(cert))
def test_gen_verify_cert_gen_key(self):
cert, key = self.response.gen_cert()
self.assertTrue(isinstance(key, OpenSSL.crypto.PKey))
self.assertTrue(self.response.verify_cert(cert))
def test_verify_bad_cert(self):
self.assertFalse(self.response.verify_cert(
test_util.load_cert('cert.pem')))
def test_simple_verify_bad_key_authorization(self):
key2 = jose.JWKRSA.load(test_util.load_vector('rsa256_key.pem'))
self.response.simple_verify(self.chall, "local", key2.public_key())
@mock.patch('acme.challenges.TLSSNI01Response.verify_cert', autospec=True)
def test_simple_verify(self, mock_verify_cert):
mock_verify_cert.return_value = mock.sentinel.verification
self.assertEqual(
mock.sentinel.verification, self.response.simple_verify(
self.chall, self.domain, KEY.public_key(),
cert=mock.sentinel.cert))
mock_verify_cert.assert_called_once_with(
self.response, mock.sentinel.cert)
@mock.patch('acme.challenges.TLSSNI01Response.probe_cert')
def test_simple_verify_false_on_probe_error(self, mock_probe_cert):
mock_probe_cert.side_effect = errors.Error
self.assertFalse(self.response.simple_verify(
self.chall, self.domain, KEY.public_key()))
class TLSSNI01Test(unittest.TestCase):
def setUp(self):
self.jmsg = {
'type': 'tls-sni-01',
'token': 'a82d5ff8ef740d12881f6d3c2277ab2e',
}
from acme.challenges import TLSSNI01
self.msg = TLSSNI01(
token=jose.b64decode('a82d5ff8ef740d12881f6d3c2277ab2e'))
def test_to_partial_json(self):
self.assertEqual(self.jmsg, self.msg.to_partial_json())
def test_from_json(self):
from acme.challenges import TLSSNI01
self.assertEqual(self.msg, TLSSNI01.from_json(self.jmsg))
def test_from_json_hashable(self):
from acme.challenges import TLSSNI01
hash(TLSSNI01.from_json(self.jmsg))
def test_from_json_invalid_token_length(self):
from acme.challenges import TLSSNI01
self.jmsg['token'] = jose.encode_b64jose(b'abcd')
self.assertRaises(
jose.DeserializationError, TLSSNI01.from_json, self.jmsg)
@mock.patch('acme.challenges.TLSSNI01Response.gen_cert')
def test_validation(self, mock_gen_cert):
mock_gen_cert.return_value = ('cert', 'key')
self.assertEqual(('cert', 'key'), self.msg.validation(
KEY, cert_key=mock.sentinel.cert_key))
mock_gen_cert.assert_called_once_with(key=mock.sentinel.cert_key)
def test_deprecation_message(self):
with mock.patch('acme.warnings.warn') as mock_warn:
from acme.challenges import TLSSNI01
assert TLSSNI01
self.assertEqual(mock_warn.call_count, 1)
self.assertTrue('deprecated' in mock_warn.call_args[0][0])
class TLSALPN01ResponseTest(unittest.TestCase):
# pylint: disable=too-many-instance-attributes
def setUp(self):
from acme.challenges import TLSALPN01Response

View File

@@ -44,7 +44,7 @@ DEFAULT_NETWORK_TIMEOUT = 45
DER_CONTENT_TYPE = 'application/pkix-cert'
class ClientBase(object):
class ClientBase(object): # pylint: disable=too-many-instance-attributes
"""ACME client base object.
:ivar messages.Directory directory:
@@ -136,8 +136,7 @@ class ClientBase(object):
"""
body = messages.UpdateAuthorization(status='deactivated')
response = self._post(authzr.uri, body)
return self._authzr_from_response(response,
authzr.body.identifier, authzr.uri)
return self._authzr_from_response(response)
def _authzr_from_response(self, response, identifier=None, uri=None):
authzr = messages.AuthorizationResource(
@@ -254,6 +253,7 @@ class Client(ClientBase):
URI from which the resource will be downloaded.
"""
# pylint: disable=too-many-arguments
self.key = key
if net is None:
net = ClientNetwork(key, alg=alg, verify_ssl=verify_ssl)
@@ -434,6 +434,7 @@ class Client(ClientBase):
was marked by the CA as invalid
"""
# pylint: disable=too-many-locals
assert max_attempts > 0
attempts = collections.defaultdict(int) # type: Dict[messages.AuthorizationResource, int]
exhausted = set()
@@ -945,7 +946,7 @@ class BackwardsCompatibleClientV2(object):
return self.client.external_account_required()
class ClientNetwork(object):
class ClientNetwork(object): # pylint: disable=too-many-instance-attributes
"""Wrapper around requests that signs POSTs for authentication.
Also adds user agent, and handles Content-Type.
@@ -971,6 +972,7 @@ class ClientNetwork(object):
def __init__(self, key, account=None, alg=jose.RS256, verify_ssl=True,
user_agent='acme-python', timeout=DEFAULT_NETWORK_TIMEOUT,
source_address=None):
# pylint: disable=too-many-arguments
self.key = key
self.account = account
self.alg = alg
@@ -1078,6 +1080,7 @@ class ClientNetwork(object):
return response
def _send_request(self, method, url, *args, **kwargs):
# pylint: disable=too-many-locals
"""Send HTTP request.
Makes sure that `verify_ssl` is respected. Logs request and

View File

@@ -318,6 +318,7 @@ class BackwardsCompatibleClientV2Test(ClientTestBase):
class ClientTest(ClientTestBase):
"""Tests for acme.client.Client."""
# pylint: disable=too-many-instance-attributes,too-many-public-methods
def setUp(self):
super(ClientTest, self).setUp()
@@ -887,7 +888,7 @@ class ClientV2Test(ClientTestBase):
new_nonce_url='https://www.letsencrypt-demo.org/acme/new-nonce')
self.client.net.get.assert_not_called()
class FakeError(messages.Error):
class FakeError(messages.Error): # pylint: disable=too-many-ancestors
"""Fake error to reproduce a malformed request ACME error"""
def __init__(self): # pylint: disable=super-init-not-called
pass
@@ -916,6 +917,7 @@ class MockJSONDeSerializable(jose.JSONDeSerializable):
class ClientNetworkTest(unittest.TestCase):
"""Tests for acme.client.ClientNetwork."""
# pylint: disable=too-many-public-methods
def setUp(self):
self.verify_ssl = mock.MagicMock()
@@ -1121,6 +1123,7 @@ class ClientNetworkTest(unittest.TestCase):
class ClientNetworkWithMockedResponseTest(unittest.TestCase):
"""Tests for acme.client.ClientNetwork which mock out response."""
# pylint: disable=too-many-instance-attributes
def setUp(self):
from acme.client import ClientNetwork

View File

@@ -28,7 +28,7 @@ logger = logging.getLogger(__name__)
_DEFAULT_SSL_METHOD = SSL.SSLv23_METHOD # type: ignore
class SSLSocket(object):
class SSLSocket(object): # pylint: disable=too-few-public-methods
"""SSL wrapper for sockets.
:ivar socket sock: Original wrapped socket.
@@ -74,7 +74,7 @@ class SSLSocket(object):
class FakeConnection(object):
"""Fake OpenSSL.SSL.Connection."""
# pylint: disable=missing-docstring
# pylint: disable=too-few-public-methods,missing-docstring
def __init__(self, connection):
self._wrapped = connection

View File

@@ -30,6 +30,7 @@ class SSLSocketAndProbeSNITest(unittest.TestCase):
class _TestServer(socketserver.TCPServer):
# pylint: disable=too-few-public-methods
# six.moves.* | pylint: disable=attribute-defined-outside-init,no-init
def server_bind(self): # pylint: disable=missing-docstring

View File

@@ -43,7 +43,7 @@ class JWS(jose.JWS):
__slots__ = jose.JWS._orig_slots # pylint: disable=no-member
@classmethod
# pylint: disable=arguments-differ
# pylint: disable=arguments-differ,too-many-arguments
def sign(cls, payload, key, alg, nonce, url=None, kid=None):
# Per ACME spec, jwk and kid are mutually exclusive, so only include a
# jwk field if kid is not provided.

View File

@@ -1,23 +1,29 @@
"""Support for standalone client challenge solvers. """
import argparse
import collections
import functools
import logging
import os
import socket
import sys
import threading
from six.moves import BaseHTTPServer # type: ignore # pylint: disable=import-error
from six.moves import http_client # pylint: disable=import-error
from six.moves import socketserver # type: ignore # pylint: disable=import-error
import OpenSSL
from acme import challenges
from acme import crypto_util
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
from acme import _TLSSNI01DeprecationModule
logger = logging.getLogger(__name__)
# six.moves.* | pylint: disable=no-member,attribute-defined-outside-init
# pylint: disable=no-init
# pylint: disable=too-few-public-methods,no-init
class TLSServer(socketserver.TCPServer):
@@ -126,6 +132,35 @@ class BaseDualNetworkedServers(object):
self.threads = []
class TLSSNI01Server(TLSServer, ACMEServerMixin):
"""TLSSNI01 Server."""
def __init__(self, server_address, certs, ipv6=False):
TLSServer.__init__(
self, server_address, BaseRequestHandlerWithLogging, certs=certs, ipv6=ipv6)
class TLSSNI01DualNetworkedServers(BaseDualNetworkedServers):
"""TLSSNI01Server Wrapper. Tries everything for both. Failures for one don't
affect the other."""
def __init__(self, *args, **kwargs):
BaseDualNetworkedServers.__init__(self, TLSSNI01Server, *args, **kwargs)
class BaseRequestHandlerWithLogging(socketserver.BaseRequestHandler):
"""BaseRequestHandler with logging."""
def log_message(self, format, *args): # pylint: disable=redefined-builtin
"""Log arbitrary message."""
logger.debug("%s - - %s", self.client_address[0], format % args)
def handle(self):
"""Handle request."""
self.log_message("Incoming request")
socketserver.BaseRequestHandler.handle(self)
class HTTPServer(BaseHTTPServer.HTTPServer):
"""Generic HTTP Server."""
@@ -228,3 +263,43 @@ class HTTP01RequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
"""
return functools.partial(
cls, simple_http_resources=simple_http_resources)
def simple_tls_sni_01_server(cli_args, forever=True):
"""Run simple standalone TLSSNI01 server."""
logging.basicConfig(level=logging.DEBUG)
parser = argparse.ArgumentParser()
parser.add_argument(
"-p", "--port", default=0, help="Port to serve at. By default "
"picks random free port.")
args = parser.parse_args(cli_args[1:])
certs = {}
_, hosts, _ = next(os.walk('.')) # type: ignore # https://github.com/python/mypy/issues/465
for host in hosts:
with open(os.path.join(host, "cert.pem")) as cert_file:
cert_contents = cert_file.read()
with open(os.path.join(host, "key.pem")) as key_file:
key_contents = key_file.read()
certs[host.encode()] = (
OpenSSL.crypto.load_privatekey(
OpenSSL.crypto.FILETYPE_PEM, key_contents),
OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert_contents))
server = TLSSNI01Server(('', int(args.port)), certs=certs)
logger.info("Serving at https://%s:%s...", *server.socket.getsockname()[:2])
if forever: # pragma: no cover
server.serve_forever()
else:
server.handle_request()
# Patching ourselves to warn about TLS-SNI challenge deprecation and removal.
sys.modules[__name__] = _TLSSNI01DeprecationModule(sys.modules[__name__])
if __name__ == "__main__":
sys.exit(simple_tls_sni_01_server(sys.argv)) # pragma: no cover

View File

@@ -1,7 +1,13 @@
"""Tests for acme.standalone."""
import multiprocessing
import os
import shutil
import socket
import threading
import tempfile
import unittest
import time
from contextlib import closing
from six.moves import http_client # pylint: disable=import-error
from six.moves import socketserver # type: ignore # pylint: disable=import-error
@@ -11,6 +17,8 @@ import mock
import requests
from acme import challenges
from acme import crypto_util
from acme import errors
from acme import test_util
from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module
@@ -33,6 +41,32 @@ class TLSServerTest(unittest.TestCase):
server.server_close()
class TLSSNI01ServerTest(unittest.TestCase):
"""Test for acme.standalone.TLSSNI01Server."""
def setUp(self):
self.certs = {b'localhost': (
test_util.load_pyopenssl_private_key('rsa2048_key.pem'),
test_util.load_cert('rsa2048_cert.pem'),
)}
from acme.standalone import TLSSNI01Server
self.server = TLSSNI01Server(('localhost', 0), certs=self.certs)
self.thread = threading.Thread(target=self.server.serve_forever)
self.thread.start()
def tearDown(self):
self.server.shutdown()
self.thread.join()
def test_it(self):
host, port = self.server.socket.getsockname()[:2]
cert = crypto_util.probe_sni(
b'localhost', host=host, port=port, timeout=1)
self.assertEqual(jose.ComparableX509(cert),
jose.ComparableX509(self.certs[b'localhost'][1]))
class HTTP01ServerTest(unittest.TestCase):
"""Tests for acme.standalone.HTTP01Server."""
@@ -136,6 +170,33 @@ class BaseDualNetworkedServersTest(unittest.TestCase):
prev_port = port
class TLSSNI01DualNetworkedServersTest(unittest.TestCase):
"""Test for acme.standalone.TLSSNI01DualNetworkedServers."""
def setUp(self):
self.certs = {b'localhost': (
test_util.load_pyopenssl_private_key('rsa2048_key.pem'),
test_util.load_cert('rsa2048_cert.pem'),
)}
from acme.standalone import TLSSNI01DualNetworkedServers
self.servers = TLSSNI01DualNetworkedServers(('localhost', 0), certs=self.certs)
self.servers.serve_forever()
def tearDown(self):
self.servers.shutdown_and_server_close()
def test_connect(self):
socknames = self.servers.getsocknames()
# connect to all addresses
for sockname in socknames:
host, port = sockname[:2]
cert = crypto_util.probe_sni(
b'localhost', host=host, port=port, timeout=1)
self.assertEqual(jose.ComparableX509(cert),
jose.ComparableX509(self.certs[b'localhost'][1]))
class HTTP01DualNetworkedServersTest(unittest.TestCase):
"""Tests for acme.standalone.HTTP01DualNetworkedServers."""
@@ -186,5 +247,60 @@ class HTTP01DualNetworkedServersTest(unittest.TestCase):
self.assertFalse(self._test_http01(add=False))
class TestSimpleTLSSNI01Server(unittest.TestCase):
"""Tests for acme.standalone.simple_tls_sni_01_server."""
def setUp(self):
# mirror ../examples/standalone
self.test_cwd = tempfile.mkdtemp()
localhost_dir = os.path.join(self.test_cwd, 'localhost')
os.makedirs(localhost_dir)
shutil.copy(test_util.vector_path('rsa2048_cert.pem'),
os.path.join(localhost_dir, 'cert.pem'))
shutil.copy(test_util.vector_path('rsa2048_key.pem'),
os.path.join(localhost_dir, 'key.pem'))
with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock:
sock.bind(('', 0))
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.port = sock.getsockname()[1]
from acme.standalone import simple_tls_sni_01_server
self.process = multiprocessing.Process(target=simple_tls_sni_01_server,
args=(['path', '-p', str(self.port)],))
self.old_cwd = os.getcwd()
os.chdir(self.test_cwd)
def tearDown(self):
os.chdir(self.old_cwd)
if self.process.is_alive():
self.process.terminate()
self.process.join(timeout=5)
# Check that we didn't timeout waiting for the process to
# terminate.
self.assertNotEqual(self.process.exitcode, None)
shutil.rmtree(self.test_cwd)
@mock.patch('acme.standalone.TLSSNI01Server.handle_request')
def test_mock(self, handle):
from acme.standalone import simple_tls_sni_01_server
simple_tls_sni_01_server(cli_args=['path', '-p', str(self.port)], forever=False)
self.assertEqual(handle.call_count, 1)
def test_live(self):
self.process.start()
cert = None
for _ in range(50):
time.sleep(0.1)
try:
cert = crypto_util.probe_sni(b'localhost', b'127.0.0.1', self.port)
break
except errors.Error: # pragma: no cover
pass
self.assertEqual(jose.ComparableX509(cert),
test_util.load_comparable_cert('rsa2048_cert.pem'))
if __name__ == "__main__":
unittest.main() # pragma: no cover

View File

@@ -4,6 +4,7 @@
"""
import os
import unittest
import pkg_resources
from cryptography.hazmat.backends import default_backend
@@ -12,6 +13,12 @@ import josepy as jose
from OpenSSL import crypto
def vector_path(*names):
"""Path to a test vector."""
return pkg_resources.resource_filename(
__name__, os.path.join('testdata', *names))
def load_vector(*names):
"""Load contents of a test vector."""
# luckily, resource_string opens file in binary mode
@@ -66,3 +73,23 @@ def load_pyopenssl_private_key(*names):
loader = _guess_loader(
names[-1], crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1)
return crypto.load_privatekey(loader, load_vector(*names))
def skip_unless(condition, reason): # pragma: no cover
"""Skip tests unless a condition holds.
This implements the basic functionality of unittest.skipUnless
which is only available on Python 2.7+.
:param bool condition: If ``False``, the test will be skipped
:param str reason: the reason for skipping the test
:rtype: callable
:returns: decorator that hides tests unless condition is ``True``
"""
if hasattr(unittest, "skipUnless"):
return unittest.skipUnless(condition, reason)
elif condition:
return lambda cls: cls
return lambda cls: None

View File

@@ -1,10 +1,10 @@
# readthedocs.org gives no way to change the install command to "pip
# install -e acme[docs]" (that would in turn install documentation
# install -e .[docs]" (that would in turn install documentation
# dependencies), but it allows to specify a requirements.txt file at
# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259)
# Although ReadTheDocs certainly doesn't need to install the project
# in --editable mode (-e), just "pip install acme[docs]" does not work as
# expected and "pip install -e acme[docs]" must be used instead
# in --editable mode (-e), just "pip install .[docs]" does not work as
# expected and "pip install -e .[docs]" must be used instead
-e acme[docs]

View File

@@ -3,7 +3,7 @@ from setuptools import find_packages
from setuptools.command.test import test as TestCommand
import sys
version = '1.0.0.dev0'
version = '0.39.0.dev0'
# Please update tox.ini when modifying dependency version requirements
install_requires = [

47
appveyor.yml Normal file
View File

@@ -0,0 +1,47 @@
image: Visual Studio 2015
environment:
matrix:
- TOXENV: py35
- TOXENV: py37-cover
- TOXENV: integration-certbot
branches:
only:
# apache-parser-v2 is a temporary branch for doing work related to
# rewriting the parser in the Apache plugin.
- apache-parser-v2
- master
- /^\d+\.\d+\.x$/ # Version branches like X.X.X
- /^test-.*$/
init:
# Since master can receive only commits from PR that have already been tested, following
# condition avoid to launch all jobs except the coverage one for commits pushed to master.
- ps: |
if (-Not $Env:APPVEYOR_PULL_REQUEST_NUMBER -And $Env:APPVEYOR_REPO_BRANCH -Eq 'master' `
-And -Not ($Env:TOXENV -Like '*-cover'))
{ $Env:APPVEYOR_SKIP_FINALIZE_ON_EXIT = 'true'; Exit-AppVeyorBuild }
install:
# Use Python 3.7 by default
- SET PATH=C:\\Python37;C:\\Python37\\Scripts;%PATH%
# Using 4 processes is proven to be the most efficient integration tests config for AppVeyor
- IF %TOXENV%==integration-certbot SET PYTEST_ADDOPTS=--numprocesses=4
# Check env
- python --version
# Upgrade pip to avoid warnings
- python -m pip install --upgrade pip
# Ready to install tox and coverage
# tools/pip_install.py is used to pin packages to a known working version.
- python tools\\pip_install.py tox codecov
build: off
test_script:
- set TOX_TESTENV_PASSENV=APPVEYOR
# Test env is set by TOXENV env variable
- tox
on_success:
- if exist .coverage codecov -F windows

View File

@@ -1,6 +1,7 @@
include LICENSE.txt
include README.rst
recursive-include docs *
recursive-include certbot_apache/tests/testdata *
include certbot_apache/_internal/centos-options-ssl-apache.conf
include certbot_apache/_internal/options-ssl-apache.conf
recursive-include certbot_apache/_internal/augeas_lens *.aug
include certbot_apache/centos-options-ssl-apache.conf
include certbot_apache/options-ssl-apache.conf
recursive-include certbot_apache/augeas_lens *.aug

View File

@@ -1 +0,0 @@
"""Certbot Apache plugin."""

View File

@@ -29,12 +29,12 @@ from certbot.plugins import common
from certbot.plugins.util import path_surgery
from certbot.plugins.enhancements import AutoHSTSEnhancement
from certbot_apache._internal import apache_util
from certbot_apache._internal import constants
from certbot_apache._internal import display_ops
from certbot_apache._internal import http_01
from certbot_apache._internal import obj
from certbot_apache._internal import parser
from certbot_apache import apache_util
from certbot_apache import constants
from certbot_apache import display_ops
from certbot_apache import http_01
from certbot_apache import obj
from certbot_apache import parser
logger = logging.getLogger(__name__)
@@ -71,17 +71,18 @@ logger = logging.getLogger(__name__)
@zope.interface.implementer(interfaces.IAuthenticator, interfaces.IInstaller)
@zope.interface.provider(interfaces.IPluginFactory)
class ApacheConfigurator(common.Installer):
# pylint: disable=too-many-instance-attributes,too-many-public-methods
"""Apache configurator.
:ivar config: Configuration.
:type config: :class:`~certbot.interfaces.IConfig`
:ivar parser: Handles low level parsing
:type parser: :class:`~certbot_apache._internal.parser`
:type parser: :class:`~certbot_apache.parser`
:ivar tup version: version of Apache
:ivar list vhosts: All vhosts found in the configuration
(:class:`list` of :class:`~certbot_apache._internal.obj.VirtualHost`)
(:class:`list` of :class:`~certbot_apache.obj.VirtualHost`)
:ivar dict assoc: Mapping between domains and vhosts
@@ -110,7 +111,7 @@ class ApacheConfigurator(common.Installer):
handle_sites=False,
challenge_location="/etc/apache2",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)
def option(self, key):
@@ -173,6 +174,8 @@ class ApacheConfigurator(common.Installer):
"(Only Ubuntu/Debian currently)")
add("ctl", default=DEFAULTS["ctl"],
help="Full path to Apache control script")
util.add_deprecated_argument(
add, argument_name="init-script", nargs=1)
def __init__(self, *args, **kwargs):
"""Initialize an Apache Configurator.
@@ -391,7 +394,7 @@ class ApacheConfigurator(common.Installer):
counterpart, should one get created
:returns: List of VirtualHosts or None
:rtype: `list` of :class:`~certbot_apache._internal.obj.VirtualHost`
:rtype: `list` of :class:`~certbot_apache.obj.VirtualHost`
"""
if self._wildcard_domain(domain):
@@ -566,7 +569,7 @@ class ApacheConfigurator(common.Installer):
counterpart, should one get created
:returns: vhost associated with name
:rtype: :class:`~certbot_apache._internal.obj.VirtualHost`
:rtype: :class:`~certbot_apache.obj.VirtualHost`
:raises .errors.PluginError: If no vhost is available or chosen
@@ -669,7 +672,7 @@ class ApacheConfigurator(common.Installer):
:param str target_name: domain handled by the desired vhost
:param vhosts: vhosts to consider
:type vhosts: `collections.Iterable` of :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhosts: `collections.Iterable` of :class:`~certbot_apache.obj.VirtualHost`
:param bool filter_defaults: whether a vhost with a _default_
addr is acceptable
@@ -811,7 +814,7 @@ class ApacheConfigurator(common.Installer):
"""Helper function for get_virtual_hosts().
:param host: In progress vhost whose names will be added
:type host: :class:`~certbot_apache._internal.obj.VirtualHost`
:type host: :class:`~certbot_apache.obj.VirtualHost`
"""
@@ -830,7 +833,7 @@ class ApacheConfigurator(common.Installer):
:param str path: Augeas path to virtual host
:returns: newly created vhost
:rtype: :class:`~certbot_apache._internal.obj.VirtualHost`
:rtype: :class:`~certbot_apache.obj.VirtualHost`
"""
addrs = set()
@@ -871,7 +874,7 @@ class ApacheConfigurator(common.Installer):
def get_virtual_hosts(self):
"""Returns list of virtual hosts found in the Apache configuration.
:returns: List of :class:`~certbot_apache._internal.obj.VirtualHost`
:returns: List of :class:`~certbot_apache.obj.VirtualHost`
objects found in configuration
:rtype: list
@@ -928,7 +931,7 @@ class ApacheConfigurator(common.Installer):
now NameVirtualHosts. If version is earlier than 2.4, check if addr
has a NameVirtualHost directive in the Apache config
:param certbot_apache._internal.obj.Addr target_addr: vhost address
:param certbot_apache.obj.Addr target_addr: vhost address
:returns: Success
:rtype: bool
@@ -946,7 +949,7 @@ class ApacheConfigurator(common.Installer):
"""Adds NameVirtualHost directive for given address.
:param addr: Address that will be added as NameVirtualHost directive
:type addr: :class:`~certbot_apache._internal.obj.Addr`
:type addr: :class:`~certbot_apache.obj.Addr`
"""
@@ -1115,7 +1118,7 @@ class ApacheConfigurator(common.Installer):
if "ssl_module" not in self.parser.modules:
self.enable_mod("ssl", temp=temp)
def make_vhost_ssl(self, nonssl_vhost):
def make_vhost_ssl(self, nonssl_vhost): # pylint: disable=too-many-locals
"""Makes an ssl_vhost version of a nonssl_vhost.
Duplicates vhost and adds default ssl options
@@ -1125,10 +1128,10 @@ class ApacheConfigurator(common.Installer):
.. note:: This function saves the configuration
:param nonssl_vhost: Valid VH that doesn't have SSLEngine on
:type nonssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type nonssl_vhost: :class:`~certbot_apache.obj.VirtualHost`
:returns: SSL vhost
:rtype: :class:`~certbot_apache._internal.obj.VirtualHost`
:rtype: :class:`~certbot_apache.obj.VirtualHost`
:raises .errors.PluginError: If more than one virtual host is in
the file or if plugin is unable to write/read vhost files.
@@ -1499,7 +1502,7 @@ class ApacheConfigurator(common.Installer):
https://httpd.apache.org/docs/2.2/mod/core.html#namevirtualhost
:param vhost: New virtual host that was recently created.
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
"""
need_to_save = False
@@ -1534,7 +1537,7 @@ class ApacheConfigurator(common.Installer):
:param str id_str: Id string for matching
:returns: The matched VirtualHost or None
:rtype: :class:`~certbot_apache._internal.obj.VirtualHost` or None
:rtype: :class:`~certbot_apache.obj.VirtualHost` or None
:raises .errors.PluginError: If no VirtualHost is found
"""
@@ -1551,7 +1554,7 @@ class ApacheConfigurator(common.Installer):
used for keeping track of VirtualHost directive over time.
:param vhost: Virtual host to add the id
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:returns: The unique ID or None
:rtype: str or None
@@ -1573,7 +1576,7 @@ class ApacheConfigurator(common.Installer):
If ID already exists, returns that instead.
:param vhost: Virtual host to add or find the id
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:returns: The unique ID for vhost
:rtype: str or None
@@ -1611,9 +1614,9 @@ class ApacheConfigurator(common.Installer):
:param str domain: domain to enhance
:param str enhancement: enhancement type defined in
:const:`~certbot.plugins.enhancements.ENHANCEMENTS`
:const:`~certbot.constants.ENHANCEMENTS`
:param options: options for the enhancement
See :const:`~certbot.plugins.enhancements.ENHANCEMENTS`
See :const:`~certbot.constants.ENHANCEMENTS`
documentation for appropriate parameter.
:raises .errors.PluginError: If Enhancement is not supported, or if
@@ -1651,7 +1654,7 @@ class ApacheConfigurator(common.Installer):
"""Increase the AutoHSTS max-age value
:param vhost: Virtual host object to modify
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:param str id_str: The unique ID string of VirtualHost
@@ -1735,13 +1738,13 @@ class ApacheConfigurator(common.Installer):
.. note:: This function saves the configuration
:param ssl_vhost: Destination of traffic, an ssl enabled vhost
:type ssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`
:param unused_options: Not currently used
:type unused_options: Not Available
:returns: Success, general_vhost (HTTP vhost)
:rtype: (bool, :class:`~certbot_apache._internal.obj.VirtualHost`)
:rtype: (bool, :class:`~certbot_apache.obj.VirtualHost`)
"""
min_apache_ver = (2, 3, 3)
@@ -1791,14 +1794,14 @@ class ApacheConfigurator(common.Installer):
.. note:: This function saves the configuration
:param ssl_vhost: Destination of traffic, an ssl enabled vhost
:type ssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`
:param header_substring: string that uniquely identifies a header.
e.g: Strict-Transport-Security, Upgrade-Insecure-Requests.
:type str
:returns: Success, general_vhost (HTTP vhost)
:rtype: (bool, :class:`~certbot_apache._internal.obj.VirtualHost`)
:rtype: (bool, :class:`~certbot_apache.obj.VirtualHost`)
:raises .errors.PluginError: If no viable HTTP host can be created or
set with header header_substring.
@@ -1826,7 +1829,7 @@ class ApacheConfigurator(common.Installer):
contains the string header_substring.
:param ssl_vhost: vhost to check
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:param header_substring: string that uniquely identifies a header.
e.g: Strict-Transport-Security, Upgrade-Insecure-Requests.
@@ -1863,7 +1866,7 @@ class ApacheConfigurator(common.Installer):
.. note:: This function saves the configuration
:param ssl_vhost: Destination of traffic, an ssl enabled vhost
:type ssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`
:param unused_options: Not currently used
:type unused_options: Not Available
@@ -1948,7 +1951,7 @@ class ApacheConfigurator(common.Installer):
delete certbot's old rewrite rules and set the new one instead.
:param vhost: vhost to check
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:raises errors.PluginEnhancementAlreadyPresent: When the exact
certbot redirection WriteRule exists in virtual host.
@@ -1990,7 +1993,7 @@ class ApacheConfigurator(common.Installer):
"""Checks if there exists a RewriteRule directive in vhost
:param vhost: vhost to check
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:returns: True if a RewriteRule directive exists.
:rtype: bool
@@ -2004,7 +2007,7 @@ class ApacheConfigurator(common.Installer):
"""Checks if a RewriteEngine directive is on
:param vhost: vhost to check
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
"""
rewrite_engine_path_list = self.parser.find_dir("RewriteEngine", "on",
@@ -2021,10 +2024,10 @@ class ApacheConfigurator(common.Installer):
"""Creates an http_vhost specifically to redirect for the ssl_vhost.
:param ssl_vhost: ssl vhost
:type ssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost`
:returns: tuple of the form
(`success`, :class:`~certbot_apache._internal.obj.VirtualHost`)
(`success`, :class:`~certbot_apache.obj.VirtualHost`)
:rtype: tuple
"""
@@ -2150,7 +2153,7 @@ class ApacheConfigurator(common.Installer):
of this method where available.
:param vhost: vhost to enable
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:raises .errors.NotSupportedError: If filesystem layout is not
supported.
@@ -2344,7 +2347,7 @@ class ApacheConfigurator(common.Installer):
Enable the AutoHSTS enhancement for defined domains
:param _unused_lineage: Certificate lineage object, unused
:type _unused_lineage: certbot._internal.storage.RenewableCert
:type _unused_lineage: certbot.storage.RenewableCert
:param domains: List of domains in certificate to enhance
:type domains: str
@@ -2387,7 +2390,7 @@ class ApacheConfigurator(common.Installer):
"""Do the initial AutoHSTS deployment to a vhost
:param ssl_vhost: The VirtualHost object to deploy the AutoHSTS
:type ssl_vhost: :class:`~certbot_apache._internal.obj.VirtualHost` or None
:type ssl_vhost: :class:`~certbot_apache.obj.VirtualHost` or None
:raises errors.PluginEnhancementAlreadyPresent: When already enhanced
@@ -2469,7 +2472,7 @@ class ApacheConfigurator(common.Installer):
and changes the HSTS max-age to a high value.
:param lineage: Certificate lineage object
:type lineage: certbot._internal.storage.RenewableCert
:type lineage: certbot.storage.RenewableCert
"""
self._autohsts_fetch_state()
if not self._autohsts:

View File

@@ -1,8 +1,6 @@
"""Apache plugin constants."""
import pkg_resources
from certbot.compat import os
MOD_SSL_CONF_DEST = "options-ssl-apache.conf"
"""Name of the mod_ssl config file as saved in `IConfig.config_dir`."""
@@ -29,7 +27,7 @@ ALL_SSL_OPTIONS_HASHES = [
"""SHA256 hashes of the contents of previous versions of all versions of MOD_SSL_CONF_SRC"""
AUGEAS_LENS_DIR = pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "augeas_lens"))
"certbot_apache", "augeas_lens")
"""Path to the Augeas lens directory"""
REWRITE_HTTPS_ARGS = [

View File

@@ -77,7 +77,7 @@ def _vhost_menu(domain, vhosts):
if free_chars < 2:
logger.debug("Display size is too small for "
"certbot_apache._internal.display_ops._vhost_menu()")
"certbot_apache.display_ops._vhost_menu()")
# This runs the edge off the screen, but it doesn't cause an "error"
filename_size = 1
disp_name_size = 1

View File

@@ -5,18 +5,17 @@ from distutils.version import LooseVersion # pylint: disable=no-name-in-module,
from certbot import util
from certbot_apache._internal import configurator
from certbot_apache._internal import override_arch
from certbot_apache._internal import override_fedora
from certbot_apache._internal import override_darwin
from certbot_apache._internal import override_debian
from certbot_apache._internal import override_centos
from certbot_apache._internal import override_gentoo
from certbot_apache._internal import override_suse
from certbot_apache import configurator
from certbot_apache import override_arch
from certbot_apache import override_fedora
from certbot_apache import override_darwin
from certbot_apache import override_debian
from certbot_apache import override_centos
from certbot_apache import override_gentoo
from certbot_apache import override_suse
OVERRIDE_CLASSES = {
"arch": override_arch.ArchConfigurator,
"cloudlinux": override_centos.CentOSConfigurator,
"darwin": override_darwin.DarwinConfigurator,
"debian": override_debian.DebianConfigurator,
"ubuntu": override_debian.DebianConfigurator,
@@ -24,10 +23,7 @@ OVERRIDE_CLASSES = {
"centos linux": override_centos.CentOSConfigurator,
"fedora_old": override_centos.CentOSConfigurator,
"fedora": override_fedora.FedoraConfigurator,
"linuxmint": override_debian.DebianConfigurator,
"ol": override_centos.CentOSConfigurator,
"oracle": override_centos.CentOSConfigurator,
"redhatenterpriseserver": override_centos.CentOSConfigurator,
"red hat enterprise linux server": override_centos.CentOSConfigurator,
"rhel": override_centos.CentOSConfigurator,
"amazon": override_centos.CentOSConfigurator,
@@ -35,7 +31,6 @@ OVERRIDE_CLASSES = {
"gentoo base system": override_gentoo.GentooConfigurator,
"opensuse": override_suse.OpenSUSEConfigurator,
"suse": override_suse.OpenSUSEConfigurator,
"sles": override_suse.OpenSUSEConfigurator,
"scientific": override_centos.CentOSConfigurator,
"scientific linux": override_centos.CentOSConfigurator,
}

View File

@@ -8,13 +8,13 @@ from certbot.compat import os
from certbot.compat import filesystem
from certbot.plugins import common
from certbot_apache._internal.obj import VirtualHost # pylint: disable=unused-import
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.obj import VirtualHost # pylint: disable=unused-import
from certbot_apache.parser import get_aug_path
logger = logging.getLogger(__name__)
class ApacheHttp01(common.ChallengePerformer):
class ApacheHttp01(common.TLSSNI01):
"""Class that performs HTTP-01 challenges within the Apache configurator."""
CONFIG_TEMPLATE22_PRE = """\

View File

@@ -24,7 +24,7 @@ class Addr(common.Addr):
return not self.__eq__(other)
def __repr__(self):
return "certbot_apache._internal.obj.Addr(" + repr(self.tup) + ")"
return "certbot_apache.obj.Addr(" + repr(self.tup) + ")"
def __hash__(self): # pylint: disable=useless-super-delegation
# Python 3 requires explicit overridden for __hash__ if __eq__ or
@@ -98,7 +98,7 @@ class Addr(common.Addr):
return self.get_addr_obj(port)
class VirtualHost(object):
class VirtualHost(object): # pylint: disable=too-few-public-methods
"""Represents an Apache Virtualhost.
:ivar str filep: file path of VH
@@ -126,6 +126,7 @@ class VirtualHost(object):
def __init__(self, filep, path, addrs, ssl, enabled, name=None,
aliases=None, modmacro=False, ancestor=None):
# pylint: disable=too-many-arguments
"""Initialize a VH."""
self.filep = filep
self.path = path

View File

@@ -4,9 +4,8 @@ import pkg_resources
import zope.interface
from certbot import interfaces
from certbot.compat import os
from certbot_apache._internal import configurator
from certbot_apache import configurator
@zope.interface.provider(interfaces.IPluginFactory)
class ArchConfigurator(configurator.ApacheConfigurator):
@@ -28,5 +27,5 @@ class ArchConfigurator(configurator.ApacheConfigurator):
handle_sites=False,
challenge_location="/etc/httpd/conf",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)

View File

@@ -7,14 +7,13 @@ import zope.interface
from certbot import errors
from certbot import interfaces
from certbot import util
from certbot.compat import os
from certbot.errors import MisconfigurationError
from acme.magic_typing import List # pylint: disable=unused-import, no-name-in-module
from certbot_apache._internal import apache_util
from certbot_apache._internal import configurator
from certbot_apache._internal import parser
from certbot_apache import apache_util
from certbot_apache import configurator
from certbot_apache import parser
logger = logging.getLogger(__name__)
@@ -41,7 +40,7 @@ class CentOSConfigurator(configurator.ApacheConfigurator):
handle_sites=False,
challenge_location="/etc/httpd/conf.d",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "centos-options-ssl-apache.conf"))
"certbot_apache", "centos-options-ssl-apache.conf")
)
def config_test(self):

View File

@@ -4,9 +4,8 @@ import pkg_resources
import zope.interface
from certbot import interfaces
from certbot.compat import os
from certbot_apache._internal import configurator
from certbot_apache import configurator
@zope.interface.provider(interfaces.IPluginFactory)
class DarwinConfigurator(configurator.ApacheConfigurator):
@@ -28,5 +27,5 @@ class DarwinConfigurator(configurator.ApacheConfigurator):
handle_sites=False,
challenge_location="/etc/apache2/other",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)

View File

@@ -10,8 +10,8 @@ from certbot import util
from certbot.compat import filesystem
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import configurator
from certbot_apache import apache_util
from certbot_apache import configurator
logger = logging.getLogger(__name__)
@@ -36,7 +36,7 @@ class DebianConfigurator(configurator.ApacheConfigurator):
handle_sites=True,
challenge_location="/etc/apache2",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)
def enable_site(self, vhost):
@@ -46,7 +46,7 @@ class DebianConfigurator(configurator.ApacheConfigurator):
modules are enabled appropriately.
:param vhost: vhost to enable
:type vhost: :class:`~certbot_apache._internal.obj.VirtualHost`
:type vhost: :class:`~certbot_apache.obj.VirtualHost`
:raises .errors.NotSupportedError: If filesystem layout is not
supported.

View File

@@ -5,11 +5,10 @@ import zope.interface
from certbot import errors
from certbot import interfaces
from certbot import util
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import configurator
from certbot_apache._internal import parser
from certbot_apache import apache_util
from certbot_apache import configurator
from certbot_apache import parser
@zope.interface.provider(interfaces.IPluginFactory)
@@ -34,7 +33,7 @@ class FedoraConfigurator(configurator.ApacheConfigurator):
challenge_location="/etc/httpd/conf.d",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
# TODO: eventually newest version of Fedora will need their own config
"certbot_apache", os.path.join("_internal", "centos-options-ssl-apache.conf"))
"certbot_apache", "centos-options-ssl-apache.conf")
)
def config_test(self):

View File

@@ -4,11 +4,10 @@ import pkg_resources
import zope.interface
from certbot import interfaces
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import configurator
from certbot_apache._internal import parser
from certbot_apache import apache_util
from certbot_apache import configurator
from certbot_apache import parser
@zope.interface.provider(interfaces.IPluginFactory)
class GentooConfigurator(configurator.ApacheConfigurator):
@@ -31,7 +30,7 @@ class GentooConfigurator(configurator.ApacheConfigurator):
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)
def _prepare_options(self):

View File

@@ -4,9 +4,8 @@ import pkg_resources
import zope.interface
from certbot import interfaces
from certbot.compat import os
from certbot_apache._internal import configurator
from certbot_apache import configurator
@zope.interface.provider(interfaces.IPluginFactory)
class OpenSUSEConfigurator(configurator.ApacheConfigurator):
@@ -28,5 +27,5 @@ class OpenSUSEConfigurator(configurator.ApacheConfigurator):
handle_sites=False,
challenge_location="/etc/apache2/vhosts.d",
MOD_SSL_CONF_SRC=pkg_resources.resource_filename(
"certbot_apache", os.path.join("_internal", "options-ssl-apache.conf"))
"certbot_apache", "options-ssl-apache.conf")
)

View File

@@ -13,12 +13,13 @@ from acme.magic_typing import Dict, List, Set # pylint: disable=unused-import,
from certbot import errors
from certbot.compat import os
from certbot_apache._internal import constants
from certbot_apache import constants
logger = logging.getLogger(__name__)
class ApacheParser(object):
# pylint: disable=too-many-public-methods
"""Class handles the fine details of parsing the Apache Configuration.
.. todo:: Make parsing general... remove sites-available etc...

View File

@@ -1,5 +1,5 @@
# pylint: disable=too-many-lines
"""Test for certbot_apache._internal.configurator AutoHSTS functionality"""
# pylint: disable=too-many-public-methods,too-many-lines
"""Test for certbot_apache.configurator AutoHSTS functionality"""
import re
import unittest
import mock
@@ -7,7 +7,7 @@ import mock
import six # pylint: disable=unused-import
from certbot import errors
from certbot_apache._internal import constants
from certbot_apache import constants
from certbot_apache.tests import util
@@ -39,24 +39,24 @@ class AutoHSTSTest(util.ApacheTest):
head.replace("arg[3]", "arg[4]"))
return None # pragma: no cover
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.enable_mod")
def test_autohsts_enable_headers_mod(self, mock_enable, _restart):
self.config.parser.modules.discard("headers_module")
self.config.parser.modules.discard("mod_header.c")
self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
self.assertTrue(mock_enable.called)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
def test_autohsts_deploy_already_exists(self, _restart):
self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
self.assertRaises(errors.PluginEnhancementAlreadyPresent,
self.config.enable_autohsts,
mock.MagicMock(), ["ocspvhost.com"])
@mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.prepare")
@mock.patch("certbot_apache.constants.AUTOHSTS_FREQ", 0)
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.prepare")
def test_autohsts_increase(self, mock_prepare, _mock_restart):
self.config._prepared = False
maxage = "\"max-age={0}\""
@@ -74,8 +74,8 @@ class AutoHSTSTest(util.ApacheTest):
inc_val)
self.assertTrue(mock_prepare.called)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._autohsts_increase")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._autohsts_increase")
def test_autohsts_increase_noop(self, mock_increase, _restart):
maxage = "\"max-age={0}\""
initial_val = maxage.format(constants.AUTOHSTS_STEPS[0])
@@ -89,8 +89,8 @@ class AutoHSTSTest(util.ApacheTest):
self.assertFalse(mock_increase.called)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.constants.AUTOHSTS_FREQ", 0)
def test_autohsts_increase_no_header(self, _restart):
self.config.enable_autohsts(mock.MagicMock(), ["ocspvhost.com"])
# Remove the header
@@ -102,8 +102,8 @@ class AutoHSTSTest(util.ApacheTest):
self.config.update_autohsts,
mock.MagicMock())
@mock.patch("certbot_apache._internal.constants.AUTOHSTS_FREQ", 0)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.constants.AUTOHSTS_FREQ", 0)
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
def test_autohsts_increase_and_make_permanent(self, _mock_restart):
maxage = "\"max-age={0}\""
max_val = maxage.format(constants.AUTOHSTS_PERMANENT)
@@ -141,18 +141,18 @@ class AutoHSTSTest(util.ApacheTest):
# Make sure that the execution does not continue when no entries in store
self.assertFalse(self.config.storage.put.called)
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
def test_autohsts_no_ssl_vhost(self, mock_select):
mock_select.return_value = self.vh_truth[0]
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
with mock.patch("certbot_apache.configurator.logger.warning") as mock_log:
self.assertRaises(errors.PluginError,
self.config.enable_autohsts,
mock.MagicMock(), "invalid.example.com")
self.assertTrue(
"Certbot was not able to find SSL" in mock_log.call_args[0][0])
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.add_vhost_id")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.add_vhost_id")
def test_autohsts_dont_enhance_twice(self, mock_id, _restart):
mock_id.return_value = "1234567"
self.config.enable_autohsts(mock.MagicMock(),
@@ -177,7 +177,7 @@ class AutoHSTSTest(util.ApacheTest):
self.config._autohsts_fetch_state()
self.config._autohsts["orphan_id"] = {"laststep": 999, "timestamp": 0}
self.config._autohsts_save_state()
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
with mock.patch("certbot_apache.configurator.logger.warning") as mock_log:
self.config.deploy_autohsts(mock.MagicMock())
self.assertTrue(mock_log.called)
self.assertTrue(

View File

@@ -1,12 +1,12 @@
"""Test for certbot_apache._internal.configurator for CentOS 6 overrides"""
"""Test for certbot_apache.configurator for CentOS 6 overrides"""
import unittest
from certbot.compat import os
from certbot.errors import MisconfigurationError
from certbot_apache._internal import obj
from certbot_apache._internal import override_centos
from certbot_apache._internal import parser
from certbot_apache import obj
from certbot_apache import override_centos
from certbot_apache import parser
from certbot_apache.tests import util

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.configurator for Centos overrides"""
"""Test for certbot_apache.configurator for Centos overrides"""
import unittest
import mock
@@ -7,8 +7,8 @@ from certbot import errors
from certbot.compat import filesystem
from certbot.compat import os
from certbot_apache._internal import obj
from certbot_apache._internal import override_centos
from certbot_apache import obj
from certbot_apache import override_centos
from certbot_apache.tests import util
@@ -55,7 +55,7 @@ class FedoraRestartTest(util.ApacheTest):
self.config.config_test()
def test_non_fedora_error(self):
c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
c_test = "certbot_apache.configurator.ApacheConfigurator.config_test"
with mock.patch(c_test) as mock_test:
mock_test.side_effect = errors.MisconfigurationError
with mock.patch("certbot.util.get_os_info") as mock_info:
@@ -64,7 +64,7 @@ class FedoraRestartTest(util.ApacheTest):
self.config.config_test)
def test_fedora_restart_error(self):
c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
c_test = "certbot_apache.configurator.ApacheConfigurator.config_test"
with mock.patch(c_test) as mock_test:
# First call raises error, second doesn't
mock_test.side_effect = [errors.MisconfigurationError, '']
@@ -74,7 +74,7 @@ class FedoraRestartTest(util.ApacheTest):
self._run_fedora_test)
def test_fedora_restart(self):
c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
c_test = "certbot_apache.configurator.ApacheConfigurator.config_test"
with mock.patch(c_test) as mock_test:
with mock.patch("certbot.util.run_script") as mock_run:
# First call raises error, second doesn't
@@ -107,7 +107,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
def test_get_parser(self):
self.assertIsInstance(self.config.parser, override_centos.CentOSParser)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_opportunistic_httpd_runtime_parsing(self, mock_get):
define_val = (
'Define: TEST1\n'
@@ -156,7 +156,7 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
raise Exception("Missed: %s" % vhost) # pragma: no cover
self.assertEqual(found, 2)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_get_sysconfig_vars(self, mock_cfg):
"""Make sure we read the sysconfig OPTIONS variable correctly"""
# Return nothing for the process calls
@@ -177,13 +177,13 @@ class MultipleVhostsTestCentOS(util.ApacheTest):
self.assertTrue("MOCK_NOSEP" in self.config.parser.variables.keys())
self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"])
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_alt_restart_works(self, mock_run_script):
mock_run_script.side_effect = [None, errors.SubprocessError, None]
self.config.restart()
self.assertEqual(mock_run_script.call_count, 3)
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_alt_restart_errors(self, mock_run_script):
mock_run_script.side_effect = [None,
errors.SubprocessError,

View File

@@ -1,4 +1,4 @@
"""Tests for certbot_apache._internal.parser."""
"""Tests for certbot_apache.parser."""
import shutil
import unittest
@@ -88,7 +88,7 @@ class ComplexParserTest(util.ParserTest):
def verify_fnmatch(self, arg, hit=True):
"""Test if Include was correctly parsed."""
from certbot_apache._internal import parser
from certbot_apache import parser
self.parser.add_dir(parser.get_aug_path(self.parser.loc["default"]),
"Include", [arg])
if hit:

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.configurator implementations of reverter"""
"""Test for certbot_apache.configurator implementations of reverter"""
import shutil
import unittest

View File

@@ -1,5 +1,5 @@
# pylint: disable=too-many-lines
"""Test for certbot_apache._internal.configurator."""
# pylint: disable=too-many-public-methods,too-many-lines
"""Test for certbot_apache.configurator."""
import copy
import shutil
import socket
@@ -20,10 +20,10 @@ from certbot.compat import filesystem
from certbot.tests import acme_util
from certbot.tests import util as certbot_util
from certbot_apache._internal import apache_util
from certbot_apache._internal import constants
from certbot_apache._internal import obj
from certbot_apache._internal import parser
from certbot_apache import apache_util
from certbot_apache import constants
from certbot_apache import obj
from certbot_apache import parser
from certbot_apache.tests import util
@@ -45,13 +45,13 @@ class MultipleVhostsTest(util.ApacheTest):
def mocked_deploy_cert(*args, **kwargs):
"""a helper to mock a deployed cert"""
g_mod = "certbot_apache._internal.configurator.ApacheConfigurator.enable_mod"
g_mod = "certbot_apache.configurator.ApacheConfigurator.enable_mod"
with mock.patch(g_mod):
config.real_deploy_cert(*args, **kwargs)
self.config.deploy_cert = mocked_deploy_cert
return self.config
@mock.patch("certbot_apache._internal.configurator.path_surgery")
@mock.patch("certbot_apache.configurator.path_surgery")
def test_prepare_no_install(self, mock_surgery):
silly_path = {"PATH": "/tmp/nothingness2342"}
mock_surgery.return_value = False
@@ -59,8 +59,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertRaises(errors.NoInstallationError, self.config.prepare)
self.assertEqual(mock_surgery.call_count, 1)
@mock.patch("certbot_apache._internal.parser.ApacheParser")
@mock.patch("certbot_apache._internal.configurator.util.exe_exists")
@mock.patch("certbot_apache.parser.ApacheParser")
@mock.patch("certbot_apache.configurator.util.exe_exists")
def test_prepare_version(self, mock_exe_exists, _):
mock_exe_exists.return_value = True
self.config.version = None
@@ -76,8 +76,8 @@ class MultipleVhostsTest(util.ApacheTest):
os.remove(os.path.join(server_root, ".certbot.lock"))
certbot_util.lock_and_call(self._test_prepare_locked, server_root)
@mock.patch("certbot_apache._internal.parser.ApacheParser")
@mock.patch("certbot_apache._internal.configurator.util.exe_exists")
@mock.patch("certbot_apache.parser.ApacheParser")
@mock.patch("certbot_apache.configurator.util.exe_exists")
def _test_prepare_locked(self, unused_parser, unused_exe_exists):
try:
self.config.prepare()
@@ -89,13 +89,13 @@ class MultipleVhostsTest(util.ApacheTest):
self.fail("Exception wasn't raised!")
def test_add_parser_arguments(self): # pylint: disable=no-self-use
from certbot_apache._internal.configurator import ApacheConfigurator
from certbot_apache.configurator import ApacheConfigurator
# Weak test..
ApacheConfigurator.add_parser_arguments(mock.MagicMock())
def test_docs_parser_arguments(self):
os.environ["CERTBOT_DOCS"] = "1"
from certbot_apache._internal.configurator import ApacheConfigurator
from certbot_apache.configurator import ApacheConfigurator
mock_add = mock.MagicMock()
ApacheConfigurator.add_parser_arguments(mock_add)
parserargs = ["server_root", "enmod", "dismod", "le_vhost_ext",
@@ -108,9 +108,13 @@ class MultipleVhostsTest(util.ApacheTest):
exp[k.replace("_", "-")] = ApacheConfigurator.OS_DEFAULTS[k]
# Special cases
exp["vhost-root"] = None
exp["init-script"] = None
found = set()
for call in mock_add.call_args_list:
# init-script is a special case: deprecated argument
if call[0][0] != "init-script":
self.assertEqual(exp[call[0][0]], call[1]['default'])
found.add(call[0][0])
# Make sure that all (and only) the expected values exist
@@ -121,13 +125,13 @@ class MultipleVhostsTest(util.ApacheTest):
del os.environ["CERTBOT_DOCS"]
def test_add_parser_arguments_all_configurators(self): # pylint: disable=no-self-use
from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES
from certbot_apache.entrypoint import OVERRIDE_CLASSES
for cls in OVERRIDE_CLASSES.values():
cls.add_parser_arguments(mock.MagicMock())
def test_all_configurators_defaults_defined(self):
from certbot_apache._internal.entrypoint import OVERRIDE_CLASSES
from certbot_apache._internal.configurator import ApacheConfigurator
from certbot_apache.entrypoint import OVERRIDE_CLASSES
from certbot_apache.configurator import ApacheConfigurator
parameters = set(ApacheConfigurator.OS_DEFAULTS.keys())
for cls in OVERRIDE_CLASSES.values():
self.assertTrue(parameters.issubset(set(cls.OS_DEFAULTS.keys())))
@@ -149,7 +153,7 @@ class MultipleVhostsTest(util.ApacheTest):
))
@certbot_util.patch_get_utility()
@mock.patch("certbot_apache._internal.configurator.socket.gethostbyaddr")
@mock.patch("certbot_apache.configurator.socket.gethostbyaddr")
def test_get_all_names_addrs(self, mock_gethost, mock_getutility):
mock_gethost.side_effect = [("google.com", "", ""), socket.error]
mock_utility = mock_getutility()
@@ -175,7 +179,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertEqual(self.config._create_vhost("nonexistent"), None) # pylint: disable=protected-access
def test_get_aug_internal_path(self):
from certbot_apache._internal.apache_util import get_internal_aug_path
from certbot_apache.apache_util import get_internal_aug_path
internal_paths = [
"Virtualhost", "IfModule/VirtualHost", "VirtualHost", "VirtualHost",
"Macro/VirtualHost", "IfModule/VirtualHost", "VirtualHost",
@@ -220,26 +224,26 @@ class MultipleVhostsTest(util.ApacheTest):
# Handle case of non-debian layout get_virtual_hosts
with mock.patch(
"certbot_apache._internal.configurator.ApacheConfigurator.conf"
"certbot_apache.configurator.ApacheConfigurator.conf"
) as mock_conf:
mock_conf.return_value = False
vhs = self.config.get_virtual_hosts()
self.assertEqual(len(vhs), 12)
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
def test_choose_vhost_none_avail(self, mock_select):
mock_select.return_value = None
self.assertRaises(
errors.PluginError, self.config.choose_vhost, "none.com")
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
def test_choose_vhost_select_vhost_ssl(self, mock_select):
mock_select.return_value = self.vh_truth[1]
self.assertEqual(
self.vh_truth[1], self.config.choose_vhost("none.com"))
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
@mock.patch("certbot_apache.display_ops.select_vhost")
@mock.patch("certbot_apache.obj.VirtualHost.conflicts")
def test_choose_vhost_select_vhost_non_ssl(self, mock_conf, mock_select):
mock_select.return_value = self.vh_truth[0]
mock_conf.return_value = False
@@ -252,8 +256,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertFalse(self.vh_truth[0].ssl)
self.assertTrue(chosen_vhost.ssl)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._find_best_vhost")
@mock.patch("certbot_apache._internal.parser.ApacheParser.add_dir")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._find_best_vhost")
@mock.patch("certbot_apache.parser.ApacheParser.add_dir")
def test_choose_vhost_and_servername_addition(self, mock_add, mock_find):
ret_vh = self.vh_truth[8]
ret_vh.enabled = False
@@ -261,13 +265,13 @@ class MultipleVhostsTest(util.ApacheTest):
self.config.choose_vhost("whatever.com")
self.assertTrue(mock_add.called)
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
def test_choose_vhost_select_vhost_with_temp(self, mock_select):
mock_select.return_value = self.vh_truth[0]
chosen_vhost = self.config.choose_vhost("none.com", create_if_no_ssl=False)
self.assertEqual(self.vh_truth[0], chosen_vhost)
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
def test_choose_vhost_select_vhost_conflicting_non_ssl(self, mock_select):
mock_select.return_value = self.vh_truth[3]
conflicting_vhost = obj.VirtualHost(
@@ -784,8 +788,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.config._add_name_vhost_if_necessary(self.vh_truth[0])
self.assertEqual(self.config.add_name_vhost.call_count, 2)
@mock.patch("certbot_apache._internal.configurator.http_01.ApacheHttp01.perform")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.configurator.http_01.ApacheHttp01.perform")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
def test_perform(self, mock_restart, mock_http_perform):
# Only tests functionality specific to configurator.perform
# Note: As more challenges are offered this will have to be expanded
@@ -801,8 +805,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertEqual(mock_restart.call_count, 1)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_cleanup(self, mock_cfg, mock_restart):
mock_cfg.return_value = ""
_, achalls = self.get_key_and_achalls()
@@ -817,8 +821,8 @@ class MultipleVhostsTest(util.ApacheTest):
else:
self.assertFalse(mock_restart.called)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.restart")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_cleanup_no_errors(self, mock_cfg, mock_restart):
mock_cfg.return_value = ""
_, achalls = self.get_key_and_achalls()
@@ -855,11 +859,11 @@ class MultipleVhostsTest(util.ApacheTest):
mock_script.side_effect = errors.SubprocessError("Can't find program")
self.assertRaises(errors.PluginError, self.config.get_version)
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_restart(self, _):
self.config.restart()
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_restart_bad_process(self, mock_run_script):
mock_run_script.side_effect = [None, errors.SubprocessError]
@@ -902,8 +906,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertEqual(self.vh_truth[0].name, res.name)
self.assertEqual(self.vh_truth[0].aliases, res.aliases)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._get_http_vhost")
@mock.patch("certbot_apache._internal.display_ops.select_vhost")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._get_http_vhost")
@mock.patch("certbot_apache.display_ops.select_vhost")
@mock.patch("certbot.util.exe_exists")
def test_enhance_unknown_vhost(self, mock_exe, mock_sel_vhost, mock_get):
self.config.parser.modules.add("rewrite_module")
@@ -926,7 +930,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.config.enhance, "certbot.demo", "unknown_enhancement")
def test_enhance_no_ssl_vhost(self):
with mock.patch("certbot_apache._internal.configurator.logger.warning") as mock_log:
with mock.patch("certbot_apache.configurator.logger.warning") as mock_log:
self.assertRaises(errors.PluginError, self.config.enhance,
"certbot.demo", "redirect")
# Check that correct logger.warning was printed
@@ -1231,7 +1235,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.config.choose_vhost("red.blue.purple.com")
self.config.enhance("red.blue.purple.com", "redirect")
verify_no_redirect = ("certbot_apache._internal.configurator."
verify_no_redirect = ("certbot_apache.configurator."
"ApacheConfigurator._verify_no_certbot_redirect")
with mock.patch(verify_no_redirect) as mock_verify:
self.config.enhance("green.blue.purple.com", "redirect")
@@ -1292,13 +1296,13 @@ class MultipleVhostsTest(util.ApacheTest):
account_key = self.rsa512jwk
achall1 = achallenges.KeyAuthorizationAnnotatedChallenge(
challb=acme_util.chall_to_challb(
challenges.HTTP01(
challenges.TLSSNI01(
token=b"jIq_Xy1mXGN37tb4L6Xj_es58fW571ZNyXekdZzhh7Q"),
"pending"),
domain="encryption-example.demo", account_key=account_key)
achall2 = achallenges.KeyAuthorizationAnnotatedChallenge(
challb=acme_util.chall_to_challb(
challenges.HTTP01(
challenges.TLSSNI01(
token=b"uqnaPzxtrndteOqtrXb0Asl5gOJfWAnnx6QJyvcmlDU"),
"pending"),
domain="certbot.demo", account_key=account_key)
@@ -1333,8 +1337,8 @@ class MultipleVhostsTest(util.ApacheTest):
self.config.parser.modules.add("socache_shmcb_module")
tmp_path = filesystem.realpath(tempfile.mkdtemp("vhostroot"))
filesystem.chmod(tmp_path, 0o755)
mock_p = "certbot_apache._internal.configurator.ApacheConfigurator._get_ssl_vhost_path"
mock_a = "certbot_apache._internal.parser.ApacheParser.add_include"
mock_p = "certbot_apache.configurator.ApacheConfigurator._get_ssl_vhost_path"
mock_a = "certbot_apache.parser.ApacheParser.add_include"
with mock.patch(mock_p) as mock_path:
mock_path.return_value = os.path.join(tmp_path, "whatever.conf")
@@ -1347,7 +1351,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertTrue(mock_add.called)
shutil.rmtree(tmp_path)
@mock.patch("certbot_apache._internal.parser.ApacheParser.parsed_in_original")
@mock.patch("certbot_apache.parser.ApacheParser.parsed_in_original")
def test_choose_vhost_and_servername_addition_parsed(self, mock_parsed):
ret_vh = self.vh_truth[8]
ret_vh.enabled = True
@@ -1369,7 +1373,7 @@ class MultipleVhostsTest(util.ApacheTest):
def test_choose_vhosts_wildcard(self):
# pylint: disable=protected-access
mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
mock_path = "certbot_apache.display_ops.select_vhost_multiple"
with mock.patch(mock_path) as mock_select_vhs:
mock_select_vhs.return_value = [self.vh_truth[3]]
vhs = self.config._choose_vhosts_wildcard("*.certbot.demo",
@@ -1385,10 +1389,10 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertFalse(vhs[0] == self.vh_truth[3])
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.make_vhost_ssl")
def test_choose_vhosts_wildcard_no_ssl(self, mock_makessl):
# pylint: disable=protected-access
mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
mock_path = "certbot_apache.display_ops.select_vhost_multiple"
with mock.patch(mock_path) as mock_select_vhs:
mock_select_vhs.return_value = [self.vh_truth[1]]
vhs = self.config._choose_vhosts_wildcard("*.certbot.demo",
@@ -1396,13 +1400,13 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertFalse(mock_makessl.called)
self.assertEqual(vhs[0], self.vh_truth[1])
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._vhosts_for_wildcard")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.make_vhost_ssl")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._vhosts_for_wildcard")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.make_vhost_ssl")
def test_choose_vhosts_wildcard_already_ssl(self, mock_makessl, mock_vh_for_w):
# pylint: disable=protected-access
# Already SSL vhost
mock_vh_for_w.return_value = [self.vh_truth[7]]
mock_path = "certbot_apache._internal.display_ops.select_vhost_multiple"
mock_path = "certbot_apache.display_ops.select_vhost_multiple"
with mock.patch(mock_path) as mock_select_vhs:
mock_select_vhs.return_value = [self.vh_truth[7]]
vhs = self.config._choose_vhosts_wildcard("whatever",
@@ -1423,7 +1427,7 @@ class MultipleVhostsTest(util.ApacheTest):
mock_choose_vhosts = mock.MagicMock()
mock_choose_vhosts.return_value = [self.vh_truth[7]]
self.config._choose_vhosts_wildcard = mock_choose_vhosts
mock_d = "certbot_apache._internal.configurator.ApacheConfigurator._deploy_cert"
mock_d = "certbot_apache.configurator.ApacheConfigurator._deploy_cert"
with mock.patch(mock_d) as mock_dep:
self.config.deploy_cert("*.wildcard.example.org", "/tmp/path",
"/tmp/path", "/tmp/path", "/tmp/path")
@@ -1431,7 +1435,7 @@ class MultipleVhostsTest(util.ApacheTest):
self.assertEqual(len(mock_dep.call_args_list), 1)
self.assertEqual(self.vh_truth[7], mock_dep.call_args_list[0][0][0])
@mock.patch("certbot_apache._internal.display_ops.select_vhost_multiple")
@mock.patch("certbot_apache.display_ops.select_vhost_multiple")
def test_deploy_cert_wildcard_no_vhosts(self, mock_dialog):
# pylint: disable=protected-access
mock_dialog.return_value = []
@@ -1440,7 +1444,7 @@ class MultipleVhostsTest(util.ApacheTest):
"*.wild.cat", "/tmp/path", "/tmp/path",
"/tmp/path", "/tmp/path")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._choose_vhosts_wildcard")
def test_enhance_wildcard_after_install(self, mock_choose):
# pylint: disable=protected-access
self.config.parser.modules.add("mod_ssl.c")
@@ -1451,7 +1455,7 @@ class MultipleVhostsTest(util.ApacheTest):
"Upgrade-Insecure-Requests")
self.assertFalse(mock_choose.called)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._choose_vhosts_wildcard")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._choose_vhosts_wildcard")
def test_enhance_wildcard_no_install(self, mock_choose):
self.vh_truth[3].ssl = True
mock_choose.return_value = [self.vh_truth[3]]
@@ -1528,7 +1532,7 @@ class AugeasVhostsTest(util.ApacheTest):
chosen_vhost = self.config._create_vhost(path)
self.assertTrue(chosen_vhost is None or chosen_vhost.path == path)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator._create_vhost")
@mock.patch("certbot_apache.configurator.ApacheConfigurator._create_vhost")
def test_get_vhost_continue(self, mock_vhost):
mock_vhost.return_value = None
vhs = self.config.get_virtual_hosts()
@@ -1540,18 +1544,18 @@ class AugeasVhostsTest(util.ApacheTest):
for name in names:
self.assertFalse(name in self.config.choose_vhost(name).aliases)
@mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
@mock.patch("certbot_apache.obj.VirtualHost.conflicts")
def test_choose_vhost_without_matching_wildcard(self, mock_conflicts):
mock_conflicts.return_value = False
mock_path = "certbot_apache._internal.display_ops.select_vhost"
mock_path = "certbot_apache.display_ops.select_vhost"
with mock.patch(mock_path, lambda _, vhosts: vhosts[0]):
for name in ("a.example.net", "other.example.net"):
self.assertTrue(name in self.config.choose_vhost(name).aliases)
@mock.patch("certbot_apache._internal.obj.VirtualHost.conflicts")
@mock.patch("certbot_apache.obj.VirtualHost.conflicts")
def test_choose_vhost_wildcard_not_found(self, mock_conflicts):
mock_conflicts.return_value = False
mock_path = "certbot_apache._internal.display_ops.select_vhost"
mock_path = "certbot_apache.display_ops.select_vhost"
names = (
"abc.example.net", "not.there.tld", "aa.wildcard.tld"
)
@@ -1563,7 +1567,7 @@ class AugeasVhostsTest(util.ApacheTest):
self.assertEqual(mock_select.call_count - orig_cc, 1)
def test_choose_vhost_wildcard_found(self):
mock_path = "certbot_apache._internal.display_ops.select_vhost"
mock_path = "certbot_apache.display_ops.select_vhost"
names = (
"ab.example.net", "a.wildcard.tld", "yetanother.example.net"
)
@@ -1617,7 +1621,7 @@ class MultiVhostsTest(util.ApacheTest):
self.assertEqual(self.config.is_name_vhost(self.vh_truth[1]),
self.config.is_name_vhost(ssl_vhost))
mock_path = "certbot_apache._internal.configurator.ApacheConfigurator._get_new_vh_path"
mock_path = "certbot_apache.configurator.ApacheConfigurator._get_new_vh_path"
with mock.patch(mock_path) as mock_getpath:
mock_getpath.return_value = None
self.assertRaises(errors.PluginError, self.config.make_vhost_ssl,
@@ -1723,7 +1727,7 @@ class InstallSslOptionsConfTest(util.ApacheTest):
self._assert_current_file()
def test_prev_file_updates_to_current(self):
from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES
from certbot_apache.constants import ALL_SSL_OPTIONS_HASHES
ALL_SSL_OPTIONS_HASHES.insert(0, "test_hash_does_not_match")
with mock.patch('certbot.crypto_util.sha256sum') as mock_sha256:
mock_sha256.return_value = ALL_SSL_OPTIONS_HASHES[0]
@@ -1762,7 +1766,7 @@ class InstallSslOptionsConfTest(util.ApacheTest):
self.assertFalse(mock_logger.warning.called)
def test_current_file_hash_in_all_hashes(self):
from certbot_apache._internal.constants import ALL_SSL_OPTIONS_HASHES
from certbot_apache.constants import ALL_SSL_OPTIONS_HASHES
self.assertTrue(self._current_ssl_options_hash() in ALL_SSL_OPTIONS_HASHES,
"Constants.ALL_SSL_OPTIONS_HASHES must be appended"
" with the sha256 hash of self.config.mod_ssl_conf when it is updated.")

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.configurator for Debian overrides"""
"""Test for certbot_apache.configurator for Debian overrides"""
import shutil
import unittest
@@ -7,8 +7,8 @@ import mock
from certbot import errors
from certbot.compat import os
from certbot_apache._internal import apache_util
from certbot_apache._internal import obj
from certbot_apache import apache_util
from certbot_apache import obj
from certbot_apache.tests import util
@@ -32,8 +32,8 @@ class MultipleVhostsTestDebian(util.ApacheTest):
def mocked_deploy_cert(*args, **kwargs):
"""a helper to mock a deployed cert"""
g_mod = "certbot_apache._internal.configurator.ApacheConfigurator.enable_mod"
d_mod = "certbot_apache._internal.override_debian.DebianConfigurator.enable_mod"
g_mod = "certbot_apache.configurator.ApacheConfigurator.enable_mod"
d_mod = "certbot_apache.override_debian.DebianConfigurator.enable_mod"
with mock.patch(g_mod):
with mock.patch(d_mod):
config.real_deploy_cert(*args, **kwargs)
@@ -47,7 +47,7 @@ class MultipleVhostsTestDebian(util.ApacheTest):
@mock.patch("certbot.util.run_script")
@mock.patch("certbot.util.exe_exists")
@mock.patch("certbot_apache._internal.parser.subprocess.Popen")
@mock.patch("certbot_apache.parser.subprocess.Popen")
def test_enable_mod(self, mock_popen, mock_exe_exists, mock_run_script):
mock_popen().communicate.return_value = ("Define: DUMP_RUN_CFG", "")
mock_popen().returncode = 0
@@ -196,7 +196,7 @@ class MultipleVhostsTestDebian(util.ApacheTest):
def test_enable_site_call_parent(self):
with mock.patch(
"certbot_apache._internal.configurator.ApacheConfigurator.enable_site") as e_s:
"certbot_apache.configurator.ApacheConfigurator.enable_site") as e_s:
self.config.parser.root = "/tmp/nonexistent"
vh = self.vh_truth[0]
vh.enabled = False

View File

@@ -1,4 +1,4 @@
"""Test certbot_apache._internal.display_ops."""
"""Test certbot_apache.display_ops."""
import unittest
import mock
@@ -9,14 +9,14 @@ from certbot.display import util as display_util
from certbot.tests import util as certbot_util
from certbot_apache._internal import obj
from certbot_apache import obj
from certbot_apache._internal.display_ops import select_vhost_multiple
from certbot_apache.display_ops import select_vhost_multiple
from certbot_apache.tests import util
class SelectVhostMultiTest(unittest.TestCase):
"""Tests for certbot_apache._internal.display_ops.select_vhost_multiple."""
"""Tests for certbot_apache.display_ops.select_vhost_multiple."""
def setUp(self):
self.base_dir = "/example_path"
@@ -45,7 +45,7 @@ class SelectVhostMultiTest(unittest.TestCase):
self.assertFalse(vhs)
class SelectVhostTest(unittest.TestCase):
"""Tests for certbot_apache._internal.display_ops.select_vhost."""
"""Tests for certbot_apache.display_ops.select_vhost."""
def setUp(self):
self.base_dir = "/example_path"
@@ -54,7 +54,7 @@ class SelectVhostTest(unittest.TestCase):
@classmethod
def _call(cls, vhosts):
from certbot_apache._internal.display_ops import select_vhost
from certbot_apache.display_ops import select_vhost
return select_vhost("example.com", vhosts)
@certbot_util.patch_get_utility()
@@ -81,9 +81,9 @@ class SelectVhostTest(unittest.TestCase):
def test_no_vhosts(self):
self.assertEqual(self._call([]), None)
@mock.patch("certbot_apache._internal.display_ops.display_util")
@mock.patch("certbot_apache.display_ops.display_util")
@certbot_util.patch_get_utility()
@mock.patch("certbot_apache._internal.display_ops.logger")
@mock.patch("certbot_apache.display_ops.logger")
def test_small_display(self, mock_logger, mock_util, mock_display_util):
mock_display_util.WIDTH = 20
mock_util().menu.return_value = (display_util.OK, 0)

View File

@@ -1,10 +1,10 @@
"""Test for certbot_apache._internal.entrypoint for override class resolution"""
"""Test for certbot_apache.entrypoint for override class resolution"""
import unittest
import mock
from certbot_apache._internal import configurator
from certbot_apache._internal import entrypoint
from certbot_apache import configurator
from certbot_apache import entrypoint
class EntryPointTest(unittest.TestCase):

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.configurator for Fedora 29+ overrides"""
"""Test for certbot_apache.configurator for Fedora 29+ overrides"""
import unittest
import mock
@@ -7,8 +7,8 @@ from certbot import errors
from certbot.compat import filesystem
from certbot.compat import os
from certbot_apache._internal import obj
from certbot_apache._internal import override_fedora
from certbot_apache import obj
from certbot_apache import override_fedora
from certbot_apache.tests import util
@@ -58,7 +58,7 @@ class FedoraRestartTest(util.ApacheTest):
self.config.config_test()
def test_fedora_restart_error(self):
c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
c_test = "certbot_apache.configurator.ApacheConfigurator.config_test"
with mock.patch(c_test) as mock_test:
# First call raises error, second doesn't
mock_test.side_effect = [errors.MisconfigurationError, '']
@@ -68,7 +68,7 @@ class FedoraRestartTest(util.ApacheTest):
self._run_fedora_test)
def test_fedora_restart(self):
c_test = "certbot_apache._internal.configurator.ApacheConfigurator.config_test"
c_test = "certbot_apache.configurator.ApacheConfigurator.config_test"
with mock.patch(c_test) as mock_test:
with mock.patch("certbot.util.run_script") as mock_run:
# First call raises error, second doesn't
@@ -101,7 +101,7 @@ class MultipleVhostsTestFedora(util.ApacheTest):
def test_get_parser(self):
self.assertIsInstance(self.config.parser, override_fedora.FedoraParser)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_opportunistic_httpd_runtime_parsing(self, mock_get):
define_val = (
'Define: TEST1\n'
@@ -135,7 +135,7 @@ class MultipleVhostsTestFedora(util.ApacheTest):
self.assertTrue("TEST2" in self.config.parser.variables.keys())
self.assertTrue("mod_another.c" in self.config.parser.modules)
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_get_version(self, mock_run_script):
mock_run_script.return_value = ('', None)
self.assertRaises(errors.PluginError, self.config.get_version)
@@ -156,7 +156,7 @@ class MultipleVhostsTestFedora(util.ApacheTest):
raise Exception("Missed: %s" % vhost) # pragma: no cover
self.assertEqual(found, 2)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_get_sysconfig_vars(self, mock_cfg):
"""Make sure we read the sysconfig OPTIONS variable correctly"""
# Return nothing for the process calls
@@ -177,13 +177,13 @@ class MultipleVhostsTestFedora(util.ApacheTest):
self.assertTrue("MOCK_NOSEP" in self.config.parser.variables.keys())
self.assertEqual("NOSEP_VAL", self.config.parser.variables["NOSEP_TWO"])
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_alt_restart_works(self, mock_run_script):
mock_run_script.side_effect = [None, errors.SubprocessError, None]
self.config.restart()
self.assertEqual(mock_run_script.call_count, 3)
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_alt_restart_errors(self, mock_run_script):
mock_run_script.side_effect = [None,
errors.SubprocessError,

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.configurator for Gentoo overrides"""
"""Test for certbot_apache.configurator for Gentoo overrides"""
import unittest
import mock
@@ -7,8 +7,8 @@ from certbot import errors
from certbot.compat import filesystem
from certbot.compat import os
from certbot_apache._internal import obj
from certbot_apache._internal import override_gentoo
from certbot_apache import obj
from certbot_apache import override_gentoo
from certbot_apache.tests import util
@@ -52,8 +52,7 @@ class MultipleVhostsTestGentoo(util.ApacheTest):
config_root=config_root,
vhost_root=vhost_root)
# pylint: disable=line-too-long
with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_runtime_variables"):
with mock.patch("certbot_apache.override_gentoo.GentooParser.update_runtime_variables"):
self.config = util.get_apache_configurator(
self.config_path, self.vhost_path, self.config_dir, self.work_dir,
os_info="gentoo")
@@ -86,17 +85,17 @@ class MultipleVhostsTestGentoo(util.ApacheTest):
self.config.parser.apacheconfig_filep = filesystem.realpath(
os.path.join(self.config.parser.root, "../conf.d/apache2"))
self.config.parser.variables = {}
with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"):
with mock.patch("certbot_apache.override_gentoo.GentooParser.update_modules"):
self.config.parser.update_runtime_variables()
for define in defines:
self.assertTrue(define in self.config.parser.variables.keys())
@mock.patch("certbot_apache._internal.parser.ApacheParser.parse_from_subprocess")
@mock.patch("certbot_apache.parser.ApacheParser.parse_from_subprocess")
def test_no_binary_configdump(self, mock_subprocess):
"""Make sure we don't call binary dumps other than modules from Apache
as this is not supported in Gentoo currently"""
with mock.patch("certbot_apache._internal.override_gentoo.GentooParser.update_modules"):
with mock.patch("certbot_apache.override_gentoo.GentooParser.update_modules"):
self.config.parser.update_runtime_variables()
self.config.parser.reset_modules()
self.assertFalse(mock_subprocess.called)
@@ -105,7 +104,7 @@ class MultipleVhostsTestGentoo(util.ApacheTest):
self.config.parser.reset_modules()
self.assertTrue(mock_subprocess.called)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_opportunistic_httpd_runtime_parsing(self, mock_get):
mod_val = (
'Loaded Modules:\n'
@@ -129,7 +128,7 @@ class MultipleVhostsTestGentoo(util.ApacheTest):
self.assertEqual(len(self.config.parser.modules), 4)
self.assertTrue("mod_another.c" in self.config.parser.modules)
@mock.patch("certbot_apache._internal.configurator.util.run_script")
@mock.patch("certbot_apache.configurator.util.run_script")
def test_alt_restart_works(self, mock_run_script):
mock_run_script.side_effect = [None, errors.SubprocessError, None]
self.config.restart()

View File

@@ -1,4 +1,4 @@
"""Test for certbot_apache._internal.http_01."""
"""Test for certbot_apache.http_01."""
import unittest
import mock
@@ -11,7 +11,7 @@ from certbot.compat import filesystem
from certbot.compat import os
from certbot.tests import acme_util
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.parser import get_aug_path
from certbot_apache.tests import util
@@ -19,7 +19,7 @@ NUM_ACHALLS = 3
class ApacheHttp01Test(util.ApacheTest):
"""Test for certbot_apache._internal.http_01.ApacheHttp01."""
"""Test for certbot_apache.http_01.ApacheHttp01."""
def setUp(self, *args, **kwargs): # pylint: disable=arguments-differ
super(ApacheHttp01Test, self).setUp(*args, **kwargs)
@@ -45,13 +45,13 @@ class ApacheHttp01Test(util.ApacheTest):
self.config.parser.modules.add("mod_{0}.c".format(mod))
self.config.parser.modules.add(mod + "_module")
from certbot_apache._internal.http_01 import ApacheHttp01
from certbot_apache.http_01 import ApacheHttp01
self.http = ApacheHttp01(self.config)
def test_empty_perform(self):
self.assertFalse(self.http.perform())
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.enable_mod")
def test_enable_modules_apache_2_2(self, mock_enmod):
self.config.version = (2, 2)
self.config.parser.modules.remove("authz_host_module")
@@ -60,7 +60,7 @@ class ApacheHttp01Test(util.ApacheTest):
enmod_calls = self.common_enable_modules_test(mock_enmod)
self.assertEqual(enmod_calls[0][0][0], "authz_host")
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.enable_mod")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.enable_mod")
def test_enable_modules_apache_2_4(self, mock_enmod):
self.config.parser.modules.remove("authz_core_module")
self.config.parser.modules.remove("mod_authz_core.c")

View File

@@ -1,4 +1,4 @@
"""Tests for certbot_apache._internal.obj."""
"""Tests for certbot_apache.obj."""
import unittest
@@ -6,8 +6,8 @@ class VirtualHostTest(unittest.TestCase):
"""Test the VirtualHost class."""
def setUp(self):
from certbot_apache._internal.obj import Addr
from certbot_apache._internal.obj import VirtualHost
from certbot_apache.obj import Addr
from certbot_apache.obj import VirtualHost
self.addr1 = Addr.fromstring("127.0.0.1")
self.addr2 = Addr.fromstring("127.0.0.1:443")
@@ -23,8 +23,7 @@ class VirtualHostTest(unittest.TestCase):
"fp", "vhp", set([self.addr2]), False, False, "localhost")
def test_repr(self):
self.assertEqual(repr(self.addr2),
"certbot_apache._internal.obj.Addr(('127.0.0.1', '443'))")
self.assertEqual(repr(self.addr2), "certbot_apache.obj.Addr(('127.0.0.1', '443'))")
def test_eq(self):
self.assertTrue(self.vhost1b == self.vhost1)
@@ -37,8 +36,8 @@ class VirtualHostTest(unittest.TestCase):
self.assertFalse(self.vhost1 != self.vhost1b)
def test_conflicts(self):
from certbot_apache._internal.obj import Addr
from certbot_apache._internal.obj import VirtualHost
from certbot_apache.obj import Addr
from certbot_apache.obj import VirtualHost
complex_vh = VirtualHost(
"fp", "vhp",
@@ -55,7 +54,7 @@ class VirtualHostTest(unittest.TestCase):
self.addr_default]))
def test_same_server(self):
from certbot_apache._internal.obj import VirtualHost
from certbot_apache.obj import VirtualHost
no_name1 = VirtualHost(
"fp", "vhp", set([self.addr1]), False, False, None)
no_name2 = VirtualHost(
@@ -78,7 +77,7 @@ class VirtualHostTest(unittest.TestCase):
class AddrTest(unittest.TestCase):
"""Test obj.Addr."""
def setUp(self):
from certbot_apache._internal.obj import Addr
from certbot_apache.obj import Addr
self.addr = Addr.fromstring("*:443")
self.addr1 = Addr.fromstring("127.0.0.1")
@@ -93,7 +92,7 @@ class AddrTest(unittest.TestCase):
self.assertTrue(self.addr2.is_wildcard())
def test_get_sni_addr(self):
from certbot_apache._internal.obj import Addr
from certbot_apache.obj import Addr
self.assertEqual(
self.addr.get_sni_addr("443"), Addr.fromstring("*:443"))
self.assertEqual(

View File

@@ -1,4 +1,5 @@
"""Tests for certbot_apache._internal.parser."""
# pylint: disable=too-many-public-methods
"""Tests for certbot_apache.parser."""
import shutil
import unittest
@@ -113,7 +114,7 @@ class BasicParserTest(util.ParserTest):
Path must be valid before attempting to add to augeas
"""
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.parser import get_aug_path
# This makes sure that find_dir will work
self.parser.modules.add("mod_ssl.c")
@@ -127,7 +128,7 @@ class BasicParserTest(util.ParserTest):
self.assertTrue("IfModule" in matches[0])
def test_add_dir_to_ifmodssl_multiple(self):
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.parser import get_aug_path
# This makes sure that find_dir will work
self.parser.modules.add("mod_ssl.c")
@@ -141,11 +142,11 @@ class BasicParserTest(util.ParserTest):
self.assertTrue("IfModule" in matches[0])
def test_get_aug_path(self):
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.parser import get_aug_path
self.assertEqual("/files/etc/apache", get_aug_path("/etc/apache"))
def test_set_locations(self):
with mock.patch("certbot_apache._internal.parser.os.path") as mock_path:
with mock.patch("certbot_apache.parser.os.path") as mock_path:
mock_path.isfile.side_effect = [False, False]
@@ -155,18 +156,18 @@ class BasicParserTest(util.ParserTest):
self.assertEqual(results["default"], results["listen"])
self.assertEqual(results["default"], results["name"])
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.parser.ApacheParser.get_arg")
@mock.patch("certbot_apache.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache.parser.ApacheParser.get_arg")
def test_parse_modules_bad_syntax(self, mock_arg, mock_find):
mock_find.return_value = ["1", "2", "3", "4", "5", "6", "7", "8"]
mock_arg.return_value = None
with mock.patch("certbot_apache._internal.parser.logger") as mock_logger:
with mock.patch("certbot_apache.parser.logger") as mock_logger:
self.parser.parse_modules()
# Make sure that we got None return value and logged the file
self.assertTrue(mock_logger.debug.called)
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_update_runtime_variables(self, mock_cfg, _):
define_val = (
'ServerRoot: "/etc/apache2"\n'
@@ -263,7 +264,7 @@ class BasicParserTest(util.ParserTest):
self.parser.modules = set()
with mock.patch(
"certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
"certbot_apache.parser.ApacheParser.parse_file") as mock_parse:
self.parser.update_runtime_variables()
self.assertEqual(self.parser.variables, expected_vars)
self.assertEqual(len(self.parser.modules), 58)
@@ -271,8 +272,8 @@ class BasicParserTest(util.ParserTest):
# Make sure we tried to include them all.
self.assertEqual(mock_parse.call_count, 25)
@mock.patch("certbot_apache._internal.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser.find_dir")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_update_runtime_variables_alt_values(self, mock_cfg, _):
inc_val = (
'Included configuration files:\n'
@@ -286,7 +287,7 @@ class BasicParserTest(util.ParserTest):
self.parser.modules = set()
with mock.patch(
"certbot_apache._internal.parser.ApacheParser.parse_file") as mock_parse:
"certbot_apache.parser.ApacheParser.parse_file") as mock_parse:
self.parser.update_runtime_variables()
# No matching modules should have been found
self.assertEqual(len(self.parser.modules), 0)
@@ -294,7 +295,7 @@ class BasicParserTest(util.ParserTest):
# path derived from root configuration Include statements
self.assertEqual(mock_parse.call_count, 1)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_update_runtime_vars_bad_output(self, mock_cfg):
mock_cfg.return_value = "Define: TLS=443=24"
self.parser.update_runtime_variables()
@@ -303,8 +304,8 @@ class BasicParserTest(util.ParserTest):
self.assertRaises(
errors.PluginError, self.parser.update_runtime_variables)
@mock.patch("certbot_apache._internal.configurator.ApacheConfigurator.option")
@mock.patch("certbot_apache._internal.parser.subprocess.Popen")
@mock.patch("certbot_apache.configurator.ApacheConfigurator.option")
@mock.patch("certbot_apache.parser.subprocess.Popen")
def test_update_runtime_vars_bad_ctl(self, mock_popen, mock_opt):
mock_popen.side_effect = OSError
mock_opt.return_value = "nonexistent"
@@ -312,7 +313,7 @@ class BasicParserTest(util.ParserTest):
errors.MisconfigurationError,
self.parser.update_runtime_variables)
@mock.patch("certbot_apache._internal.parser.subprocess.Popen")
@mock.patch("certbot_apache.parser.subprocess.Popen")
def test_update_runtime_vars_bad_exit(self, mock_popen):
mock_popen().communicate.return_value = ("", "")
mock_popen.returncode = -1
@@ -321,7 +322,7 @@ class BasicParserTest(util.ParserTest):
self.parser.update_runtime_variables)
def test_add_comment(self):
from certbot_apache._internal.parser import get_aug_path
from certbot_apache.parser import get_aug_path
self.parser.add_comment(get_aug_path(self.parser.loc["name"]), "123456")
comm = self.parser.find_comments("123456")
self.assertEqual(len(comm), 1)
@@ -337,9 +338,9 @@ class ParserInitTest(util.ApacheTest):
shutil.rmtree(self.config_dir)
shutil.rmtree(self.work_dir)
@mock.patch("certbot_apache._internal.parser.ApacheParser.init_augeas")
@mock.patch("certbot_apache.parser.ApacheParser.init_augeas")
def test_prepare_no_augeas(self, mock_init_augeas):
from certbot_apache._internal.parser import ApacheParser
from certbot_apache.parser import ApacheParser
mock_init_augeas.side_effect = errors.NoInstallationError
self.config.config_test = mock.Mock()
self.assertRaises(
@@ -348,17 +349,17 @@ class ParserInitTest(util.ApacheTest):
version=(2, 4, 22), configurator=self.config)
def test_init_old_aug(self):
from certbot_apache._internal.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser.check_aug_version") as mock_c:
from certbot_apache.parser import ApacheParser
with mock.patch("certbot_apache.parser.ApacheParser.check_aug_version") as mock_c:
mock_c.return_value = False
self.assertRaises(
errors.NotSupportedError,
ApacheParser, os.path.relpath(self.config_path),
"/dummy/vhostpath", version=(2, 4, 22), configurator=self.config)
@mock.patch("certbot_apache._internal.parser.ApacheParser._get_runtime_cfg")
@mock.patch("certbot_apache.parser.ApacheParser._get_runtime_cfg")
def test_unparseable(self, mock_cfg):
from certbot_apache._internal.parser import ApacheParser
from certbot_apache.parser import ApacheParser
mock_cfg.return_value = ('Define: TEST')
self.assertRaises(
errors.PluginError,
@@ -366,9 +367,9 @@ class ParserInitTest(util.ApacheTest):
"/dummy/vhostpath", version=(2, 2, 22), configurator=self.config)
def test_root_normalized(self):
from certbot_apache._internal.parser import ApacheParser
from certbot_apache.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser."
with mock.patch("certbot_apache.parser.ApacheParser."
"update_runtime_variables"):
path = os.path.join(
self.temp_dir,
@@ -379,8 +380,8 @@ class ParserInitTest(util.ApacheTest):
self.assertEqual(parser.root, self.config_path)
def test_root_absolute(self):
from certbot_apache._internal.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser."
from certbot_apache.parser import ApacheParser
with mock.patch("certbot_apache.parser.ApacheParser."
"update_runtime_variables"):
parser = ApacheParser(
os.path.relpath(self.config_path),
@@ -389,8 +390,8 @@ class ParserInitTest(util.ApacheTest):
self.assertEqual(parser.root, self.config_path)
def test_root_no_trailing_slash(self):
from certbot_apache._internal.parser import ApacheParser
with mock.patch("certbot_apache._internal.parser.ApacheParser."
from certbot_apache.parser import ApacheParser
with mock.patch("certbot_apache.parser.ApacheParser."
"update_runtime_variables"):
parser = ApacheParser(
self.config_path + os.path.sep,

View File

@@ -13,12 +13,12 @@ from certbot.display import util as display_util
from certbot.plugins import common
from certbot.tests import util as test_util
from certbot_apache._internal import configurator
from certbot_apache._internal import entrypoint
from certbot_apache._internal import obj
from certbot_apache import configurator
from certbot_apache import entrypoint
from certbot_apache import obj
class ApacheTest(unittest.TestCase):
class ApacheTest(unittest.TestCase): # pylint: disable=too-few-public-methods
def setUp(self, test_dir="debian_apache_2_4/multiple_vhosts",
config_root="debian_apache_2_4/multiple_vhosts/apache2",
@@ -72,16 +72,16 @@ class ParserTest(ApacheTest):
zope.component.provideUtility(display_util.FileDisplay(sys.stdout,
False))
from certbot_apache._internal.parser import ApacheParser
from certbot_apache.parser import ApacheParser
self.aug = augeas.Augeas(
flags=augeas.Augeas.NONE | augeas.Augeas.NO_MODL_AUTOLOAD)
with mock.patch("certbot_apache._internal.parser.ApacheParser."
with mock.patch("certbot_apache.parser.ApacheParser."
"update_runtime_variables"):
self.parser = ApacheParser(
self.config_path, self.vhost_path, configurator=self.config)
def get_apache_configurator(
def get_apache_configurator( # pylint: disable=too-many-arguments, too-many-locals
config_path, vhost_path,
config_dir, work_dir, version=(2, 4, 7),
os_info="generic",
@@ -105,11 +105,11 @@ def get_apache_configurator(
in_progress_dir=os.path.join(backups, "IN_PROGRESS"),
work_dir=work_dir)
with mock.patch("certbot_apache._internal.configurator.util.run_script"):
with mock.patch("certbot_apache._internal.configurator.util."
with mock.patch("certbot_apache.configurator.util.run_script"):
with mock.patch("certbot_apache.configurator.util."
"exe_exists") as mock_exe_exists:
mock_exe_exists.return_value = True
with mock.patch("certbot_apache._internal.parser.ApacheParser."
with mock.patch("certbot_apache.parser.ApacheParser."
"update_runtime_variables"):
try:
config_class = entrypoint.OVERRIDE_CLASSES[os_info]

View File

@@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/certbot-apache.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/certbot-apache.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/certbot-apache"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/certbot-apache"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.augeas_configurator`
---------------------------------------------
.. automodule:: certbot_apache.augeas_configurator
:members:

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.configurator`
--------------------------------------
.. automodule:: certbot_apache.configurator
:members:

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.display_ops`
-------------------------------------
.. automodule:: certbot_apache.display_ops
:members:

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.obj`
-----------------------------
.. automodule:: certbot_apache.obj
:members:

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.parser`
--------------------------------
.. automodule:: certbot_apache.parser
:members:

View File

@@ -0,0 +1,5 @@
:mod:`certbot_apache.tls_sni_01`
------------------------------------
.. automodule:: certbot_apache.tls_sni_01
:members:

318
certbot-apache/docs/conf.py Normal file
View File

@@ -0,0 +1,318 @@
# -*- coding: utf-8 -*-
#
# certbot-apache documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 18 13:39:26 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
from certbot.compat import os
import shlex
import mock
# http://docs.readthedocs.org/en/latest/faq.html#i-get-import-errors-on-libraries-that-depend-on-c-modules
# c.f. #262
sys.modules.update(
(mod_name, mock.MagicMock()) for mod_name in ['augeas'])
here = os.path.abspath(os.path.dirname(__file__))
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath(os.path.join(here, '..')))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.intersphinx',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.viewcode',
]
autodoc_member_order = 'bysource'
autodoc_default_flags = ['show-inheritance', 'private-members']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'certbot-apache'
copyright = u'2014-2015, Let\'s Encrypt Project'
author = u'Certbot Project'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '0'
# The full version, including alpha/beta/rc tags.
release = '0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = 'en'
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
default_role = 'py:obj'
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
# http://docs.readthedocs.org/en/latest/theme.html#how-do-i-use-this-locally-and-on-read-the-docs
# on_rtd is whether we are on readthedocs.org
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
if not on_rtd: # only import and set the theme if we're building docs locally
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
# otherwise, readthedocs.org uses their theme by default, so no need to specify it
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'certbot-apachedoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'certbot-apache.tex', u'certbot-apache Documentation',
u'Certbot Project', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'certbot-apache', u'certbot-apache Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'certbot-apache', u'certbot-apache Documentation',
author, 'certbot-apache', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
intersphinx_mapping = {
'python': ('https://docs.python.org/', None),
'acme': ('https://acme-python.readthedocs.org/en/latest/', None),
'certbot': ('https://certbot.eff.org/docs/', None),
}

View File

@@ -0,0 +1,31 @@
.. certbot-apache documentation master file, created by
sphinx-quickstart on Sun Oct 18 13:39:26 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to certbot-apache's documentation!
==============================================
Contents:
.. toctree::
:maxdepth: 2
.. toctree::
:maxdepth: 1
api
.. automodule:: certbot_apache
:members:
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

View File

@@ -0,0 +1,263 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=_build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
set I18NSPHINXOPTS=%SPHINXOPTS% .
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 2> nul
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\certbot-apache.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\certbot-apache.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

View File

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

View File

@@ -1,11 +1,12 @@
# readthedocs.org gives no way to change the install command to "pip
# install -e certbot[docs]" (that would in turn install documentation
# install -e .[docs]" (that would in turn install documentation
# dependencies), but it allows to specify a requirements.txt file at
# https://readthedocs.org/dashboard/letsencrypt/advanced/ (c.f. #259)
# Although ReadTheDocs certainly doesn't need to install the project
# in --editable mode (-e), just "pip install .[docs]" does not work as
# expected and "pip install -e certbot[docs]" must be used instead
# expected and "pip install -e .[docs]" must be used instead
-e acme
-e certbot[docs]
-e .
-e certbot-apache[docs]

View File

@@ -4,13 +4,13 @@ from setuptools.command.test import test as TestCommand
import sys
version = '1.0.0.dev0'
version = '0.39.0.dev0'
# Remember to update local-oldest-requirements.txt when changing the minimum
# acme/certbot version.
install_requires = [
'acme>=0.29.0',
'certbot>=0.39.0',
'certbot>=0.39.0.dev0',
'mock',
'python-augeas',
'setuptools',
@@ -18,6 +18,11 @@ install_requires = [
'zope.interface',
]
docs_extras = [
'Sphinx>=1.0', # autodoc_member_order = 'bysource', autodoc_default_flags
'sphinx_rtd_theme',
]
class PyTest(TestCommand):
user_options = []
@@ -69,9 +74,12 @@ setup(
packages=find_packages(),
include_package_data=True,
install_requires=install_requires,
extras_require={
'docs': docs_extras,
},
entry_points={
'certbot.plugins': [
'apache = certbot_apache._internal.entrypoint:ENTRYPOINT',
'apache = certbot_apache.entrypoint:ENTRYPOINT',
],
},
test_suite='certbot_apache',

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="0.40.1"
LE_AUTO_VERSION="0.38.0"
BASENAME=$(basename $0)
USAGE="Usage: $BASENAME [OPTIONS]
A self-updating wrapper script for the Certbot ACME client. When run, updates
@@ -775,8 +775,6 @@ elif [ -f /etc/redhat-release ]; then
RPM_USE_PYTHON_3=1
elif [ "$RPM_DIST_NAME" = "rhel" -a "$RPM_DIST_VERSION" -ge 8 ]; then
RPM_USE_PYTHON_3=1
elif [ "$RPM_DIST_NAME" = "centos" -a "$RPM_DIST_VERSION" -ge 8 ]; then
RPM_USE_PYTHON_3=1
else
RPM_USE_PYTHON_3=0
fi
@@ -1338,18 +1336,18 @@ letsencrypt==0.7.0 \
--hash=sha256:105a5fb107e45bcd0722eb89696986dcf5f08a86a321d6aef25a0c7c63375ade \
--hash=sha256:c36e532c486a7e92155ee09da54b436a3c420813ec1c590b98f635d924720de9
certbot==0.40.1 \
--hash=sha256:afe4d7edc61d4cab8b6f7ab7611d66aaba67d9f0404fa2760bd1cc430b2ec9ec \
--hash=sha256:8dc81b3044cf401c55fa36c30893887fcb92657df1d76a8848059683df3b10d1
acme==0.40.1 \
--hash=sha256:a85387c26fb4fc24511b2579b8c61177b3175fd25e130c5be95a840d9f67d54f \
--hash=sha256:33bf8686408d5b6b79886a9a43aee691ca754408deaec4fb2bb17b9af48a5ffc
certbot-apache==0.40.1 \
--hash=sha256:6c4a4e21a17bd8120056595e5670c9a0f86756da0ad269196e8d56fc1b9fec82 \
--hash=sha256:16404e9e404f0b98c18bd752fad812a45ef7f9b0efa9bbc8589f24a94e67de7c
certbot-nginx==0.40.1 \
--hash=sha256:acdbfc4ab75ebc810264ee1248332f8e857c5e7776717b7cd53c4ceceb2b4d34 \
--hash=sha256:014fdda80647ad9e67019b16c7cdaee5d21a750b393bcb98e1300615cc930f4f
certbot==0.38.0 \
--hash=sha256:618abf3ae17c2fc3cb99baa4bf000dd5e2d7875b7811f5ef1edf6ebd7a33945f \
--hash=sha256:c27712101794e3adf54f3a3067c63be5caa507a930a79865bc654b6864121c6b
acme==0.38.0 \
--hash=sha256:6231571b4a94d6d621b28bef6f6d4846b3c2ebca840f9718d3212036c3bd2af8 \
--hash=sha256:1c1e9c0826a8f72d670b0ca28b7e6392ce4781eb33222f35133705b6551885d8
certbot-apache==0.38.0 \
--hash=sha256:0b5a2c2bcc430470b5131941ebdfde0a13e28dec38918c1a4ebea5dd35ad38bc \
--hash=sha256:2d335543e0ae9292303238736907ce6b321ac49eb49fe4e0b775abdc0ba57c62
certbot-nginx==0.38.0 \
--hash=sha256:af82944e171d2e93c81438b185f8051e742c6f47f7382cb1a647b1c7ca2b53f2 \
--hash=sha256:cecd1fa3de6e19980fdb9c3b3269b15b7da71b5748ee7ae5caddcc18dbb208ac
UNLIKELY_EOF
# -------------------------------------------------------------------------

View File

@@ -2,8 +2,8 @@
# Avoid false warnings because certbot packages are not installed in the thread that executes
# the coverage: indeed, certbot is launched as a CLI from a subprocess.
disable_warnings = module-not-imported,no-data-collected
omit = **/*_test.py,**/tests/*,**/dns_common*,**/certbot_nginx/_internal/parser_obj.py
omit = **/*_test.py,**/tests/*,**/dns_common*,**/certbot_nginx/parser_obj.py
[report]
# Exclude unit tests in coverage during integration tests.
omit = **/*_test.py,**/tests/*,**/dns_common*,**/certbot_nginx/_internal/parser_obj.py
omit = **/*_test.py,**/tests/*,**/dns_common*,**/certbot_nginx/parser_obj.py

View File

@@ -0,0 +1,171 @@
import shutil
import subprocess
import os
import pkg_resources
import getpass
def construct_apache_config_dir(apache_root, http_port, https_port, key_path=None,
cert_path=None, wtf_prefix='le'):
config_path = os.path.join(apache_root, 'config')
shutil.copytree('/etc/apache2', config_path, symlinks=True)
webroot_path = os.path.join(apache_root, 'www')
os.mkdir(webroot_path)
with open(os.path.join(webroot_path, 'index.html'), 'w') as file_h:
file_h.write('Hello World!')
main_config_path = os.path.join(config_path, 'apache2.conf')
with open(main_config_path, 'w') as file_h:
file_h.write('''\
ServerRoot "{config}"
DefaultRuntimeDir ${{APACHE_RUN_DIR}}
PidFile ${{APACHE_PID_FILE}}
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
User ${{APACHE_RUN_USER}}
Group ${{APACHE_RUN_GROUP}}
HostnameLookups Off
ErrorLog ${{APACHE_LOG_DIR}}/error.log
LogLevel warn
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
Include ports.conf
<Directory />
Options FollowSymLinks
AllowOverride None
Require all denied
</Directory>
<Directory /usr/share>
AllowOverride None
Require all granted
</Directory>
<Directory {webroot}/>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
AccessFileName .htaccess
<FilesMatch "^\.ht">
Require all denied
</FilesMatch>
LogFormat "%v:%p %h %l %u %t \\"%r\\" %>s %O \\"%{{Referer}}i\\" \\"%{{User-Agent}}i\\"" vhost_combined
LogFormat "%h %l %u %t \\"%r\\" %>s %O \\"%{{Referer}}i\\" \\"%{{User-Agent}}i\\"" combined
LogFormat "%h %l %u %t \\"%r\\" %>s %O" common
LogFormat "%{{Referer}}i -> %U" referer
LogFormat "%{{User-agent}}i" agent
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf
'''.format(config=config_path, webroot=webroot_path))
with open(os.path.join(config_path, 'ports.conf'), 'w') as file_h:
file_h.write('''\
Listen {http}
<IfModule ssl_module>
Listen {https}
</IfModule>
<IfModule mod_gnutls.c>
Listen {https}
</IfModule>
'''.format(http=http_port, https=https_port))
new_environ = os.environ.copy()
new_environ['APACHE_CONFDIR'] = config_path
run_path = os.path.join(apache_root, 'run')
lock_path = os.path.join(apache_root, 'lock')
logs_path = os.path.join(apache_root, 'logs')
os.mkdir(run_path)
os.mkdir(lock_path)
os.mkdir(logs_path)
user = getpass.getuser()
user = user if user != 'root' else 'www-data'
group = user
pid_file = os.path.join(run_path, 'apache.pid')
with open(os.path.join(config_path, 'envvars'), 'w') as file_h:
file_h.write('''\
unset HOME
export APACHE_RUN_USER={user}
export APACHE_RUN_GROUP={group}
export APACHE_PID_FILE={pid_file}
export APACHE_RUN_DIR={run_path}
export APACHE_LOCK_DIR={lock_path}
export APACHE_LOG_DIR={logs_path}
export LANG=C
'''.format(user=user, group=group, pid_file=pid_file,
run_path=run_path, lock_path=lock_path, logs_path=logs_path))
new_environ['APACHE_RUN_USER'] = user
new_environ['APACHE_RUN_GROUP'] = group
new_environ['APACHE_PID_FILE'] = pid_file
new_environ['APACHE_RUN_DIR'] = run_path
new_environ['APACHE_LOCK_DIR'] = lock_path
new_environ['APACHE_LOG_DIR'] = logs_path
le_host = 'apache.{0}.wtf'.format(wtf_prefix)
with open(os.path.join(config_path, 'sites-available', '000-default.conf'), 'w') as file_h:
file_h.write('''\
<VirtualHost *:{http}>
ServerAdmin webmaster@localhost
ServerName {le_host}
DocumentRoot {webroot}
ErrorLog ${{APACHE_LOG_DIR}}/error.log
CustomLog ${{APACHE_LOG_DIR}}/access.log combined
</VirtualHost>
'''.format(http=http_port, le_host=le_host, webroot=webroot_path))
key_path = key_path if key_path \
else pkg_resources.resource_filename('certbot_integration_tests', 'assets/key.pem')
cert_path = cert_path if cert_path \
else pkg_resources.resource_filename('certbot_integration_tests', 'assets/cert.pem')
with open(os.path.join(config_path, 'sites-available', 'default-ssl.conf'), 'w') as file_h:
file_h.write('''\
<IfModule mod_ssl.c>
<VirtualHost _default_:{https}>
ServerAdmin webmaster@localhost
ServerName {le_host}
DocumentRoot {webroot}
ErrorLog ${{APACHE_LOG_DIR}}/error.log
CustomLog ${{APACHE_LOG_DIR}}/access.log combined
SSLEngine on
SSLCertificateFile {cert_path}
SSLCertificateKeyFile {key_path}
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>
'''.format(https=https_port, le_host=le_host, webroot=webroot_path,
cert_path=cert_path, key_path=key_path))
return new_environ, config_path, pid_file
def test():
env = construct_apache_config_dir('/tmp/test1', 5001, 5002)
subprocess.call(['apache2ctl', '-DFOREGROUND'], env=env)

View File

@@ -0,0 +1,51 @@
import errno
import os
import signal
import subprocess
from certbot_integration_tests.certbot_tests import context as certbot_context
from certbot_integration_tests.apache_tests import apache_config
from certbot_integration_tests.utils import certbot_call
class IntegrationTestsContext(certbot_context.IntegrationTestsContext):
def __init__(self, request):
super(IntegrationTestsContext, self).__init__(request)
subprocess.check_output(['chmod', '+x', self.workspace])
self.apache_root = os.path.join(self.workspace, 'apache')
os.mkdir(self.apache_root)
self.env, self.config_dir, self.pid_file = apache_config.construct_apache_config_dir(
self.apache_root, self.http_01_port, self.tls_alpn_01_port,
wtf_prefix=self.worker_id)
def cleanup(self):
self._stop_apache()
super(IntegrationTestsContext, self).cleanup()
def certbot_test_apache(self, args):
command = ['--authenticator', 'apache', '--installer', 'apache',
'--apache-server-root', self.config_dir,
'--apache-challenge-location', self.apache_root]
command.extend(args)
return certbot_call.certbot_test(
command, self.directory_url, self.http_01_port, self.tls_alpn_01_port,
self.config_dir, self.workspace, env=self.env, force_renew=True)
def _stop_apache(self):
try:
with open(self.pid_file) as file_h:
pid = int(file_h.read().strip())
except BaseException:
pid = None
if pid:
try:
os.kill(pid, signal.SIGTERM)
except OSError as err:
# Ignore "No such process" error, Apache may already be stopped.
if err.errno != errno.ESRCH:
raise

View File

@@ -0,0 +1,18 @@
import pytest
from certbot_integration_tests.apache_tests import context as apache_context
@pytest.fixture()
def context(request):
# Fixture request is a built-in pytest fixture describing current test request.
integration_test_context = apache_context.IntegrationTestsContext(request)
try:
yield integration_test_context
finally:
integration_test_context.cleanup()
def test_it(context):
command = ['-d', 'apache.{0}.wtf'.format(context.worker_id)]
context.certbot_test_apache(command)

View File

@@ -62,6 +62,11 @@ def test_registration_override(context):
context.certbot(['unregister'])
context.certbot(['register', '--email', 'ex1@domain.org,ex2@domain.org'])
# TODO: When `certbot register --update-registration` is fully deprecated,
# delete the two following deprecated uses
context.certbot(['register', '--update-registration', '--email', 'ex1@domain.org'])
context.certbot(['register', '--update-registration', '--email', 'ex1@domain.org,ex2@domain.org'])
context.certbot(['update_account', '--email', 'example@domain.org'])
context.certbot(['update_account', '--email', 'ex1@domain.org,ex2@domain.org'])
@@ -589,21 +594,3 @@ def test_ocsp_status_live(context):
assert output.count('INVALID') == 1, 'Expected {0} to be INVALID'.format(cert)
assert output.count('REVOKED') == 1, 'Expected {0} to be REVOKED'.format(cert)
def test_dry_run_deactivate_authzs(context):
"""Test that Certbot deactivates authorizations when performing a dry run"""
name = context.get_domain('dry-run-authz-deactivation')
args = ['certonly', '--cert-name', name, '-d', name, '--dry-run']
log_line = 'Recreating order after authz deactivation'
# First order will not need deactivation
context.certbot(args)
with open(join(context.workspace, 'logs', 'letsencrypt.log'), 'r') as f:
assert log_line not in f.read(), 'First order should not have had any authz reuse'
# Second order will require deactivation
context.certbot(args)
with open(join(context.workspace, 'logs', 'letsencrypt.log'), 'r') as f:
assert log_line in f.read(), 'Second order should have been recreated due to authz reuse'

View File

@@ -125,7 +125,6 @@ class ACMEServer(object):
environ = os.environ.copy()
environ['PEBBLE_VA_NOSLEEP'] = '1'
environ['PEBBLE_WFE_NONCEREJECT'] = '0'
environ['PEBBLE_AUTHZREUSE'] = '100'
self._launch_process(
[pebble_path, '-config', pebble_config_path, '-dnsserver', '127.0.0.1:8053'],

View File

@@ -11,7 +11,7 @@ from certbot_integration_tests.utils.constants import *
def certbot_test(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
config_dir, workspace, force_renew=True):
config_dir, workspace, env=None, force_renew=True):
"""
Invoke the certbot executable available in PATH in a test context for the given args.
The test context consists in running certbot in debug mode, with various flags suitable
@@ -23,18 +23,20 @@ def certbot_test(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
:param int tls_alpn_01_port: port for the TLS-ALPN-01 challenges
:param str config_dir: certbot configuration directory to use
:param str workspace: certbot current directory to use
:param obj env: the environment variables to use (default: None, then current env will be used)
:param bool force_renew: set False to not force renew existing certificates (default: True)
:return: stdout as string
:rtype: str
"""
new_environ = env if env else os.environ.copy()
command, env = _prepare_args_env(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
config_dir, workspace, force_renew)
config_dir, workspace, force_renew, new_environ)
return subprocess.check_output(command, universal_newlines=True, cwd=workspace, env=env)
def _prepare_environ(workspace):
new_environ = os.environ.copy()
def _prepare_environ(workspace, new_environ):
new_environ = new_environ.copy()
new_environ['TMPDIR'] = workspace
# So, pytest is nice, and a little too nice for our usage.
@@ -80,9 +82,9 @@ def _compute_additional_args(workspace, environ, force_renew):
def _prepare_args_env(certbot_args, directory_url, http_01_port, tls_alpn_01_port,
config_dir, workspace, force_renew):
config_dir, workspace, force_renew, new_environ):
new_environ = _prepare_environ(workspace)
new_environ = _prepare_environ(workspace, new_environ)
additional_args = _compute_additional_args(workspace, new_environ, force_renew)
command = [

View File

@@ -14,7 +14,7 @@ RUN /opt/certbot/src/letsencrypt-auto-source/letsencrypt-auto --os-packages-only
# the above is not likely to change, so by putting it further up the
# Dockerfile we make sure we cache as much as possible
COPY certbot/setup.py certbot/README.rst certbot/CHANGELOG.md certbot/MANIFEST.in linter_plugin.py tox.cover.py tox.ini .pylintrc /opt/certbot/src/
COPY setup.py README.rst CHANGELOG.md MANIFEST.in linter_plugin.py tox.cover.py tox.ini .pylintrc /opt/certbot/src/
# all above files are necessary for setup.py, however, package source
# code directory has to be copied separately to a subdirectory...
@@ -38,7 +38,7 @@ ENV PATH /opt/certbot/venv/bin:$PATH
RUN /opt/certbot/venv/bin/python \
/opt/certbot/src/tools/pip_install_editable.py \
/opt/certbot/src/acme \
/opt/certbot/src/certbot \
/opt/certbot/src \
/opt/certbot/src/certbot-apache \
/opt/certbot/src/certbot-nginx \
/opt/certbot/src/certbot-compatibility-test

View File

@@ -1,5 +1,6 @@
include LICENSE.txt
include README.rst
recursive-include docs *
include certbot_compatibility_test/configurators/apache/a2enmod.sh
include certbot_compatibility_test/configurators/apache/a2dismod.sh
include certbot_compatibility_test/configurators/apache/Dockerfile

View File

@@ -6,10 +6,10 @@ import subprocess
import mock
import zope.interface
from certbot._internal import configuration
from certbot import configuration
from certbot import errors as le_errors
from certbot import util as certbot_util
from certbot_apache._internal import entrypoint
from certbot_apache import entrypoint
from certbot_compatibility_test import errors
from certbot_compatibility_test import interfaces
from certbot_compatibility_test import util
@@ -18,6 +18,7 @@ from certbot_compatibility_test.configurators import common as configurators_com
@zope.interface.implementer(interfaces.IConfiguratorProxy)
class Proxy(configurators_common.Proxy):
# pylint: disable=too-many-instance-attributes
"""A common base for Apache test configurators"""
def __init__(self, args):
@@ -27,7 +28,7 @@ class Proxy(configurators_common.Proxy):
self.modules = self.server_root = self.test_conf = self.version = None
patch = mock.patch(
"certbot_apache._internal.configurator.display_ops.select_vhost")
"certbot_apache.configurator.display_ops.select_vhost")
mock_display = patch.start()
mock_display.side_effect = le_errors.PluginError(
"Unable to determine vhost")

View File

@@ -4,7 +4,7 @@ import os
import shutil
import tempfile
from certbot._internal import constants
from certbot import constants
from certbot_compatibility_test import errors
from certbot_compatibility_test import util
@@ -13,6 +13,7 @@ logger = logging.getLogger(__name__)
class Proxy(object):
# pylint: disable=too-many-instance-attributes
"""A common base for compatibility test configurators"""
@classmethod

View File

@@ -7,9 +7,9 @@ import zope.interface
from acme.magic_typing import Set # pylint: disable=unused-import, no-name-in-module
from certbot._internal import configuration
from certbot_nginx._internal import configurator
from certbot_nginx._internal import constants
from certbot import configuration
from certbot_nginx import configurator
from certbot_nginx import constants
from certbot_compatibility_test import errors
from certbot_compatibility_test import interfaces
from certbot_compatibility_test import util
@@ -18,6 +18,7 @@ from certbot_compatibility_test.configurators import common as configurators_com
@zope.interface.implementer(interfaces.IConfiguratorProxy)
class Proxy(configurators_common.Proxy):
# pylint: disable=too-many-instance-attributes
"""A common base for Nginx test configurators"""
def load_config(self):

View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCsREbM+UcfsgDy2w56AVGyxsO0HVsbEZHHoEzv7qksIwFgRYMp
rowwIxD450RQQqjvw9IoXlMVmr1t5szn5KXn9JRO9T5KNCCy3VPx75WBcp6kzd9Q
2HS1OEOtpilNnDkZ+TJfdgFWPUBYj2o4Md1hPmcvagiIJY5U6speka2bjwIDAQAB
AoGANCMZ9pF/mDUsmlP4Rq69hkkoFAxKdZ/UqkF256so4mXZ1cRUFTpxzWPfkCWW
hGAYdzCiG3uo08IYkPmojIqkN1dk5Hcq5eQAmshaPkQHQCHjmPjjcNvgjIXQoGUf
TpDU2hbY4UAlJlj4ZLh+jGP5Zq8/WrNi8RsI3v9Nagfp/FECQQDgi2q8p1gX0TNh
d1aEKmSXkR3bxkyFk6oS+pBrAG3+yX27ZayN6Rx6DOs/FcBsOu7fX3PYBziDeEWe
Lkf1P743AkEAxGYT/LY3puglSz4iJZZzWmRCrVOg41yhfQ+F1BRX43/2vtoU5GyM
2lUn1vQ2e/rfmnAvfJxc90GeZCIHB1ihaQJBALH8UMLxMtbOMJgVbDKfF9U8ZhqK
+KT5A1q/2jG2yXmoZU1hroFeQgBMtTvwFfK0VBwjIUQflSBA+Y4EyW0Q9ckCQGvd
jHitM1+N/H2YwHRYbz5j9mLvnVuCEod3MQ9LpQGj1Eb5y6OxIqL/RgQ+2HW7UXem
yc3sqvp5pZ5lOesE+JECQETPI64gqxlTIs3nErNMpMynUuTWpaElOcIJTT6icLzB
Xix67kKXjROO5D58GEYkM0Yi5k7YdUPoQBW7MoIrSIA=
-----END RSA PRIVATE KEY-----

View File

@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDCzejLjo8wsz0avrylt7HQyF0+vsKritF70EGmc64cV0XfkCTR
o+vMXBXMuUY6Kv3hTXV7klgkNYmL7gXAsFGQ4B9qeMnkYn0GcQdI51u076y/26Fu
37uJg45Q6eApKInJSsyLVMcAT4HUJ6fFnUodFAKR7vTzOQryNW7Et4gA4wIDAQAB
AoGAKiAU40/krwdTg2ETslJS5W8ums7tkeLnAfs69x+02vQUbA/jpmHoL70KCcdW
5GU/mWUCrsIqxUm+gL/sBosaV/TF256qUBt2qQCZTN8MbDaNSYiiMnucOfbWdIqx
Zgls6GUoXQvPic9RUoFSlgfSjo5ezz6el5ihvRMp+wbk24ECQQD3oz4hN029DSZo
Y3+flmBn77gA0BMUvLa6hmt9b3xT5U/ToCLfbmUvpx7zV1g5era2y9qt/o3UtAbW
1zCVETgzAkEAyWHv/+RnSXp8/D4YwTVWyeWi862uNBPkuLGP/0zASdwBfBK3uBls
+VumfSCtp0kt2AXXmScg1fkHdeAVT6AkkQJBAJb2XRnCrRFiwtdAULzo3zx9Vp6o
OfmaUYrEByMgo5pBYLiSFrA+jFDQgH238YCY3mnxPA517+CLHuA5rtQw+yECQCfm
gL/pyFE1tLfhsdPuNpDwL9YqLl7hJis1+zrxQRQhRCYKK16NoxrQ/u7B38ZKaIvp
tGsC5q2elszTJkXNjBECQCVE9QCVx056vHVdPWM8z3GAeV3sJQ01HLLjebTEEz6G
jH54gk+YYPp4kjCvVUykbnB58BY2n88GQt5Jj5eLuMo=
-----END RSA PRIVATE KEY-----

View File

@@ -8,13 +8,13 @@ import tarfile
import josepy as jose
from certbot.tests import util as test_util
from certbot._internal import constants
from acme import test_util
from certbot import constants
from certbot_compatibility_test import errors
_KEY_BASE = "rsa2048_key.pem"
_KEY_BASE = "rsa1024_key.pem"
KEY_PATH = test_util.vector_path(_KEY_BASE)
KEY = test_util.load_pyopenssl_private_key(_KEY_BASE)
JWK = jose.JWKRSA(key=test_util.load_rsa_private_key(_KEY_BASE))

Some files were not shown because too many files have changed in this diff Show More