Compare commits

...

16 Commits

Author SHA1 Message Date
Brad Warren
2cbacd1219 test quiet and fast 2019-06-14 13:00:08 -07:00
Adrien Ferrand
b91dc709bf Clear implementation 2019-06-14 21:00:40 +02:00
Adrien Ferrand
8e47b1cca6 Update acme_server.py 2019-06-14 19:59:07 +02:00
Adrien Ferrand
675428e43a Update proxy.py 2019-06-14 19:56:49 +02:00
Adrien Ferrand
325c611d72 Update proxy.py 2019-06-14 19:54:49 +02:00
Adrien Ferrand
6ce34d0447 Update acme_server.py 2019-06-14 19:25:02 +02:00
Adrien Ferrand
a9921351fb Update proxy.py 2019-06-14 19:22:49 +02:00
Adrien Ferrand
d7d787f225 Update constants.py 2019-06-14 19:13:22 +02:00
Adrien Ferrand
d11408b46b Give proxy process to the ACMEServer context manager 2019-06-14 17:17:02 +02:00
Adrien Ferrand
563ed73abc Python 2/3 cross-compatibility 2019-06-14 17:16:44 +02:00
Adrien Ferrand
c3cd7412b9 Merge branch 'master' into certbot-ci-python-proxy
# Conflicts:
#	certbot-ci/certbot_integration_tests/utils/acme_server.py
2019-06-14 16:59:23 +02:00
Adrien Ferrand
f6c7fe8b2d Resolve from the path 2019-06-14 16:53:39 +02:00
Adrien Ferrand
d97c395133 Working logic 2019-06-14 16:52:03 +02:00
Adrien Ferrand
d60b140986 Refactor proxy config 2019-06-14 15:58:36 +02:00
Adrien Ferrand
a8751deeaa Work in progress 2019-06-13 23:56:42 +02:00
Adrien Ferrand
bd011375ae Create a python proxy 2019-06-13 15:39:07 +02:00
4 changed files with 60 additions and 219 deletions

View File

