def test_driver(self): # Run the driver program to issue the certificate. import subprocess subprocess.check_call([ sys.executable, "free_tls_certificates/driver.py", "--server", ACME_SERVER, ] + domains + [ os.path.join(self.output_dir, 'driver_private.key'), os.path.join(self.output_dir, 'driver_certificate.crt'), self.challenges_dir, self.account_dir, ], env={ "PYTHONPATH": ".:" + ":".join(sys.path) }) # Check that the private key was written. self.assertTrue(os.path.exists(os.path.join(self.output_dir, 'driver_private.key'))) # Check that the certificate is valid. cert = load_cert_chain(os.path.join(self.output_dir, 'driver_certificate.crt')) self.assertEqual(len(cert), 2) # two elements in chain cert_domains = get_certificate_domains(cert[0]) self.assertEqual(cert_domains[0], domains[0]) self.assertEqual(set(cert_domains), set(domains)) # Check that the chain is valid. chain_names = get_certificate_domains(cert[1]) self.assertEqual(chain_names[0], 'happy hacker fake CA') # Check that the certificate is signed by the first element in the chain. self.assertEqual(cert[0].issuer, cert[1].subject)
def test_self_signed(self): self.do_issue(domains=["selfsigned.le.wtf", "www.selfsigned.le.wtf"], self_signed=True) from free_tls_certificates.utils import load_certificate, get_certificate_cn, get_certificate_domains cert = load_certificate(os.path.join(self.output_dir, "certificate.crt")) self.assertEqual(cert.issuer, cert.subject) self.assertEqual(get_certificate_cn(cert), "selfsigned.le.wtf") self.assertEqual(set(get_certificate_domains(cert)), set(["selfsigned.le.wtf", "www.selfsigned.le.wtf"]))
def test_self_signed(self): self.do_issue(domains=["selfsigned.le.wtf", "www.selfsigned.le.wtf"], self_signed=True) from free_tls_certificates.utils import load_certificate, get_certificate_cn, get_certificate_domains cert = load_certificate( os.path.join(self.output_dir, "certificate.crt")) self.assertEqual(cert.issuer, cert.subject) self.assertEqual(get_certificate_cn(cert), "selfsigned.le.wtf") self.assertEqual(set(get_certificate_domains(cert)), set(["selfsigned.le.wtf", "www.selfsigned.le.wtf"]))
def stop_if_certificate_valid(opts): # Stop if the certificate is already valid for all of the domains. import idna if not os.path.exists(opts["certificate_fn"]): if sys.stdin.isatty(): sys.stderr.write("Certificate file %s not present...\n" % opts["certificate_fn"]) return def idna_encode(domain): # squash exceptions here try: return idna.encode(domain).decode("ascii") except: return domain # Load the certificate. from free_tls_certificates.utils import load_certificate, get_certificate_domains cert = load_certificate(opts["certificate_fn"]) # If this is a self-signed certificate (and the user is seeking # a real one), provision a new one. if cert.issuer == cert.subject and not opts["self_signed"]: if sys.stdin.isatty(): sys.stderr.write("Replacing self-signed certificate...\n") return # If this is expiring within 30 days, provision a new one. expires_in = cert.not_valid_after - datetime.datetime.now() if expires_in < datetime.timedelta(days=30): if sys.stdin.isatty(): sys.stderr.write( "Replacing expiring certificate (expires in %s)...\n" % str(expires_in)) return # If the certificate is not valid for one of the domains we're requesting, # provision a new one. request_domains = set(idna_encode(domain) for domain in opts["domains"]) cert_domains = set(get_certificate_domains(cert)) if len(request_domains - cert_domains) > 0: if sys.stdin.isatty(): sys.stderr.write( "Certificate is not valid for %s (found %s)...\n" % (", ".join( x.decode('ascii') for x in (request_domains - cert_domains)), ", ".join( x.decode('ascii') for x in cert_domains))) return # Certificate is valid for the requested domains - no need to provision. if sys.stdout.isatty(): print("Certificate is already valid and good for at least 30 days.") sys.exit(3)
def stop_if_certificate_valid(opts): # Stop if the certificate is already valid for all of the domains. import idna if not os.path.exists(opts["certificate_fn"]): if sys.stdin.isatty(): sys.stderr.write("Certificate file %s not present...\n" % opts["certificate_fn"]) return def idna_encode(domain): # squash exceptions here try: return idna.encode(domain).decode("ascii") except: return domain # Load the certificate. from free_tls_certificates.utils import load_certificate, get_certificate_domains cert = load_certificate(opts["certificate_fn"]) # If this is a self-signed certificate (and the user is seeking # a real one), provision a new one. if cert.issuer == cert.subject and not opts["self_signed"]: if sys.stdin.isatty(): sys.stderr.write("Replacing self-signed certificate...\n") return # If this is expiring within 30 days, provision a new one. expires_in = cert.not_valid_after - datetime.datetime.now() if expires_in < datetime.timedelta(days=30): if sys.stdin.isatty(): sys.stderr.write("Replacing expiring certificate (expires in %s)...\n" % str(expires_in)) return # If the certificate is not valid for one of the domains we're requesting, # provision a new one. request_domains = set(idna_encode(domain) for domain in opts["domains"]) cert_domains = set(get_certificate_domains(cert)) if len(request_domains - cert_domains) > 0: if sys.stdin.isatty(): sys.stderr.write("Certificate is not valid for %s (found %s)...\n" % ( ", ".join(request_domains - cert_domains), ", ".join(cert_domains) )) return # Certificate is valid for the requested domains - no need to provision. if sys.stdout.isatty(): print("Certificate is already valid and good for at least 30 days.") sys.exit(3)
def _check_certificate(vhost, days=30, self_signed=False): if not os.path.exists(vhost.certificate_file): logger.info("Certificate file of %s not present.", vhost) return False # Load the certificate. cert = freetlsutis.load_certificate(vhost.certificate_file) # If this is a self-signed certificate (and the user is seeking # a real one), provision a new one. if cert.issuer == cert.subject and not self_signed: logger.info("Replacing self-signed certificate of %s", vhost) return False # If this is expiring within the given days, provision a new one. expires_in = cert.not_valid_after - datetime.datetime.now() if expires_in < datetime.timedelta(days=days): logger.info("Replacing expiring certificate of %s (expires in %s).", vhost, expires_in) return False # If the certificate is not valid for one of the domains # we're requesting, provision a new one. def idna_encode(domain): # squash exceptions here try: return idna.encode(domain).decode("ascii") except Exception: # pylint: disable=W0703 return domain request_domains = set(idna_encode(domain) for domain in vhost.domains) cert_domains = set(freetlsutis.get_certificate_domains(cert)) missing_domains = request_domains - cert_domains if missing_domains: logger.info("Certificate of %s is not valid for: %s", vhost, missing_domains) return False # Certificate is valid for the requested domains - no need to provision. logger.info("Certificate of %s is valid", vhost) return True
def test__main(self): # Call the first time. It raises an exception telling us the # URL to the terms of service agreement the user needs to agree to. with self.assertRaises(client.NeedToAgreeToTOS) as cm: self.do_issue() tos_url = cm.exception.url # Now agree. But it'll raise an exception telling us we need # to make a file available at a certain URL. with self.assertRaises(client.NeedToTakeAction) as cm: self.do_issue(agree_to_tos_url=tos_url) actions = cm.exception.actions # It should give us as many actions as domains we asked to verify. self.assertEqual(len(actions), len(domains)) for action in actions: # Check that each action is a HTTP validation file request. self.assertIsInstance(action, client.NeedToInstallFile) self.assertTrue( re.match(r"http://[^/]+/.well-known/acme-challenge/", action.url)) self.assertTrue( re.match(r"^[A-Za-z0-9\._-]{60,100}$", action.contents)) self.assertTrue( re.match(r"^[A-Za-z0-9_-]{40,50}$", action.file_name)) # Create the file so we can pass validation. We write it to the # directory that our local HTTP server is serving. fn = os.path.join(self.challenges_dir, action.file_name) with open(fn, 'w') as f: f.write(action.contents) # Try to get the certificate again, but it'll tell us to wait while # the ACME server processes the request. with self.assertRaises(client.WaitABit) as cm: self.do_issue() # Now actually wait until the certificate is issued. while True: try: # Try to get the certificate again. self.do_issue() # Success. break except client.WaitABit: time.sleep(1) continue # Check that the certificate is valid. cert = load_cert_chain(os.path.join(self.output_dir, 'certificate.crt')) self.assertEqual(len(cert), 1) # one element in certificate file cert_domains = get_certificate_domains(cert[0]) self.assertEqual(cert_domains[0], domains[0]) self.assertEqual(set(cert_domains), set(domains)) # Check that the chain is valid. chain = load_cert_chain(os.path.join(self.output_dir, 'chain.crt')) self.assertEqual(len(chain), 1) # one element in chain chain_names = get_certificate_domains(chain[0]) self.assertEqual(chain_names[0], 'happy hacker fake CA') # Check that the certificate is signed by the first element in the chain. self.assertEqual(cert[0].issuer, chain[0].subject)
def test_driver(self, self_signed=False): # Run the driver program to issue the certificate. # Make sure no certificate file already exists. cert_fn = os.path.join(self.output_dir, 'driver_certificate.crt') if os.path.exists(cert_fn): os.unlink(cert_fn) # Run the driver. import subprocess def execute_driver_app(): if not self_signed: args = ["--server", ACME_SERVER] else: args = ["--self-signed"] subprocess.check_call( [ sys.executable, "free_tls_certificates/driver.py", ] + args + domains + [ os.path.join(self.output_dir, 'driver_private.key'), os.path.join(self.output_dir, 'driver_certificate.crt'), ] + ([ self.challenges_dir, self.account_dir, ] if not self_signed else []), env={"PYTHONPATH": ".:" + ":".join(sys.path)}) execute_driver_app() # Check that the private key was written. self.assertTrue( os.path.exists(os.path.join(self.output_dir, 'driver_private.key'))) # Check that the certificate is valid. cert = load_cert_chain(cert_fn) if not self_signed: self.assertEqual(len(cert), 2) # two elements in chain else: self.assertEqual(len(cert), 1) # no chain, just the cert cert_domains = get_certificate_domains(cert[0]) self.assertEqual(cert_domains[0], domains[0]) self.assertEqual(set(cert_domains), set(domains)) if not self_signed: # Check that the chain is valid. chain_names = get_certificate_domains(cert[1]) self.assertEqual(chain_names[0], 'happy hacker fake CA') # Check that the certificate is signed by the first element in the chain. self.assertEqual(cert[0].issuer, cert[1].subject) else: # Check that the certificate is actually self-signed. from free_tls_certificates.utils import load_certificate cert = load_certificate(cert_fn) self.assertEqual(cert.issuer, cert.subject) # Run the driver again --- this time it should say that the certificate # exists and is valid and exits with a return code of 3. with self.assertRaises(subprocess.CalledProcessError) as cm: execute_driver_app() self.assertEqual(cm.exception.returncode, 3)
def test__main(self): # Call the first time. It raises an exception telling us the # URL to the terms of service agreement the user needs to agree to. with self.assertRaises(client.NeedToAgreeToTOS) as cm: self.do_issue() tos_url = cm.exception.url # Now agree. But it'll raise an exception telling us we need # to make a file available at a certain URL. with self.assertRaises(client.NeedToTakeAction) as cm: self.do_issue(agree_to_tos_url=tos_url) actions = cm.exception.actions # It should give us as many actions as domains we asked to verify. self.assertEqual(len(actions), len(domains)) for action in actions: # Check that each action is a HTTP validation file request. self.assertIsInstance(action, client.NeedToInstallFile) self.assertTrue(re.match(r"http://[^/]+/.well-known/acme-challenge/", action.url)) self.assertTrue(re.match(r"^[A-Za-z0-9\._-]{60,100}$", action.contents)) self.assertTrue(re.match(r"^[A-Za-z0-9_-]{40,50}$", action.file_name)) # Create the file so we can pass validation. We write it to the # directory that our local HTTP server is serving. fn = os.path.join(self.challenges_dir, action.file_name) with open(fn, 'w') as f: f.write(action.contents) # Try to get the certificate again, but it'll tell us to wait while # the ACME server processes the request. with self.assertRaises(client.WaitABit) as cm: self.do_issue() # Now actually wait until the certificate is issued. while True: try: # Try to get the certificate again. self.do_issue() # Success. break except client.WaitABit: time.sleep(1) continue # Check that the certificate is valid. cert = load_cert_chain(os.path.join(self.output_dir, 'certificate.crt')) self.assertEqual(len(cert), 1) # one element in certificate file cert_domains = get_certificate_domains(cert[0]) self.assertEqual(cert_domains[0], domains[0]) self.assertEqual(set(cert_domains), set(domains)) # Check that the chain is valid. chain = load_cert_chain(os.path.join(self.output_dir, 'chain.crt')) self.assertEqual(len(chain), 1) # one element in chain chain_names = get_certificate_domains(chain[0]) self.assertEqual(chain_names[0], 'happy hacker fake CA') # Check that the certificate is signed by the first element in the chain. self.assertEqual(cert[0].issuer, chain[0].subject)
def test_driver(self, self_signed=False): # Run the driver program to issue the certificate. # Make sure no certificate file already exists. cert_fn = os.path.join(self.output_dir, 'driver_certificate.crt') if os.path.exists(cert_fn): os.unlink(cert_fn) # Run the driver. import subprocess def execute_driver_app(): if not self_signed: args = ["--server", ACME_SERVER] else: args = ["--self-signed"] subprocess.check_call( [ sys.executable, "free_tls_certificates/driver.py", ] + args + domains + [ os.path.join(self.output_dir, 'driver_private.key'), os.path.join(self.output_dir, 'driver_certificate.crt'), ] + ([ self.challenges_dir, self.account_dir, ] if not self_signed else []) , env={ "PYTHONPATH": ".:" + ":".join(sys.path) }) execute_driver_app() # Check that the private key was written. self.assertTrue(os.path.exists(os.path.join(self.output_dir, 'driver_private.key'))) # Check that the certificate is valid. cert = load_cert_chain(cert_fn) if not self_signed: self.assertEqual(len(cert), 2) # two elements in chain else: self.assertEqual(len(cert), 1) # no chain, just the cert cert_domains = get_certificate_domains(cert[0]) self.assertEqual(cert_domains[0], domains[0]) self.assertEqual(set(cert_domains), set(domains)) if not self_signed: # Check that the chain is valid. chain_names = get_certificate_domains(cert[1]) self.assertEqual(chain_names[0], 'happy hacker fake CA') # Check that the certificate is signed by the first element in the chain. self.assertEqual(cert[0].issuer, cert[1].subject) else: # Check that the certificate is actually self-signed. from free_tls_certificates.utils import load_certificate cert = load_certificate(cert_fn) self.assertEqual(cert.issuer, cert.subject) # Run the driver again --- this time it should say that the certificate # exists and is valid and exits with a return code of 3. with self.assertRaises(subprocess.CalledProcessError) as cm: execute_driver_app() self.assertEqual(cm.exception.returncode, 3)