Skip to content

Remove python integration test in-the-past scaffolding #8086

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion start.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
if not startservers.install(race_detection=False):
raise(Exception("failed to build"))

if not startservers.start(fakeclock=None):
if not startservers.start():
sys.exit(1)
try:
os.wait()
Expand Down
23 changes: 0 additions & 23 deletions test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,29 +154,6 @@ def verify_akamai_purge():
break
reset_akamai_purges()

twenty_days_ago_functions = [ ]

def register_twenty_days_ago(f):
"""Register a function to be run during "setup_twenty_days_ago." This allows
test cases to define their own custom setup.
"""
twenty_days_ago_functions.append(f)

def setup_twenty_days_ago():
"""Do any setup that needs to happen 20 day in the past, for tests that
will run in the 'present'.
"""
for f in twenty_days_ago_functions:
f()

six_months_ago_functions = []

def register_six_months_ago(f):
six_months_ago_functions.append(f)

def setup_six_months_ago():
[f() for f in six_months_ago_functions]

def waitport(port, prog, perTickCheck=None):
"""Wait until a port on localhost is open."""
for _ in range(1000):
Expand Down
17 changes: 1 addition & 16 deletions test/integration-test.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,7 @@ def main():
if not startservers.install(race_detection=race_detection):
raise(Exception("failed to build"))

if not args.test_case_filter:
now = datetime.datetime.utcnow()

six_months_ago = now+datetime.timedelta(days=-30*6)
if not startservers.start(fakeclock=fakeclock(six_months_ago)):
raise(Exception("startservers failed (mocking six months ago)"))
setup_six_months_ago()
startservers.stop()

twenty_days_ago = now+datetime.timedelta(days=-20)
if not startservers.start(fakeclock=fakeclock(twenty_days_ago)):
raise(Exception("startservers failed (mocking twenty days ago)"))
setup_twenty_days_ago()
startservers.stop()

if not startservers.start(fakeclock=None):
if not startservers.start():
raise(Exception("startservers failed"))

if args.run_chisel:
Expand Down
11 changes: 4 additions & 7 deletions test/startservers.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,16 +199,14 @@ def install(race_detection):

return subprocess.call(["/usr/bin/make", "GO_BUILD_FLAGS=%s" % go_build_flags]) == 0

def run(cmd, fakeclock):
def run(cmd):
e = os.environ.copy()
e.setdefault("GORACE", "halt_on_error=1")
if fakeclock:
e.setdefault("FAKECLOCK", fakeclock)
p = subprocess.Popen(cmd, env=e)
p.cmd = cmd
return p