@@ -30,96 +30,6 @@ extended-test-suite: &extended-test-suite
matrix: matrix:
include: include:
# Main test suite
- python: "2.7"
env: ACME_SERVER=pebble TOXENV=integration
sudo: required
services: docker
<<: *not-on-master
# This job is always executed, including on master
- python: "2.7"
env: TOXENV=py27-cover FYI="py27 tests + code coverage"
- python: "2.7"
env: TOXENV=lint
<<: *not-on-master
- python: "3.4"
env: TOXENV=mypy
<<: *not-on-master
- python: "3.5"
env: TOXENV=mypy
<<: *not-on-master
- python: "2.7"
env: TOXENV='py27-{acme,apache,certbot,dns,nginx}-oldest'
sudo: required
services: docker
<<: *not-on-master
- python: "3.4"
env: TOXENV=py34
sudo: required
services: docker
<<: *not-on-master
- python: "3.7"
dist: xenial
env: TOXENV=py37
sudo: required
services: docker
<<: *not-on-master
- sudo: required
env: TOXENV=apache_compat
services: docker
before_install:
addons:
<<: *not-on-master
- sudo: required
env: TOXENV=le_auto_trusty
services: docker
before_install:
addons:
<<: *not-on-master
- python: "2.7"
env: TOXENV=apacheconftest-with-pebble
sudo: required
services: docker
<<: *not-on-master
- python: "2.7"
env: TOXENV=nginxroundtrip
<<: *not-on-master
# Extended test suite on cron jobs and pushes to tested branches other than master
- sudo: required
env: TOXENV=nginx_compat
services: docker
before_install:
addons:
<<: *extended-test-suite
- python: "2.7"
env:
- TOXENV=travis-test-farm-apache2
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "2.7"
env:
- TOXENV=travis-test-farm-leauto-upgrades
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
git:
depth: false # This is needed to have the history to checkout old versions of certbot-auto.
<<: *extended-test-suite
- python: "2.7"
env:
- TOXENV=travis-test-farm-certonly-standalone
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "2.7"
env:
- TOXENV=travis-test-farm-sdists
- secure: "f+j/Lj9s1lcuKo5sEFrlRd1kIAMnIJI4z0MTI7QF8jl9Fkmbx7KECGzw31TNgzrOSzxSapHbcueFYvNCLKST+kE/8ogMZBbwqXfEDuKpyF6BY3uYoJn+wPVE5pIb8Hhe08xPte8TTDSMIyHI3EyTfcAKrIreauoArePvh/cRvSw="
<<: *extended-test-suite
- python: "3.7"
dist: xenial
env: TOXENV=py37 CERTBOT_NO_PIN=1
<<: *extended-test-suite
- python: "2.7" - python: "2.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required sudo: required
@@ -130,12 +40,6 @@ matrix:
sudo: required sudo: required
services: docker services: docker
<<: *extended-test-suite <<: *extended-test-suite
- python: "2.7"
env: TOXENV=py27-certbot-oldest
<<: *extended-test-suite
- python: "2.7"
env: TOXENV=py27-nginx-oldest
<<: *extended-test-suite
- python: "2.7" - python: "2.7"
env: ACME_SERVER=boulder-v1 TOXENV=integration-certbot-oldest env: ACME_SERVER=boulder-v1 TOXENV=integration-certbot-oldest
sudo: required sudo: required
@@ -156,19 +60,6 @@ matrix:
sudo: required sudo: required
services: docker services: docker
<<: *extended-test-suite <<: *extended-test-suite
- python: "3.4"
env: TOXENV=py34
<<: *extended-test-suite
- python: "3.5"
env: TOXENV=py35
<<: *extended-test-suite
- python: "3.6"
env: TOXENV=py36
<<: *extended-test-suite
- python: "3.7"
dist: xenial
env: TOXENV=py37
<<: *extended-test-suite
- python: "3.4" - python: "3.4"
env: ACME_SERVER=boulder-v1 TOXENV=integration env: ACME_SERVER=boulder-v1 TOXENV=integration
sudo: required sudo: required
@@ -211,44 +102,6 @@ matrix:
sudo: required sudo: required
services: docker services: docker
<<: *extended-test-suite <<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_xenial
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_jessie
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=le_auto_centos6
services: docker
<<: *extended-test-suite
- sudo: required
env: TOXENV=docker_dev
services: docker
addons:
apt:
packages: # don't install nginx and apache
- libaugeas0
<<: *extended-test-suite
- language: generic
env: TOXENV=py27
os: osx
addons:
homebrew:
packages:
- augeas
- python2
<<: *extended-test-suite
- language: generic
env: TOXENV=py3
os: osx
addons:
homebrew:
packages:
- augeas
- python3
<<: *extended-test-suite
# container-based infrastructure # container-based infrastructure
sudo: false sudo: false
@@ -274,13 +127,3 @@ after_success: '[ "$TOXENV" == "py27-cover" ] && codecov -F linux'
notifications: notifications:
email: false email: false
irc:
channels:
# This is set to a secure variable to prevent forks from sending
# notifications. This value was created by installing
# https://github.com/travis-ci/travis.rb and running
# `travis encrypt "chat.freenode.net#certbot-devel"`.
- secure: "EWW66E2+KVPZyIPR8ViENZwfcup4Gx3/dlimmAZE0WuLwxDCshBBOd3O8Rf6pBokEoZlXM5eDT6XdyJj8n0DLslgjO62pExdunXpbcMwdY7l1ELxX2/UbnDTE6UnPYa09qVBHNG7156Z6yE0x2lH4M9Ykvp0G0cubjPQHylAwo0="
on_cancel: never
on_success: never
on_failure: always

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
"""Module to setup an ACME CA server environment able to run multiple tests in parallel""" """Module to setup an ACME CA server environment able to run multiple tests in parallel"""
from __future__ import print_function from __future__ import print_function
import json
import tempfile import tempfile
import time import time
import os import os
@@ -10,10 +11,9 @@ import sys
from os.path import join from os.path import join
import requests import requests
import json
import yaml import yaml
from certbot_integration_tests.utils import misc from certbot_integration_tests.utils import misc, proxy
from certbot_integration_tests.utils.constants import * from certbot_integration_tests.utils.constants import *
@@ -23,13 +23,19 @@ class ACMEServer(object):
(eg. challenges ports). ACMEServer is also a context manager, and so can be used to (eg. challenges ports). ACMEServer is also a context manager, and so can be used to
ensure ACME server is started/stopped upon context enter/exit. ensure ACME server is started/stopped upon context enter/exit.
""" """
def __init__(self, acme_xdist, start, stop): def __init__(self, acme_xdist, start, server_cleanup):
self._proxy_process = None
self._server_cleanup = server_cleanup
self.acme_xdist = acme_xdist self.acme_xdist = acme_xdist
self.start = start self.start = start
self.stop = stop
def stop(self):
if self._proxy_process:
self._proxy_process.terminate()
self._server_cleanup()
def __enter__(self): def __enter__(self):
self.start() self._proxy_process = self.start()
return self.acme_xdist return self.acme_xdist
def __exit__(self, exc_type, exc_val, exc_tb): def __exit__(self, exc_type, exc_val, exc_tb):
@@ -52,14 +58,15 @@ def setup_acme_server(acme_server, nodes, proxy=True):
""" """
acme_type = 'pebble' if acme_server == 'pebble' else 'boulder' acme_type = 'pebble' if acme_server == 'pebble' else 'boulder'
acme_xdist = _construct_acme_xdist(acme_server, nodes) acme_xdist = _construct_acme_xdist(acme_server, nodes)
workspace, stop = _construct_workspace(acme_type) workspace, server_cleanup = _construct_workspace(acme_type)
def start(): def start():
if proxy: proxy_process = _prepare_traefik_proxy(acme_xdist) if proxy else None
_prepare_traefik_proxy(workspace, acme_xdist)
_prepare_acme_server(workspace, acme_type, acme_xdist) _prepare_acme_server(workspace, acme_type, acme_xdist)
return ACMEServer(acme_xdist, start, stop) return proxy_process
return ACMEServer(acme_xdist, start, server_cleanup)
def _construct_acme_xdist(acme_server, nodes): def _construct_acme_xdist(acme_server, nodes):
@@ -155,60 +162,16 @@ def _prepare_acme_server(workspace, acme_type, acme_xdist):
raise raise
def _prepare_traefik_proxy(workspace, acme_xdist): def _prepare_traefik_proxy(acme_xdist):
"""Configure and launch Traefik, the HTTP reverse proxy""" """Configure and launch Traefik, the HTTP reverse proxy"""
print('=> Starting traefik instance deployment...') print('=> Configuring the HTTP proxy...')
instance_path = join(workspace, 'traefik') mapping = {r'.+\.{0}\.wtf'.format(node): 'http://127.0.0.1:{0}'.format(port)
traefik_subnet = '10.33.33' for node, port in acme_xdist['http_port'].items()}
try: command = [sys.executable, proxy.__file__, str(HTTP_01_PORT), json.dumps(mapping)]
os.mkdir(instance_path) process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
print('=> Finished configuring the HTTP proxy.')
with open(join(instance_path, 'docker-compose.yml'), 'w') as file_h: return process
file_h.write('''\
version: '3'
services:
traefik:
image: traefik
command: --api --rest
ports:
- {http_01_port}:80
- {traefik_api_port}:8080
networks:
traefiknet:
ipv4_address: {traefik_subnet}.2
networks:
traefiknet:
ipam:
config:
- subnet: {traefik_subnet}.0/24
'''.format(traefik_subnet=traefik_subnet,
traefik_api_port=TRAEFIK_API_PORT,
http_01_port=HTTP_01_PORT))
_launch_command(['docker-compose', 'up', '--force-recreate', '-d'], cwd=instance_path)
misc.check_until_timeout('http://localhost:{0}/api'.format(TRAEFIK_API_PORT))
config = {
'backends': {
node: {
'servers': {node: {'url': 'http://{0}.1:{1}'.format(traefik_subnet, port)}}
} for node, port in acme_xdist['http_port'].items()
},
'frontends': {
node: {
'backend': node, 'passHostHeader': True,
'routes': {node: {'rule': 'HostRegexp: {{subdomain:.+}}.{0}.wtf'.format(node)}}
} for node in acme_xdist['http_port'].keys()
}
}
response = requests.put('http://localhost:{0}/api/providers/rest'.format(TRAEFIK_API_PORT),
data=json.dumps(config))
response.raise_for_status()
print('=> Finished traefik instance deployment.')
except BaseException:
print('Error while setting up traefik instance.')
raise
def _launch_command(command, cwd=os.getcwd()): def _launch_command(command, cwd=os.getcwd()):

