Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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"]))
Ejemplo n.º 3
0
    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"]))
Ejemplo n.º 4
0
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)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
    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
Ejemplo n.º 7
0
    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)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
    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)