diff --git a/docker-compose.yml b/docker-compose.yml index 7bca8697e..87840f026 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: boulder: # To minimize fetching this should be the same version used below - image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-06-28 + image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08 environment: FAKE_DNS: 10.77.77.77 PKCS11_PROXY_SOCKET: tcp://boulder-hsm:5657 @@ -55,7 +55,7 @@ services: working_dir: /go/src/github.com/letsencrypt/boulder bhsm: # To minimize fetching this should be the same version used above - image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-06-28 + image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08 environment: PKCS11_DAEMON_SOCKET: tcp://0.0.0.0:5657 command: /usr/local/bin/pkcs11-daemon /usr/lib/softhsm/libsofthsm2.so @@ -77,7 +77,7 @@ services: logging: driver: none netaccess: - image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-06-28 + image: letsencrypt/boulder-tools-go${TRAVIS_GO_VERSION:-1.12}:2019-04-08 environment: GO111MODULE: "on" GOFLAGS: "-mod=vendor" diff --git a/test.sh b/test.sh index 109c031f0..416876a6a 100755 --- a/test.sh +++ b/test.sh @@ -110,9 +110,9 @@ if [[ "$RUN" =~ "integration" ]] ; then args+=("--skip-setup") fi - source ${CERTBOT_PATH:-/certbot}/${VENV_NAME:-venv3}/bin/activate + source ${CERTBOT_PATH:-/certbot}/${VENV_NAME:-venv}/bin/activate DIRECTORY=http://boulder:4000/directory \ - python3 test/integration-test.py "${args[@]}" + python2 test/integration-test.py "${args[@]}" fi # Test that just ./start.py works, which is a proxy for testing that diff --git a/test/boulder-tools/Dockerfile.tmpl b/test/boulder-tools/Dockerfile.tmpl index dabf5b2be..384dda0ec 100644 --- a/test/boulder-tools/Dockerfile.tmpl +++ b/test/boulder-tools/Dockerfile.tmpl @@ -9,5 +9,4 @@ RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" WORKDIR $GOPATH ADD build.sh /tmp/build.sh -ADD requirements.txt /tmp/requirements.txt RUN /tmp/build.sh diff --git a/test/boulder-tools/build.sh b/test/boulder-tools/build.sh index 2562aede7..d4da04f55 100755 --- a/test/boulder-tools/build.sh +++ b/test/boulder-tools/build.sh @@ -51,8 +51,6 @@ git clone https://github.com/certbot/certbot /certbot cd /certbot ./letsencrypt-auto --os-packages-only ./tools/venv3.py -source venv3/bin/activate -pip install -r /tmp/requirements.txt cd - # Install pkcs11-proxy. Checked out commit was master HEAD at time diff --git a/test/challtestsrv.py b/test/challtestsrv.py index d88450b15..f14482a15 100644 --- a/test/challtestsrv.py +++ b/test/challtestsrv.py @@ -1,4 +1,4 @@ -import requests +import urllib2 import json class ChallTestServer: @@ -39,14 +39,14 @@ class ChallTestServer: self._baseURL = url def _postURL(self, url, body): - return requests.post( + return urllib2.urlopen( url, - data=json.dumps(body)).text + data=json.dumps(body)).read() def _URL(self, path): urlPath = self._paths.get(path, None) if urlPath is None: - raise(Exception("No challenge test server URL path known for {0}".format(path))) + raise Exception("No challenge test server URL path known for {0}".format(path)) return self._baseURL + urlPath def _clear_request_history(self, host, typ): diff --git a/test/chisel.py b/test/chisel.py index 93b197a1f..3d0aa132e 100644 --- a/test/chisel.py +++ b/test/chisel.py @@ -14,7 +14,7 @@ import socket import sys import threading import time -import requests +import urllib2 from cryptography import x509 from cryptography.hazmat.backends import default_backend @@ -73,9 +73,9 @@ def update_email(client, email): email. """ if client is None: - raise(NoClientError("update_email requires a valid acme.Client argument")) + raise NoClientError("update_email requires a valid acme.Client argument") if email is None: - raise(EmailRequiredError("update_email requires an email argument")) + raise EmailRequiredError("update_email requires an email argument") if not email.startswith("mailto:"): email = "mailto:"+ email acct = client.account @@ -86,7 +86,7 @@ def get_chall(authz, typ): for chall_body in authz.body.challenges: if isinstance(chall_body.chall, typ): return chall_body - raise(Exception("No %s challenge found" % typ)) + raise Exception("No %s challenge found" % typ) class ValidationError(Exception): """An error that occurs during challenge validation.""" @@ -110,9 +110,9 @@ def issue(client, authzs, cert_output=None): csr = OpenSSL.crypto.X509Req() csr.add_extensions([ OpenSSL.crypto.X509Extension( - 'subjectAltName'.encode(), + 'subjectAltName', critical=False, - value=(', '.join('DNS:' + d for d in domains)).encode() + value=', '.join('DNS:' + d for d in domains).encode() ), ]) csr.set_pubkey(pkey) @@ -126,21 +126,19 @@ def issue(client, authzs, cert_output=None): # If we get a PollError, pick the first failed authz and turn it into a more # useful ValidationError that contains details we can look for in tests. for authz in error.updated: - r = requests.get(authz.uri) - r.raise_for_status() - updated_authz = r.json() + updated_authz = json.loads(urllib2.urlopen(authz.uri).read()) domain = authz.body.identifier.value, for c in updated_authz['challenges']: if 'error' in c: err = c['error'] - raise(ValidationError(domain, err['type'], err['detail'])) + raise ValidationError(domain, err['type'], err['detail']) # If none of the authz's had an error, just re-raise. raise if cert_output is not None: pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert_resource.body) with open(cert_output, 'w') as f: - f.write(pem.decode()) + f.write(pem) return cert_resource def http_01_answer(client, chall_body): @@ -225,7 +223,7 @@ def auth_and_issue(domains, chall_type="dns-01", email=None, cert_output=None, c elif chall_type == "tls-alpn-01": cleanup = do_tlsalpn_challenges(client, authzs) else: - raise(Exception("invalid challenge type %s" % chall_type)) + raise Exception("invalid challenge type %s" % chall_type) try: cert_resource = issue(client, authzs, cert_output) @@ -252,15 +250,15 @@ def expect_problem(problem_type, func): else: raise if not ok: - raise(Exception('Expected %s, got no error' % problem_type)) + raise Exception('Expected %s, got no error' % problem_type) if __name__ == "__main__": domains = sys.argv[1:] if len(domains) == 0: - print(__doc__) + print __doc__ sys.exit(0) try: auth_and_issue(domains) - except messages.Error as e: - print(e) + except messages.Error, e: + print e sys.exit(1) diff --git a/test/chisel2.py b/test/chisel2.py index 0657b2077..39ca19bea 100644 --- a/test/chisel2.py +++ b/test/chisel2.py @@ -15,6 +15,7 @@ import sys import signal import threading import time +import urllib2 from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.asymmetric import rsa @@ -59,14 +60,14 @@ def make_client(email=None): client.net.account = client.new_account(messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) else: - raise(Exception("Unrecognized terms of service URL %s" % tos)) + raise Exception("Unrecognized terms of service URL %s" % tos) return client def get_chall(authz, typ): for chall_body in authz.body.challenges: if isinstance(chall_body.chall, typ): return chall_body - raise(Exception("No %s challenge found" % typ.typ)) + raise Exception("No %s challenge found" % typ.typ) def make_csr(domains): key = OpenSSL.crypto.PKey() @@ -99,7 +100,7 @@ def auth_and_issue(domains, chall_type="dns-01", email=None, cert_output=None, c elif chall_type == "tls-alpn-01": cleanup = do_tlsalpn_challenges(client, authzs) else: - raise(Exception("invalid challenge type %s" % chall_type)) + raise Exception("invalid challenge type %s" % chall_type) try: order = client.poll_and_finalize(order) @@ -171,7 +172,7 @@ def expect_problem(problem_type, func): if e.typ == problem_type: ok = True else: - raise(Exception("Expected %s, got %s" % (problem_type, error.__str__()))) + raise Exception("Expected %s, got %s" % (problem_type, error.__str__())) except acme_errors.ValidationError as e: for authzr in e.failed_authzrs: for chall in authzr.body.challenges: @@ -179,19 +180,19 @@ def expect_problem(problem_type, func): if error and error.typ == problem_type: ok = True elif error: - raise(Exception("Expected %s, got %s" % (problem_type, error.__str__()))) + raise Exception("Expected %s, got %s" % (problem_type, error.__str__())) if not ok: - raise(Exception('Expected %s, got no error' % problem_type)) + raise Exception('Expected %s, got no error' % problem_type) if __name__ == "__main__": # Die on SIGINT signal.signal(signal.SIGINT, signal.SIG_DFL) domains = sys.argv[1:] if len(domains) == 0: - print(__doc__) + print __doc__ sys.exit(0) try: auth_and_issue(domains) - except messages.Error as e: - print(e) + except messages.Error, e: + print e sys.exit(1) diff --git a/test/helpers.py b/test/helpers.py index 2b6ae999a..01acf6312 100644 --- a/test/helpers.py +++ b/test/helpers.py @@ -1,11 +1,11 @@ +#!/usr/bin/env python2.7 import base64 import os -import urllib +import urllib2 import time import re import random import json -import requests import socket import tempfile import shutil @@ -38,20 +38,20 @@ def random_domain(): return "rand.%x.xyz" % random.randrange(2**32) def run(cmd, **kwargs): - return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, **kwargs).decode() + return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, **kwargs) def fetch_ocsp(request_bytes, url): """Fetch an OCSP response using POST, GET, and GET with URL encoding. Returns a tuple of the responses. """ - ocsp_req_b64 = base64.b64encode(request_bytes).decode() + ocsp_req_b64 = base64.b64encode(request_bytes) # Make the OCSP request three different ways: by POST, by GET, and by GET with # URL-encoded parameters. All three should have an identical response. - get_response = requests.get("%s/%s" % (url, ocsp_req_b64)).content - get_encoded_response = requests.get("%s/%s" % (url, urllib.parse.quote(ocsp_req_b64, safe = ""))).content - post_response = requests.post("%s/" % (url), data=request_bytes).content + get_response = urllib2.urlopen("%s/%s" % (url, ocsp_req_b64)).read() + get_encoded_response = urllib2.urlopen("%s/%s" % (url, urllib2.quote(ocsp_req_b64, safe = ""))).read() + post_response = urllib2.urlopen("%s/" % (url), request_bytes).read() return (post_response, get_response, get_encoded_response) @@ -61,13 +61,13 @@ def make_ocsp_req(cert_file, issuer_file): # First generate the OCSP request in DER form run("openssl ocsp -no_nonce -issuer %s -cert %s -reqout %s" % ( issuer_file, cert_file, ocsp_req_file)) - with open(ocsp_req_file, mode='rb') as f: + with open(ocsp_req_file) as f: ocsp_req = f.read() return ocsp_req def ocsp_verify(cert_file, issuer_file, ocsp_response): ocsp_resp_file = os.path.join(tempdir, "ocsp.resp") - with open(ocsp_resp_file, "wb") as f: + with open(ocsp_resp_file, "w") as f: f.write(ocsp_response) output = run("openssl ocsp -no_nonce -issuer %s -cert %s \ -verify_other %s -CAfile test/test-root.pem \ @@ -76,8 +76,8 @@ def ocsp_verify(cert_file, issuer_file, ocsp_response): # also look for the string "Response Verify Failure" verify_failure = "Response Verify Failure" if re.search(verify_failure, output): - print(output) - raise(Exception("OCSP verify failure")) + print output + raise Exception("OCSP verify failure") return output def verify_ocsp(cert_file, issuer_file, url, status): @@ -87,28 +87,28 @@ def verify_ocsp(cert_file, issuer_file, url, status): # Verify all responses are the same for resp in responses: if resp != responses[0]: - raise(Exception("OCSP responses differed: %s vs %s" %( - base64.b64encode(responses[0]), base64.b64encode(resp)))) + raise Exception("OCSP responses differed: %s vs %s" %( + base64.b64encode(responses[0]), base64.b64encode(resp))) # Check response is for the correct certificate and is correct # status resp = responses[0] verify_output = ocsp_verify(cert_file, issuer_file, resp) if not re.search("%s: %s" % (cert_file, status), verify_output): - print(verify_output) - raise(Exception("OCSP response wasn't '%s'" % status)) + print verify_output + raise Exception("OCSP response wasn't '%s'" % status) def reset_akamai_purges(): - requests.post("http://localhost:6789/debug/reset-purges", data="{}") + urllib2.urlopen("http://localhost:6789/debug/reset-purges", "{}") def verify_akamai_purge(): deadline = time.time() + 0.25 while True: time.sleep(0.05) if time.time() > deadline: - raise(Exception("Timed out waiting for Akamai purge")) - response = requests.get("http://localhost:6789/debug/get-purges") - purgeData = response.json() + raise Exception("Timed out waiting for Akamai purge") + response = urllib2.urlopen("http://localhost:6789/debug/get-purges") + purgeData = json.load(response) if len(purgeData["V3"]) is not 1: continue break @@ -142,7 +142,7 @@ def waitport(port, prog, perTickCheck=None): return True except socket.error as e: if e.errno == errno.ECONNREFUSED: - print("Waiting for debug port %d (%s)" % (port, prog)) + print "Waiting for debug port %d (%s)" % (port, prog) else: raise - raise(Exception("timed out waiting for debug port %d (%s)" % (port, prog))) + raise Exception("timed out waiting for debug port %d (%s)" % (port, prog)) diff --git a/test/integration-test.py b/test/integration-test.py index 965b2929b..04352fa69 100644 --- a/test/integration-test.py +++ b/test/integration-test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- """ This file contains basic infrastructure for running the integration test cases. @@ -53,7 +53,7 @@ def run_expired_authz_purger(): tool = "expired-authz-purger" out = get_future_output("./bin/expired-authz-purger --config cmd/expired-authz-purger/config.json", target_time) if 'via FAKECLOCK' not in out: - raise(Exception("%s was not built with `integration` build tag" % (tool))) + raise Exception("%s was not built with `integration` build tag" % (tool)) if num is None: return if CONFIG_NEXT: @@ -61,8 +61,8 @@ def run_expired_authz_purger(): else: expected_output = 'Deleted a total of %d expired authorizations from %s' % (num, table) if expected_output not in out: - raise(Exception("%s did not print '%s'. Output:\n%s" % ( - tool, expected_output, out))) + raise Exception("%s did not print '%s'. Output:\n%s" % ( + tool, expected_output, out)) now = datetime.datetime.utcnow() @@ -121,9 +121,9 @@ def test_stats(): def expect_stat(port, stat): url = "http://localhost:%d/metrics" % port response = requests.get(url) - if not stat in response.text: + if not stat in response.content: print(response.content) - raise(Exception("%s not present in %s" % (stat, url))) + raise Exception("%s not present in %s" % (stat, url)) expect_stat(8000, "\nresponse_time_count{") expect_stat(8000, "\ngo_goroutines ") expect_stat(8000, '\ngrpc_client_handling_seconds_count{grpc_method="NewRegistration",grpc_service="ra.RegistrationAuthority",grpc_type="unary"} ') @@ -156,7 +156,7 @@ def main(): args = parser.parse_args() if not (args.run_all or args.run_certbot or args.run_chisel or args.run_loadtest or args.custom is not None): - raise(Exception("must run at least one of the letsencrypt or chisel tests with --all, --certbot, --chisel, --load or --custom")) + raise Exception("must run at least one of the letsencrypt or chisel tests with --all, --certbot, --chisel, --load or --custom") if not args.skip_setup: now = datetime.datetime.utcnow() @@ -169,13 +169,13 @@ def main(): now = datetime.datetime.utcnow() twenty_days_ago = now+datetime.timedelta(days=-20) if not startservers.start(race_detection=True, fakeclock=fakeclock(twenty_days_ago), config_dir=config): - raise(Exception("startservers failed (mocking twenty days ago)")) + raise Exception("startservers failed (mocking twenty days ago)") v1_integration.caa_client = caa_client = chisel.make_client() setup_twenty_days_ago() startservers.stop() if not startservers.start(race_detection=True): - raise(Exception("startservers failed")) + raise Exception("startservers failed") if args.run_all or args.run_chisel: run_chisel(args.test_case_filter) @@ -202,7 +202,7 @@ def main(): run_loadtest() if not startservers.check(): - raise(Exception("startservers.check failed")) + raise Exception("startservers.check failed") global exit_status exit_status = 0 @@ -253,7 +253,7 @@ def check_balance(): for address in addresses: metrics = requests.get("http://%s/metrics" % address) if not "grpc_server_handled_total" in metrics.text: - raise(Exception("no gRPC traffic processed by %s; load balancing problem?") + raise Exception("no gRPC traffic processed by %s; load balancing problem?" % address) def run_cert_checker(): @@ -263,7 +263,7 @@ if __name__ == "__main__": try: main() except subprocess.CalledProcessError as e: - raise(Exception("%s. Output:\n%s" % (e, e.output))) + raise Exception("%s. Output:\n%s" % (e, e.output)) @atexit.register def stop(): diff --git a/test/boulder-tools/requirements.txt b/test/requirements.txt similarity index 100% rename from test/boulder-tools/requirements.txt rename to test/requirements.txt diff --git a/test/startservers.py b/test/startservers.py index b9fd55877..406ad353c 100644 --- a/test/startservers.py +++ b/test/startservers.py @@ -1,4 +1,5 @@ import atexit +import BaseHTTPServer import os import shutil import signal @@ -101,7 +102,7 @@ def start(race_detection, fakeclock=None, config_dir=default_config_dir): print(e) return False - print("All servers running. Hit ^C to kill.") + print "All servers running. Hit ^C to kill." return True def check(): @@ -119,9 +120,9 @@ def check(): else: busted.append(p) if busted: - print("\n\nThese processes exited early (check above for their output):") + print "\n\nThese processes exited early (check above for their output):" for p in busted: - print("\t'%s' with pid %d exited %d" % (p.cmd, p.pid, p.returncode)) + print "\t'%s' with pid %d exited %d" % (p.cmd, p.pid, p.returncode) processes = stillok return not busted @@ -132,7 +133,7 @@ def startChallSrv(): """ global challSrvProcess if challSrvProcess is not None: - raise(Exception("startChallSrv called more than once")) + raise Exception("startChallSrv called more than once") # NOTE(@cpu): We specify explicit bind addresses for -https01 and # --tlsalpn01 here to allow HTTPS HTTP-01 responses on 5001 for on interface diff --git a/test/v1_integration.py b/test/v1_integration.py index cda1561b3..69f20a975 100644 --- a/test/v1_integration.py +++ b/test/v1_integration.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- import datetime import json @@ -6,6 +7,7 @@ import random import re import requests import time +import urllib2 import startservers @@ -38,7 +40,7 @@ def rand_http_chall(client): for c in authz.body.challenges: if isinstance(c.chall, challenges.HTTP01): return d, c.chall - raise(Exception("No HTTP-01 challenge found for random domain authz")) + raise Exception("No HTTP-01 challenge found for random domain authz") def test_http_challenge_loop_redirect(): client = chisel.make_client() @@ -156,7 +158,7 @@ def test_http_challenge_http_redirect(): # There should have been at least two GET requests made to the # challtestsrv. There may have been more if remote VAs were configured. if len(history) < 2: - raise(Exception("Expected at least 2 HTTP request events on challtestsrv, found {1}".format(len(history)))) + raise Exception("Expected at least 2 HTTP request events on challtestsrv, found {1}".format(len(history))) initialRequests = [] redirectedRequests = [] @@ -164,7 +166,7 @@ def test_http_challenge_http_redirect(): for request in history: # All requests should have been over HTTP if request['HTTPS'] is True: - raise(Exception("Expected all requests to be HTTP")) + raise Exception("Expected all requests to be HTTP") # Initial requests should have the expected initial HTTP-01 URL for the challenge if request['URL'] == challengePath: initialRequests.append(request) @@ -173,15 +175,15 @@ def test_http_challenge_http_redirect(): elif request['URL'] == redirectPath: redirectedRequests.append(request) else: - raise(Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request))) + raise Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request)) # There should have been at least 1 initial HTTP-01 validation request. if len(initialRequests) < 1: - raise(Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests)))) + raise Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests))) # There should have been at least 1 redirected HTTP request for each VA if len(redirectedRequests) < 1: - raise(Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests)))) + raise Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests))) def test_http_challenge_https_redirect(): client = chisel.make_client() @@ -218,7 +220,7 @@ def test_http_challenge_https_redirect(): # There should have been at least two GET requests made to the challtestsrv by the VA if len(history) < 2: - raise(Exception("Expected 2 HTTP request events on challtestsrv, found {0}".format(len(history)))) + raise Exception("Expected 2 HTTP request events on challtestsrv, found {0}".format(len(history))) initialRequests = [] redirectedRequests = [] @@ -232,26 +234,26 @@ def test_http_challenge_https_redirect(): elif request['URL'] == redirectPath: redirectedRequests.append(request) else: - raise(Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request))) + raise Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request)) # There should have been at least 1 initial HTTP-01 validation request. if len(initialRequests) < 1: - raise(Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests)))) + raise Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests))) # All initial requests should have been over HTTP for r in initialRequests: if r['HTTPS'] is True: - raise(Exception("Expected all initial requests to be HTTP")) + raise Exception("Expected all initial requests to be HTTP") # There should have been at least 1 redirected HTTP request for each VA if len(redirectedRequests) < 1: - raise(Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests)))) + raise Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests))) # All the redirected requests should have been over HTTPS with the correct # SNI value for r in redirectedRequests: if r['HTTPS'] is False: - raise(Exception("Expected all redirected requests to be HTTPS")) + raise Exception("Expected all redirected requests to be HTTPS") elif r['ServerName'] != d: - raise(Exception("Expected all redirected requests to have ServerName {0} got \"{1}\"".format(d, r['ServerName']))) + raise Exception("Expected all redirected requests to have ServerName {0} got \"{1}\"".format(d, r['ServerName'])) class SlowHTTPRequestHandler(BaseHTTPRequestHandler): def do_GET(self): @@ -307,7 +309,7 @@ def test_http_challenge_timeout(): # present the timeout is 20s so adding 2s of padding = 22s) expectedDuration = 22 if delta.total_seconds() == 0 or delta.total_seconds() > expectedDuration: - raise(Exception("expected timeout to occur in under {0} seconds. Took {1}".format(expectedDuration, delta.total_seconds()))) + raise Exception("expected timeout to occur in under {0} seconds. Took {1}".format(expectedDuration, delta.total_seconds())) def test_tls_alpn_challenge(): # Pick two random domains @@ -331,7 +333,7 @@ def test_issuer(): of length exactly 1. """ certr, authzs = auth_and_issue([random_domain()]) - cert = requests.get(certr.uri).content + cert = urllib2.urlopen(certr.uri).read() # In the future the chain URI will use HTTPS so include the root certificate # for the WFE's PKI. Note: We use the requests library here so we honor the # REQUESTS_CA_BUNDLE passed by test.sh. @@ -374,7 +376,7 @@ def test_ct_submission(): def submissions(group): count = 0 for log in group: - count += int(requests.get(log + "?hostnames=%s" % hostname).text) + count += int(urllib2.urlopen(log + "?hostnames=%s" % hostname).read()) return count auth_and_issue([hostname]) @@ -384,29 +386,29 @@ def test_ct_submission(): for i in range(len(log_groups)): if got[i] < expected[i]: - raise(Exception("For log group %d, got %d submissions, expected %d." % - (i, got[i], expected[i]))) + raise Exception("For log group %d, got %d submissions, expected %d." % + (i, got[i], expected[i])) def test_expiration_mailer(): email_addr = "integration.%x@letsencrypt.org" % random.randrange(2**16) cert, _ = auth_and_issue([random_domain()], email=email_addr) # Check that the expiration mailer sends a reminder - expiry = datetime.datetime.strptime(cert.body.get_notAfter().decode(), '%Y%m%d%H%M%SZ') + expiry = datetime.datetime.strptime(cert.body.get_notAfter(), '%Y%m%d%H%M%SZ') no_reminder = expiry + datetime.timedelta(days=-31) first_reminder = expiry + datetime.timedelta(days=-13) last_reminder = expiry + datetime.timedelta(days=-2) - requests.post("http://localhost:9381/clear", data='') - print(get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % - default_config_dir, no_reminder)) - print(get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % - default_config_dir, first_reminder)) - print(get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % - default_config_dir, last_reminder)) - resp = requests.get("http://localhost:9381/count?to=%s" % email_addr) - mailcount = int(resp.text) + urllib2.urlopen("http://localhost:9381/clear", data='') + print get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % + default_config_dir, no_reminder) + print get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % + default_config_dir, first_reminder) + print get_future_output('./bin/expiration-mailer --config %s/expiration-mailer.json' % + default_config_dir, last_reminder) + resp = urllib2.urlopen("http://localhost:9381/count?to=%s" % email_addr) + mailcount = int(resp.read()) if mailcount != 2: - raise(Exception("\nExpiry mailer failed: expected 2 emails, got %d" % mailcount)) + raise Exception("\nExpiry mailer failed: expected 2 emails, got %d" % mailcount) def test_revoke_by_account(): client = chisel.make_client() @@ -442,13 +444,13 @@ def test_recheck_caa(): recheck CAA and reject the request. """ if len(caa_recheck_authzs) == 0: - raise(Exception("CAA authzs not prepared for test_caa")) + raise Exception("CAA authzs not prepared for test_caa") domains = [] for a in caa_recheck_authzs: response = requests.get(a.uri) if response.status_code != 200: - raise(Exception("Unexpected response for CAA authz: ", - response.status_code)) + raise Exception("Unexpected response for CAA authz: ", + response.status_code) domain = a.body.identifier.value domains.append(domain) challSrv.add_caa_issue(domain, ";") @@ -516,11 +518,11 @@ def test_account_update(): result = chisel.update_email(client, email=email) # We expect one contact in the result if len(result.body.contact) != 1: - raise(Exception("\nUpdate account failed: expected one contact in result, got 0")) + raise Exception("\nUpdate account failed: expected one contact in result, got 0") # We expect it to be the email we just updated to actual = result.body.contact[0] if actual != "mailto:"+email: - raise(Exception("\nUpdate account failed: expected contact %s, got %s" % (email, actual))) + raise Exception("\nUpdate account failed: expected contact %s, got %s" % (email, actual)) def test_renewal_exemption(): """ @@ -576,13 +578,13 @@ def test_admin_revoker_cert(): def test_sct_embedding(): certr, authzs = auth_and_issue([random_domain()]) - certBytes = requests.get(certr.uri).content + certBytes = urllib2.urlopen(certr.uri).read() cert = x509.load_der_x509_certificate(certBytes, default_backend()) # make sure there is no poison extension try: cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")) - raise(Exception("certificate contains CT poison extension")) + raise Exception("certificate contains CT poison extension") except x509.ExtensionNotFound: # do nothing pass @@ -591,15 +593,15 @@ def test_sct_embedding(): try: sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2")) except x509.ExtensionNotFound: - raise(Exception("certificate doesn't contain SCT list extension")) + raise Exception("certificate doesn't contain SCT list extension") if len(sctList.value) != 2: - raise(Exception("SCT list contains wrong number of SCTs")) + raise Exception("SCT list contains wrong number of SCTs") for sct in sctList.value: if sct.version != x509.certificate_transparency.Version.v1: - raise(Exception("SCT contains wrong version")) + raise Exception("SCT contains wrong version") if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE: - raise(Exception("SCT contains wrong entry type")) + raise Exception("SCT contains wrong entry type") delta = sct.timestamp - datetime.datetime.now() if abs(delta) > datetime.timedelta(hours=1): - raise(Exception("Delta between SCT timestamp and now was too great " - "%s vs %s (%s)" % (sct.timestamp, datetime.datetime.now(), delta))) + raise Exception("Delta between SCT timestamp and now was too great " + "%s vs %s (%s)" % (sct.timestamp, datetime.datetime.now(), delta)) diff --git a/test/v2_integration.py b/test/v2_integration.py index 5e4259c77..0150ac52f 100644 --- a/test/v2_integration.py +++ b/test/v2_integration.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- """ Integration test cases for ACMEv2 as implemented by boulder-wfe2. @@ -64,7 +65,7 @@ def rand_http_chall(client): for c in a.body.challenges: if isinstance(c.chall, challenges.HTTP01): return d, c.chall - raise(Exception("No HTTP-01 challenge found for random domain authz")) + raise Exception("No HTTP-01 challenge found for random domain authz") def test_http_challenge_broken_redirect(): """ @@ -97,9 +98,9 @@ def test_http_challenge_broken_redirect(): c = chisel2.get_chall(authzr, challenges.HTTP01) error = c.error if error is None or error.typ != "urn:ietf:params:acme:error:connection": - raise(Exception("Expected connection prob, got %s" % (error.__str__()))) + raise Exception("Expected connection prob, got %s" % (error.__str__())) if error.detail != expectedError: - raise(Exception("Expected prob detail %s, got %s" % (expectedError, error.detail))) + raise Exception("Expected prob detail %s, got %s" % (expectedError, error.detail)) challSrv.remove_http_redirect(challengePath) @@ -217,7 +218,7 @@ def test_http_challenge_http_redirect(): # There should have been at least two GET requests made to the # challtestsrv. There may have been more if remote VAs were configured. if len(history) < 2: - raise(Exception("Expected at least 2 HTTP request events on challtestsrv, found {1}".format(len(history)))) + raise Exception("Expected at least 2 HTTP request events on challtestsrv, found {1}".format(len(history))) initialRequests = [] redirectedRequests = [] @@ -225,7 +226,7 @@ def test_http_challenge_http_redirect(): for request in history: # All requests should have been over HTTP if request['HTTPS'] is True: - raise(Exception("Expected all requests to be HTTP")) + raise Exception("Expected all requests to be HTTP") # Initial requests should have the expected initial HTTP-01 URL for the challenge if request['URL'] == challengePath: initialRequests.append(request) @@ -234,15 +235,15 @@ def test_http_challenge_http_redirect(): elif request['URL'] == redirectPath: redirectedRequests.append(request) else: - raise(Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request))) + raise Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request)) # There should have been at least 1 initial HTTP-01 validation request. if len(initialRequests) < 1: - raise(Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests)))) + raise Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests))) # There should have been at least 1 redirected HTTP request for each VA if len(redirectedRequests) < 1: - raise(Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests)))) + raise Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests))) def test_http_challenge_https_redirect(): client = chisel2.make_client() @@ -277,7 +278,7 @@ def test_http_challenge_https_redirect(): error = chall.error if error: problems.append(error.__str__()) - raise(Exception("validation problem: %s" % "; ".join(problems))) + raise Exception("validation problem: %s" % "; ".join(problems)) challSrv.remove_http_redirect(challengePath) challSrv.remove_a_record(d) @@ -287,7 +288,7 @@ def test_http_challenge_https_redirect(): # There should have been at least two GET requests made to the challtestsrv by the VA if len(history) < 2: - raise(Exception("Expected 2 HTTP request events on challtestsrv, found {0}".format(len(history)))) + raise Exception("Expected 2 HTTP request events on challtestsrv, found {0}".format(len(history))) initialRequests = [] redirectedRequests = [] @@ -301,30 +302,30 @@ def test_http_challenge_https_redirect(): elif request['URL'] == redirectPath: redirectedRequests.append(request) else: - raise(Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request))) + raise Exception("Unexpected request URL {0} in challtestsrv history: {1}".format(request['URL'], request)) # There should have been at least 1 initial HTTP-01 validation request. if len(initialRequests) < 1: - raise(Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests)))) + raise Exception("Expected {0} initial HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(initialRequests))) # All initial requests should have been over HTTP for r in initialRequests: if r['HTTPS'] is True: - raise(Exception("Expected all initial requests to be HTTP, got %s" % r)) + raise Exception("Expected all initial requests to be HTTP, got %s" % r) # There should have been at least 1 redirected HTTP request for each VA if len(redirectedRequests) < 1: - raise(Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests)))) + raise Exception("Expected {0} redirected HTTP-01 request events on challtestsrv, found {1}".format(validation_attempts, len(redirectedRequests))) # All the redirected requests should have been over HTTPS with the correct # SNI value for r in redirectedRequests: if r['HTTPS'] is False: - raise(Exception("Expected all redirected requests to be HTTPS")) + raise Exception("Expected all redirected requests to be HTTPS") # TODO(@cpu): The following ServerName test will fail with config-next # until https://github.com/letsencrypt/boulder/issues/3969 is fixed. if CONFIG_NEXT: return elif r['ServerName'] != d: - raise(Exception("Expected all redirected requests to have ServerName {0} got \"{1}\"".format(d, r['ServerName']))) + raise Exception("Expected all redirected requests to have ServerName {0} got \"{1}\"".format(d, r['ServerName'])) def test_tls_alpn_challenge(): # Pick two random domains @@ -353,8 +354,8 @@ def test_overlapping_wildcard(): authzs = order.authorizations if len(authzs) != 2: - raise(Exception("order for %s had %d authorizations, expected 2" % - (domains, len(authzs)))) + raise Exception("order for %s had %d authorizations, expected 2" % + (domains, len(authzs))) cleanup = chisel2.do_dns_challenges(client, authzs) try: @@ -419,8 +420,8 @@ def test_wildcard_authz_reuse(): # We expect all of the returned authorizations to be pending status for authz in order.authorizations: if authz.body.status != Status("pending"): - raise(Exception("order for %s included a non-pending authorization (status: %s) from a previous HTTP-01 order" % - ((domains), str(authz.body.status)))) + raise Exception("order for %s included a non-pending authorization (status: %s) from a previous HTTP-01 order" % + ((domains), str(authz.body.status))) def test_bad_overlap_wildcard(): chisel2.expect_problem("urn:ietf:params:acme:error:malformed", @@ -469,20 +470,20 @@ def test_order_reuse_failed_authz(): # If the poll ended and an authz's status isn't invalid then we reached the # deadline, fail the test if not authzFailed: - raise(Exception("timed out waiting for order %s to become invalid" % firstOrderURI)) + raise Exception("timed out waiting for order %s to become invalid" % firstOrderURI) # Make another order with the same domains order = client.new_order(csr_pem) # It should not be the same order as before if order.uri == firstOrderURI: - raise(Exception("new-order for %s returned a , now-invalid, order" % domains)) + raise Exception("new-order for %s returned a , now-invalid, order" % domains) # We expect all of the returned authorizations to be pending status for authz in order.authorizations: if authz.body.status != Status("pending"): - raise(Exception("order for %s included a non-pending authorization (status: %s) from a previous order" % - ((domains), str(authz.body.status)))) + raise Exception("order for %s included a non-pending authorization (status: %s) from a previous order" % + ((domains), str(authz.body.status))) # We expect the new order can be fulfilled cleanup = chisel2.do_http_challenges(client, order.authorizations) @@ -583,13 +584,12 @@ def test_revoke_by_privkey(): def test_sct_embedding(): order = chisel2.auth_and_issue([random_domain()]) - print(order.fullchain_pem.encode()) - cert = x509.load_pem_x509_certificate(order.fullchain_pem.encode(), default_backend()) + cert = x509.load_pem_x509_certificate(str(order.fullchain_pem), default_backend()) # make sure there is no poison extension try: cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3")) - raise(Exception("certificate contains CT poison extension")) + raise Exception("certificate contains CT poison extension") except x509.ExtensionNotFound: # do nothing pass @@ -598,14 +598,14 @@ def test_sct_embedding(): try: sctList = cert.extensions.get_extension_for_oid(x509.ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2")) except x509.ExtensionNotFound: - raise(Exception("certificate doesn't contain SCT list extension")) + raise Exception("certificate doesn't contain SCT list extension") if len(sctList.value) != 2: - raise(Exception("SCT list contains wrong number of SCTs")) + raise Exception("SCT list contains wrong number of SCTs") for sct in sctList.value: if sct.version != x509.certificate_transparency.Version.v1: - raise(Exception("SCT contains wrong version")) + raise Exception("SCT contains wrong version") if sct.entry_type != x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE: - raise(Exception("SCT contains wrong entry type")) + raise Exception("SCT contains wrong entry type") def test_only_return_existing_reg(): client = chisel2.uninitialized_client() @@ -624,7 +624,7 @@ def test_only_return_existing_reg(): }) resp = client.net.post(client.directory['newAccount'], acct, acme_version=2) if resp.status_code != 200: - raise(Exception("incorrect response returned for onlyReturnExisting")) + raise Exception("incorrect response returned for onlyReturnExisting") other_client = chisel2.uninitialized_client() newAcct = extendedAcct({ @@ -671,7 +671,7 @@ def BouncerHTTPRequestHandler(redirect, guestlist): self.log_message("BouncerHandler UA {0} has no requests on the Guestlist. Sending request to the curb".format(ua)) self.send_response(200) self.end_headers() - self.wfile.write(u'(• ◡ •) <( VIPs only! )') + self.wfile.write(b'(• ◡ •) <( VIPs only! )') BouncerHandler.guestlist = guestlist BouncerHandler.redirect = redirect @@ -707,7 +707,7 @@ def multiva_setup(client, guestlist): if isinstance(c.chall, challenges.HTTP01): chall = c.chall if chall is None: - raise(Exception("No HTTP-01 challenge found for random domain authz")) + raise Exception("No HTTP-01 challenge found for random domain authz") token = chall.encode("token") @@ -791,16 +791,16 @@ def test_http_multiva_threshold_fail(): # test needs to unpack an `acme_errors.ValidationError` on its own. It # might be possible to clean this up in the future. if len(e.failed_authzrs) != 1: - raise(Exception("expected one failed authz, found {0}".format(len(e.failed_authzrs)))) + raise Exception("expected one failed authz, found {0}".format(len(e.failed_authzrs))) challs = e.failed_authzrs[0].body.challenges httpChall = None for chall_body in challs: if isinstance(chall_body.chall, challenges.HTTP01): httpChall = chall_body if httpChall is None: - raise(Exception("no HTTP-01 challenge in failed authz")) + raise Exception("no HTTP-01 challenge in failed authz") if httpChall.error.typ != "urn:ietf:params:acme:error:unauthorized": - raise(Exception("expected unauthorized prob, found {0}".format(httpChall.error.typ))) + raise Exception("expected unauthorized prob, found {0}".format(httpChall.error.typ)) finally: cleanup() @@ -827,7 +827,7 @@ def wait_for_tcp_server(addr, port): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: sock.connect((addr, port)) - sock.sendall(b"\n") + sock.sendall("\n") return except socket.error: time.sleep(0.5) @@ -869,9 +869,9 @@ def test_http2_http01_challenge(): c = chisel2.get_chall(authzr, challenges.HTTP01) error = c.error if error is None or error.typ != "urn:ietf:params:acme:error:connection": - raise(Exception("Expected connection prob, got %s" % (error.__str__()))) + raise Exception("Expected connection prob, got %s" % (error.__str__())) if not error.detail.endswith(expectedError): - raise(Exception("Expected prob detail ending in %s, got %s" % (expectedError, error.detail))) + raise Exception("Expected prob detail ending in %s, got %s" % (expectedError, error.detail)) finally: server.shutdown() server.server_close() @@ -908,7 +908,7 @@ def test_z1_reuse(): if a.uri in authz_uris: authz_uris.remove(a.uri) if len(authz_uris) != 0: - raise(Exception("Failed to reuse all authzs. Remaining: %s" % authz_uris)) + raise Exception("Failed to reuse all authzs. Remaining: %s" % authz_uris) def test_new_order_policy_errs(): """ @@ -938,15 +938,18 @@ def test_new_order_policy_errs(): if e.detail != 'Error creating new order :: Cannot issue for "out-addr.in-addr.arpa": Policy forbids issuing for name (and 1 more problems. Refer to sub-problems for more information.)': raise(Exception('Order problem detail did not match expected')) if not ok: - raise(Exception('Expected problem, got no error')) + raise Exception('Expected problem, got no error') def test_long_san_no_cn(): try: chisel2.auth_and_issue([''.join(random.choice(string.ascii_uppercase) for x in range(61)) + ".com"]) - # if we get to this raise(the auth_and_issue call didn't fail, so fail the test) - raise(Exception("Issuance didn't fail when the only SAN in a certificate was longer than the max CN length")) + # if we get to this raise the auth_and_issue call didn't fail, so fail the test + raise Exception("Issuance didn't fail when the only SAN in a certificate was longer than the max CN length") except messages.Error as e: if e.typ != "urn:ietf:params:acme:error:malformed": - raise(Exception('Expected malformed type problem, got {0}'.format(e.typ))) + raise Exception('Expected malformed type problem, got {0}'.format(e.typ)) if e.detail != 'Error finalizing order :: issuing precertificate: CSR doesn\'t contain a SAN short enough to fit in CN': - raise(Exception('Problem detail did not match expected')) + raise Exception('Problem detail did not match expected') + +def run(cmd, **kwargs): + return subprocess.check_output(cmd, shell=True, stderr=subprocess.STDOUT, **kwargs)