View File

@@ -2,7 +2,6 @@
HTTP_01_PORT = 5002 HTTP_01_PORT = 5002
TLS_ALPN_01_PORT = 5001 TLS_ALPN_01_PORT = 5001
CHALLTESTSRV_PORT = 8055 CHALLTESTSRV_PORT = 8055
TRAEFIK_API_PORT = 8056
BOULDER_V1_DIRECTORY_URL = 'http://localhost:4000/directory' BOULDER_V1_DIRECTORY_URL = 'http://localhost:4000/directory'
BOULDER_V2_DIRECTORY_URL = 'http://localhost:4001/directory' BOULDER_V2_DIRECTORY_URL = 'http://localhost:4001/directory'
PEBBLE_DIRECTORY_URL = 'https://localhost:14000/dir' PEBBLE_DIRECTORY_URL = 'https://localhost:14000/dir'

View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python
import json
import sys
import re
import requests
from six.moves import BaseHTTPServer
from certbot_integration_tests.utils.misc import GracefulTCPServer
def _create_proxy(mapping):
class ProxyHandler(BaseHTTPServer.BaseHTTPRequestHandler):
def do_GET(self):
headers = {key.lower(): value for key, value in self.headers.items()}
backend = [backend for pattern, backend in mapping.items()
if re.match(pattern, headers['host'])][0]
response = requests.get(backend + self.path, headers=headers)
self.send_response(response.status_code)
for key, value in response.headers.items():
self.send_header(key, value)
self.end_headers()
self.wfile.write(response.content)
return ProxyHandler
if __name__ == '__main__':
http_port = int(sys.argv[1])
port_mapping = json.loads(sys.argv[2])
httpd = GracefulTCPServer(('', http_port), _create_proxy(port_mapping))
try:
httpd.serve_forever()
except KeyboardInterrupt:
pass