def start(fakeclock):
def start():
"""Return True if everything builds and starts.

Give up and return False if anything fails to build, or dies at
Expand Down Expand Up @@ -237,7 +235,7 @@ def start(fakeclock):
print("Starting service", service.name)
try:
global processes
p = run(service.cmd, fakeclock)
p = run(service.cmd)
processes.append(p)
if service.grpc_port is not None:
waithealth(' '.join(p.args), service.grpc_port, service.host_override)
Expand Down Expand Up @@ -297,8 +295,7 @@ def startChallSrv():
'--management', ':8055',
'--http01', '10.77.77.77:80',
'-https01', '10.77.77.77:443',
'--tlsalpn01', '10.88.88.88:443'],
None)
'--tlsalpn01', '10.88.88.88:443'])
# Wait for the pebble-challtestsrv management port.
if not waitport(8055, ' '.join(challSrvProcess.args)):
return False
Expand Down
119 changes: 0 additions & 119 deletions test/v2_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -1085,69 +1085,6 @@ def test_ct_submission():
if total_count < 2:
raise(Exception("Got %d total submissions, expected at least 2" % total_count))

def check_ocsp_basic_oid(cert_file, issuer_file, url):
"""
This function checks if an OCSP response was successful, but doesn't verify
the signature or timestamp. This is useful when simulating the past, so we
don't incorrectly reject a response for being in the past.
"""
ocsp_request = make_ocsp_req(cert_file, issuer_file)
responses = fetch_ocsp(ocsp_request, url)
# An unauthorized response (for instance, if the OCSP responder doesn't know
# about this cert) will just be 30 03 0A 01 06. A "good" or "revoked"
# response will contain, among other things, the id-pkix-ocsp-basic OID
# identifying the response type. We look for that OID to confirm we got a
# successful response.
expected = bytearray.fromhex("06 09 2B 06 01 05 05 07 30 01 01")
for resp in responses:
if not expected in bytearray(resp):
raise(Exception("Did not receive successful OCSP response: %s doesn't contain %s" %
(base64.b64encode(resp), base64.b64encode(expected))))

ocsp_exp_unauth_setup_data = {}
@register_six_months_ago
def ocsp_exp_unauth_setup():
client = chisel2.make_client(None)
cert_file = temppath('ocsp_exp_unauth_setup.pem')
chisel2.auth_and_issue([random_domain()], client=client, cert_output=cert_file.name)

# Since our servers are pretending to be in the past, but the openssl cli
# isn't, we'll get an expired OCSP response. Just check that it exists;
# don't do the full verification (which would fail).
lastException = None
for issuer_file in glob.glob("test/certs/webpki/int-rsa-*.cert.pem"):
try:
check_ocsp_basic_oid(cert_file.name, issuer_file, "http://localhost:4002")
global ocsp_exp_unauth_setup_data
ocsp_exp_unauth_setup_data['cert_file'] = cert_file.name
return
except Exception as e:
lastException = e
continue
raise(lastException)

def test_ocsp_exp_unauth():
tries = 0
if 'cert_file' not in ocsp_exp_unauth_setup_data:
raise Exception("ocsp_exp_unauth_setup didn't run")
cert_file = ocsp_exp_unauth_setup_data['cert_file']
last_error = ""
while tries < 5:
try:
verify_ocsp(cert_file, "test/certs/webpki/int-rsa-*.cert.pem", "http://localhost:4002", "XXX")
raise(Exception("Unexpected return from verify_ocsp"))
except subprocess.CalledProcessError as cpe:
last_error = cpe.output
if cpe.output == b"Responder Error: unauthorized (6)\n":
break
except e:
last_error = e
pass
tries += 1
time.sleep(0.25)
else:
raise(Exception("timed out waiting for unauthorized OCSP response for expired certificate. Last error: {}".format(last_error)))

def test_expiration_mailer():
email_addr = "integration.%[email protected]" % random.randrange(2**16)
order = chisel2.auth_and_issue([random_domain()], email=email_addr)
Expand Down Expand Up @@ -1324,59 +1261,3 @@ def test_auth_deactivation():
resp = client.deactivate_authorization(order.authorizations[0])
if resp.body.status is not messages.STATUS_DEACTIVATED:
raise Exception("unexpected authorization status")

def get_ocsp_response_and_reason(cert_file, issuer_glob, url):
"""Returns the ocsp response output and revocation reason."""
output = verify_ocsp(cert_file, issuer_glob, url, None)
m = re.search('Reason: (\w+)', output)
reason = m.group(1) if m is not None else ""
return output, reason

ocsp_resigning_setup_data = {}
@register_twenty_days_ago
def ocsp_resigning_setup():
"""Issue and then revoke a cert in the past.

Useful setup for test_ocsp_resigning, which needs to check that the
revocation reason is still correctly set after re-signing and old OCSP
response.
"""
client = chisel2.make_client(None)
cert_file = temppath('ocsp_resigning_setup.pem')
order = chisel2.auth_and_issue([random_domain()], client=client, cert_output=cert_file.name)

cert = OpenSSL.crypto.load_certificate(
OpenSSL.crypto.FILETYPE_PEM, order.fullchain_pem)
# Revoke for reason 5: cessationOfOperation
client.revoke(josepy.ComparableX509(cert), 5)

ocsp_response, reason = get_ocsp_response_and_reason(
cert_file.name, "test/certs/webpki/int-rsa-*.cert.pem", "http://localhost:4002")
global ocsp_resigning_setup_data
ocsp_resigning_setup_data = {
'cert_file': cert_file.name,
'response': ocsp_response,
'reason': reason
}

def test_ocsp_resigning():
"""Check that, after re-signing an OCSP, the reason is still set."""
if 'response' not in ocsp_resigning_setup_data:
raise Exception("ocsp_resigning_setup didn't run")

tries = 0
while tries < 5:
resp, reason = get_ocsp_response_and_reason(
ocsp_resigning_setup_data['cert_file'], "test/certs/webpki/int-rsa-*.cert.pem", "http://localhost:4002")
if resp != ocsp_resigning_setup_data['response']:
break
tries += 1
time.sleep(0.25)
else:
raise(Exception("timed out waiting for re-signed OCSP response for certificate"))

if reason != ocsp_resigning_setup_data['reason']:
raise(Exception("re-signed ocsp response has different reason %s expected %s" % (
reason, ocsp_resigning_setup_data['reason'])))
if reason != "cessationOfOperation":
raise(Exception("re-signed ocsp response has wrong reason %s" % reason))
Loading