def test_only_return_existing_reg(): client = chisel2.uninitialized_client() email = "*****@*****.**" client.new_account(messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) client = chisel2.uninitialized_client(key=client.net.key) class extendedAcct(dict): def json_dumps(self, indent=None): return json.dumps(self) acct = extendedAcct({ "termsOfServiceAgreed": True, "contact": [email], "onlyReturnExisting": True }) resp = client.net.post(client.directory['newAccount'], acct, acme_version=2) if resp.status_code != 200: raise Exception("incorrect response returned for onlyReturnExisting") other_client = chisel2.uninitialized_client() newAcct = extendedAcct({ "termsOfServiceAgreed": True, "contact": [email], "onlyReturnExisting": True }) chisel2.expect_problem("urn:ietf:params:acme:error:accountDoesNotExist", lambda: other_client.net.post(other_client.directory['newAccount'], newAcct, acme_version=2))
def test_bad_overlap_wildcard(): if not os.environ.get('BOULDER_CONFIG_DIR', '').startswith("test/config-next"): return chisel2.expect_problem( "urn:ietf:params:acme:error:malformed", lambda: chisel2.auth_and_issue(["*.example.com", "www.example.com"]))
def test_failed_validation_limit(): """ Fail a challenge repeatedly for the same domain, with the same account. Once we reach the rate limit we should get a rateLimitedError. Note that this depends on the specific threshold configured in rate-limit-policies.yml. This also incidentally tests a fix for https://github.com/letsencrypt/boulder/issues/4329. We expect to get ValidationErrors, eventually followed by a rate limit error. """ domain = "fail." + random_domain() csr_pem = chisel2.make_csr([domain]) client = chisel2.make_client() threshold = 3 for _ in range(threshold): order = client.new_order(csr_pem) chall = order.authorizations[0].body.challenges[0] client.answer_challenge(chall, chall.response(client.net.key)) try: client.poll_and_finalize(order) except errors.ValidationError as e: pass chisel2.expect_problem( "urn:ietf:params:acme:error:rateLimited", lambda: chisel2.auth_and_issue([domain], client=client))
def test_only_return_existing_reg(): client = chisel2.uninitialized_client() email = "*****@*****.**" client.new_account( messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) client = chisel2.uninitialized_client(key=client.net.key) class extendedAcct(dict): def json_dumps(self, indent=None): return json.dumps(self) acct = extendedAcct({ "termsOfServiceAgreed": True, "contact": [email], "onlyReturnExisting": True }) resp = client.net.post(client.directory['newAccount'], acct, acme_version=2) if resp.status_code != 200: raise Exception("incorrect response returned for onlyReturnExisting") other_client = chisel2.uninitialized_client() newAcct = extendedAcct({ "termsOfServiceAgreed": True, "contact": [email], "onlyReturnExisting": True }) chisel2.expect_problem( "urn:ietf:params:acme:error:accountDoesNotExist", lambda: other_client.net.post( other_client.directory['newAccount'], newAcct, acme_version=2))
def test_wildcard_exactblacklist(): """ Test issuance for a wildcard that would cover an exact blacklist entry. It should fail with a policy error. """ # We include "highrisk.le-test.hoffman-andrews.com" in `test/hostname-policy.json` # Issuing for "*.le-test.hoffman-andrews.com" should be blocked domain = "*.le-test.hoffman-andrews.com" # We expect this to produce a policy problem chisel2.expect_problem("urn:ietf:params:acme:error:rejectedIdentifier", lambda: chisel2.auth_and_issue([domain], chall_type="dns-01"))
def test_highrisk_blocklist(): """ Test issuance for a subdomain of a HighRiskBlockedNames entry. It should fail with a policy error. """ # We include "example.org" in `test/hostname-policy.yaml` in the # HighRiskBlockedNames list so issuing for "foo.example.org" should be # blocked. domain = "foo.example.org" # We expect this to produce a policy problem chisel2.expect_problem("urn:ietf:params:acme:error:rejectedIdentifier", lambda: chisel2.auth_and_issue([domain], chall_type="dns-01"))
def test_http_challenge_loop_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to itself challengePath = "/.well-known/acme-challenge/{0}".format(token) add_http_redirect(challengePath, "http://{0}{1}".format(d, challengePath)) # Issuing for the the name should fail because of the challenge domains's # redirect loop. chisel2.expect_problem( "urn:acme:error:connection", lambda: auth_and_issue([d], client=client, chall_type="http-01")) remove_http_redirect(challengePath)
def test_http_challenge_loop_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to itself challengePath = "/.well-known/acme-challenge/{0}".format(token) challSrv.add_http_redirect( challengePath, "http://{0}{1}".format(d, challengePath)) # Issuing for the the name should fail because of the challenge domains's # redirect loop. chisel2.expect_problem("urn:ietf:params:acme:error:connection", lambda: chisel2.auth_and_issue([d], client=client, chall_type="http-01")) challSrv.remove_http_redirect(challengePath)
def test_http_challenge_badhost_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to a bare IP # hostname. challengePath = "/.well-known/acme-challenge/{0}".format(token) add_http_redirect(challengePath, "https://127.0.0.1{0}".format(challengePath)) # Issuing for the name should cause a connection error because the redirect # domain name is an IP address. chisel2.expect_problem( "urn:acme:error:connection", lambda: auth_and_issue([d], client=client, chall_type="http-01")) remove_http_redirect(challengePath)
def test_order_finalize_early(): """ Test that finalizing an order before its fully authorized results in the order having an error set and the status being invalid. """ # Create a client client = chisel2.make_client(None) # Create a random domain and a csr domains = [random_domain()] csr_pem = chisel2.make_csr(domains) # Create an order for the domain order = client.new_order(csr_pem) deadline = datetime.datetime.now() + datetime.timedelta(seconds=5) # Finalizing an order early should generate an orderNotReady error. chisel2.expect_problem("urn:ietf:params:acme:error:orderNotReady", lambda: client.finalize_order(order, deadline))
def test_http_challenge_badproto_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to whacky # non-http/https protocol URL. challengePath = "/.well-known/acme-challenge/{0}".format(token) challSrv.add_http_redirect(challengePath, "gopher://{0}{1}".format(d, challengePath)) # Issuing for the name should cause a connection error because the redirect # domain name is an IP address. chisel2.expect_problem( "urn:ietf:params:acme:error:connection", lambda: chisel2. auth_and_issue([d], client=client, chall_type="http-01")) challSrv.remove_http_redirect(challengePath)
def test_http_challenge_badport_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to a host with # an invalid port. challengePath = "/.well-known/acme-challenge/{0}".format(token) challSrv.add_http_redirect(challengePath, "http://{0}:1337{1}".format(d, challengePath)) # Issuing for the name should fail because of the challenge domain's # invalid port redirect. chisel2.expect_problem( "urn:ietf:params:acme:error:connection", lambda: chisel2. auth_and_issue([d], client=client, chall_type="http-01")) challSrv.remove_http_redirect(challengePath)
def test_http_challenge_badhost_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to a bare IP # hostname. challengePath = "/.well-known/acme-challenge/{0}".format(token) challSrv.add_http_redirect( challengePath, "https://127.0.0.1{0}".format(challengePath)) # Issuing for the name should cause a connection error because the redirect # domain name is an IP address. chisel2.expect_problem("urn:acme:error:connection", lambda: auth_and_issue([d], client=client, chall_type="http-01")) challSrv.remove_http_redirect(challengePath)
def test_http_challenge_badproto_redirect(): client = chisel2.make_client() # Create an authz for a random domain and get its HTTP-01 challenge token d, chall = rand_http_chall(client) token = chall.encode("token") # Create a HTTP redirect from the challenge's validation path to whacky # non-http/https protocol URL. challengePath = "/.well-known/acme-challenge/{0}".format(token) challSrv.add_http_redirect( challengePath, "gopher://{0}{1}".format(d, challengePath)) # Issuing for the name should cause a connection error because the redirect # domain name is an IP address. chisel2.expect_problem("urn:ietf:params:acme:error:connection", lambda: chisel2.auth_and_issue([d], client=client, chall_type="http-01")) challSrv.remove_http_redirect(challengePath)
def test_order_finalize_early(): """ Test that finalizing an order before its fully authorized results in the order having an error set and the status being invalid. """ # Create a client client = chisel2.make_client(None) # Create a random domain and a csr domains = [ random_domain() ] csr_pem = chisel2.make_csr(domains) # Create an order for the domain order = client.new_order(csr_pem) deadline = datetime.datetime.now() + datetime.timedelta(seconds=5) # Finalizing an order early should generate an orderNotReady error. chisel2.expect_problem("urn:ietf:params:acme:error:orderNotReady", lambda: client.finalize_order(order, deadline))
def test_order_finalize_early(): """ Test that finalizing an order before its fully authorized results in the order having an error set and the status being invalid. """ # Create a client client = make_client(None) # Create a random domain and a csr domains = [random_domain()] csr_pem = make_csr(domains) # Create an order for the domain order = client.new_order(csr_pem) # Finalize the order without doing anything with the authorizations. YOLO # We expect this to generate an unauthorized error. chisel2.expect_problem( "urn:ietf:params:acme:error:unauthorized", lambda: client.net.post( order.body.finalize, CertificateRequest(csr=order.csr))) # Poll for a fixed amount of time checking for the order to become invalid # from the early finalization attempt initiated above failing deadline = datetime.datetime.now() + datetime.timedelta(seconds=5) while datetime.datetime.now() < deadline: time.sleep(1) updatedOrder = requests.get(order.uri).json() if updatedOrder['status'] == "invalid": break # If the loop ended and the status isn't invalid then we reached the # deadline waiting for the order to become invalid, fail the test if updatedOrder['status'] != "invalid": raise Exception("timed out waiting for order %s to become invalid" % order.uri) # The order should have an error with the expected type if updatedOrder['error'][ 'type'] != 'urn:ietf:params:acme:error:unauthorized': raise Exception("order %s has incorrect error field type: \"%s\"" % (order.uri, updatedOrder['error']['type']))
def test_order_finalize_early(): """ Test that finalizing an order before its fully authorized results in the order having an error set and the status being invalid. """ # Create a client client = chisel2.make_client(None) # Create a random domain and a csr domains = [ random_domain() ] csr_pem = chisel2.make_csr(domains) # Create an order for the domain order = client.new_order(csr_pem) deadline = datetime.datetime.now() + datetime.timedelta(seconds=5) # Finalizing an order early should generate an unauthorized error and we # should check that the order is invalidated. chisel2.expect_problem("urn:ietf:params:acme:error:unauthorized", lambda: client.finalize_order(order, deadline)) # Poll for a fixed amount of time checking for the order to become invalid # from the early finalization attempt initiated above failing while datetime.datetime.now() < deadline: time.sleep(1) updatedOrder = requests.get(order.uri).json() if updatedOrder['status'] == "invalid": break # If the loop ended and the status isn't invalid then we reached the # deadline waiting for the order to become invalid, fail the test if updatedOrder['status'] != "invalid": raise Exception("timed out waiting for order %s to become invalid" % order.uri) # The order should have an error with the expected type if updatedOrder['error']['type'] != 'urn:ietf:params:acme:error:unauthorized': raise Exception("order %s has incorrect error field type: \"%s\"" % (order.uri, updatedOrder['error']['type']))
def test_bad_overlap_wildcard(): chisel2.expect_problem( "urn:ietf:params:acme:error:malformed", lambda: chisel2.auth_and_issue(["*.example.com", "www.example.com"]))
def test_bad_overlap_wildcard(): if not os.environ.get('BOULDER_CONFIG_DIR', '').startswith("test/config-next"): return chisel2.expect_problem("urn:ietf:params:acme:error:malformed", lambda: chisel2.auth_and_issue(["*.example.com", "www.example.com"]))
def test_bad_overlap_wildcard(): chisel2.expect_problem("urn:ietf:params:acme:error:malformed", lambda: chisel2.auth_and_issue(["*.example.com", "www.example.com"]))