Ejemplo n.º 1
0
 def test_rsa_key(self):
     """
     Passing ``u'rsa'`` results in an RSA private key.
     """
     key1 = generate_private_key(u'rsa')
     self.assertThat(key1, IsInstance(rsa.RSAPrivateKey))
     key2 = generate_private_key(u'rsa')
     self.assertThat(key2, IsInstance(rsa.RSAPrivateKey))
     self.assertThat(key1.public_key().public_numbers(),
                     Not(Equals(key2.public_key().public_numbers())))
Ejemplo n.º 2
0
 def test_rsa_key(self):
     """
     Passing ``u'rsa'`` results in an RSA private key.
     """
     key1 = generate_private_key(u'rsa')
     self.assertThat(key1, IsInstance(rsa.RSAPrivateKey))
     key2 = generate_private_key(u'rsa')
     self.assertThat(key2, IsInstance(rsa.RSAPrivateKey))
     self.assertThat(
         key1.public_key().public_numbers(),
         Not(Equals(key2.public_key().public_numbers())))
Ejemplo n.º 3
0
 def test_rsa_key(self):
     """
     Passing ``u'rsa'`` results in an RSA private key.
     """
     key1 = generate_private_key(u'rsa')
     self.assertIsInstance(key1,rsa.RSAPrivateKey)
     key2 = generate_private_key(u'rsa')
     self.assertIsInstance(key2, rsa.RSAPrivateKey)
     self.assertNotEqual(
         key1.public_key().public_numbers(),
         key2.public_key().public_numbers()
         )
Ejemplo n.º 4
0
def generate_wildcard_pem_bytes():
    """
    Generate a wildcard (subject name '*') self-signed certificate valid for
    10 years.

    https://cryptography.io/en/latest/x509/tutorial/#creating-a-self-signed-certificate

    :return: Bytes representation of the PEM certificate data
    """
    key = generate_private_key(u'rsa')
    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'*')])
    cert = (x509.CertificateBuilder().issuer_name(name).subject_name(
        name).not_valid_before(datetime.today() - timedelta(
            days=1)).not_valid_after(datetime.now() +
                                     timedelta(days=3650)).serial_number(
                                         int(uuid.uuid4())).public_key(
                                             key.public_key()).sign(
                                                 private_key=key,
                                                 algorithm=hashes.SHA256(),
                                                 backend=default_backend()))

    return b''.join((key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption()),
                     cert.public_bytes(serialization.Encoding.PEM)))
Ejemplo n.º 5
0
def _parse(reactor, directory, pemdir, *args, **kwargs):
    """
    Parse a txacme endpoint description.

    :param reactor: The Twisted reactor.
    :param directory: ``twisted.python.url.URL`` for the ACME directory to use
        for issuing certs.
    :param str pemdir: The path to the certificate directory to use.
    """
    onstore_scripts = kwargs.pop('onstore', 'false').lower().startswith('t')
    def colon_join(items):
        return ':'.join([item.replace(':', '\\:') for item in items])
    sub = colon_join(list(args) + ['='.join(item) for item in kwargs.items()])
    pem_path = FilePath(pemdir).asTextMode()
    acme_key_file = pem_path.child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(
            acme_key_file.getContent(),
            password=None,
            backend=default_backend())
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))
    acme_key = JWKRSA(key=key)
    return AutoTLSEndpoint(
        reactor=reactor,
        directory=directory,
        client_creator=partial(Client.from_url, key=acme_key, alg=RS256),
        cert_store=DirectoryStore(pem_path, onstore_scripts=onstore_scripts),
        cert_mapping=HostDirectoryMap(pem_path),
        sub_endpoint=serverFromString(reactor, sub))
Ejemplo n.º 6
0
 def _generate_ca_cert(self):
     """
     Generate a CA cert/key.
     """
     if self._ca_key is None:
         self._ca_key = generate_private_key(u'rsa')
     self._ca_name = x509.Name([
         x509.NameAttribute(NameOID.COMMON_NAME, u'ACME Snake Oil CA')])
     self._ca_cert = (
         x509.CertificateBuilder()
         .subject_name(self._ca_name)
         .issuer_name(self._ca_name)
         .not_valid_before(self._now() - timedelta(seconds=3600))
         .not_valid_after(self._now() + timedelta(days=3650))
         .public_key(self._ca_key.public_key())
         .serial_number(int(uuid4()))
         .add_extension(
             x509.BasicConstraints(ca=True, path_length=0),
             critical=True)
         .add_extension(
             x509.SubjectKeyIdentifier.from_public_key(
                 self._ca_key.public_key()),
             critical=False)
         .sign(
             private_key=self._ca_key,
             algorithm=hashes.SHA256(),
             backend=default_backend()))
     self._ca_aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(
         self._ca_key.public_key())
Ejemplo n.º 7
0
def load_or_create_client_key(key_file):
    """Load the ACME account key from a file, creating it if it does not exist.

    Args:
        key_file (str): name of the file to use as the account key
    """
    # this is based on txacme.endpoint.load_or_create_client_key, but doesn't
    # hardcode the 'client.key' filename
    acme_key_file = FilePath(key_file)
    if acme_key_file.exists():
        logger.info("Loading ACME account key from '%s'", acme_key_file)
        key = serialization.load_pem_private_key(
            acme_key_file.getContent(), password=None, backend=default_backend()
        )
    else:
        logger.info("Saving new ACME account key to '%s'", acme_key_file)
        key = generate_private_key("rsa")
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption(),
            )
        )
    return JWKRSA(key=key)
Ejemplo n.º 8
0
def generate_wildcard_pem_bytes():
    """
    Generate a wildcard (subject name '*') self-signed certificate valid for
    10 years.

    https://cryptography.io/en/latest/x509/tutorial/#creating-a-self-signed-certificate

    :return: Bytes representation of the PEM certificate data
    """
    key = generate_private_key(u'rsa')
    name = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u'*')])
    cert = (
        x509.CertificateBuilder()
        .issuer_name(name)
        .subject_name(name)
        .not_valid_before(datetime.today() - timedelta(days=1))
        .not_valid_after(datetime.now() + timedelta(days=3650))
        .serial_number(int(uuid.uuid4()))
        .public_key(key.public_key())
        .sign(
            private_key=key,
            algorithm=hashes.SHA256(),
            backend=default_backend())
        )

    return b''.join((
        key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()),
        cert.public_bytes(serialization.Encoding.PEM)
    ))
Ejemplo n.º 9
0
def maybe_key(pem_path):
    """
    Set up a client key if one does not exist already.

    https://gist.github.com/glyph/27867a478bb71d8b6046fbfb176e1a33#file-local-certs-py-L32-L50

    :type pem_path: twisted.python.filepath.FilePath
    :param pem_path:
        The path to the certificate directory to use.
    """
    acme_key_file = pem_path.child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(
            acme_key_file.getContent(),
            password=None,
            backend=default_backend()
        )
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()
            )
        )
    return JWKRSA(key=key)
    def setup_method(self):
        self.fake_marathon = FakeMarathon()
        self.fake_marathon_api = FakeMarathonAPI(self.fake_marathon)

        self.cert_store = MemoryStore()

        self.fake_marathon_lb = FakeMarathonLb()

        key = JWKRSA(key=generate_private_key(u'rsa'))
        self.clock = Clock()
        self.clock.rightNow = (
            datetime.now() - datetime(1970, 1, 1)).total_seconds()
        self.txacme_client = FailableTxacmeClient(key, self.clock)
Ejemplo n.º 11
0
def maybe_key(pem_path):
    acme_key_file = pem_path.child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(acme_key_file.getContent(),
                                                 password=None,
                                                 backend=default_backend())
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))
    acme_key = JWKRSA(key=key)
    return acme_key
    def test_key_exists(self, pem_path):
        """
        When we get the client key and the key file already exists, the file
        should be read and the existing key returned.
        """
        raw_key = generate_private_key(u'rsa')
        expected_key = JWKRSA(key=raw_key)

        pem_file = pem_path.child(u'client.key')
        pem_file.setContent(raw_key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.TraditionalOpenSSL,
            encryption_algorithm=serialization.NoEncryption()
        ))

        actual_key = maybe_key(pem_path)
        assert_that(actual_key, Equals(expected_key))
Ejemplo n.º 13
0
    def _test_issue(self, name):
        def got_cert(certr):
            key_bytes = self.issued_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption())
            FilePath('issued.crt').setContent(certr.body)
            FilePath('issued.key').setContent(key_bytes)
            return certr

        action = start_action(action_type=u'integration:issue')
        with action.context():
            self.issued_key = generate_private_key('rsa')
            csr = csr_for_names([name], self.issued_key)
            return (DeferredContext(
                self.client.request_issuance(CertificateRequest(
                    csr=csr))).addCallback(got_cert).addActionFinish())
Ejemplo n.º 14
0
    def _test_issue(self, name):
        def got_cert(certr):
            key_bytes = self.issued_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption())
            FilePath('issued.crt').setContent(certr.body)
            FilePath('issued.key').setContent(key_bytes)
            return certr

        action = start_action(action_type=u'integration:issue')
        with action.context():
            self.issued_key = generate_private_key('rsa')
            csr = csr_for_names([name], self.issued_key)
            return (
                DeferredContext(
                    self.client.request_issuance(CertificateRequest(csr=csr)))
                .addCallback(got_cert)
                .addActionFinish())
Ejemplo n.º 15
0
def _get_account_key():
    """
    Return the private key to be used for ACME interaction.
    """
    if ACCOUNT_KEY_PEM:
        return serialization.load_pem_private_key(
            ACCOUNT_KEY_PEM.encode('ascii'),
            password=None,
            backend=default_backend(),
        )
    # We don't have a key...so generate one.
    key = generate_private_key('rsa')
    account_key = key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.TraditionalOpenSSL,
        encryption_algorithm=serialization.NoEncryption(),
    )
    print('New account key generated:\n%s' % (account_key))
    return key
Ejemplo n.º 16
0
    def setup_method(self):
        self.fake_marathon = FakeMarathon()
        self.fake_marathon_api = FakeMarathonAPI(self.fake_marathon)
        marathon_client = MarathonClient(['http://localhost:8080'],
                                         client=self.fake_marathon_api.client)

        self.cert_store = MemoryStore()

        self.fake_marathon_lb = FakeMarathonLb()
        mlb_client = MarathonLbClient(['http://localhost:9090'],
                                      client=self.fake_marathon_lb.client)

        key = JWKRSA(key=generate_private_key(u'rsa'))
        clock = Clock()
        clock.rightNow = (datetime.now() -
                          datetime(1970, 1, 1)).total_seconds()
        self.txacme_client = FailableTxacmeClient(key, clock)

        self.marathon_acme = MarathonAcme(marathon_client, 'external',
                                          self.cert_store, mlb_client,
                                          lambda: succeed(self.txacme_client),
                                          clock)
Ejemplo n.º 17
0
def maybe_key(pem_path):
    """
    Set up a client key if one does not exist already.

    https://gist.github.com/glyph/27867a478bb71d8b6046fbfb176e1a33#file-local-certs-py-L32-L50

    :type pem_path: twisted.python.filepath.FilePath
    :param pem_path:
        The path to the certificate directory to use.
    """
    acme_key_file = pem_path.child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(acme_key_file.getContent(),
                                                 password=None,
                                                 backend=default_backend())
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))
    return jose.JWKRSA(key=key)
Ejemplo n.º 18
0
def load_or_create_client_key(pem_path):
    """
    Load the client key from a directory, creating it if it does not exist.

    .. note:: The client key that will be created will be a 2048-bit RSA key.

    :type pem_path: ``twisted.python.filepath.FilePath``
    :param pem_path: The certificate directory
        to use, as with the endpoint.
    """
    acme_key_file = pem_path.asTextMode().child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(acme_key_file.getContent(),
                                                 password=None,
                                                 backend=default_backend())
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))
    return JWKRSA(key=key)
Ejemplo n.º 19
0
def load_or_create_client_key(pem_path):
    """
    Load the client key from a directory, creating it if it does not exist.

    .. note:: The client key that will be created will be a 2048-bit RSA key.

    :type pem_path: ``twisted.python.filepath.FilePath``
    :param pem_path: The certificate directory
        to use, as with the endpoint.
    """
    acme_key_file = pem_path.asTextMode().child(u'client.key')
    if acme_key_file.exists():
        key = serialization.load_pem_private_key(
            acme_key_file.getContent(),
            password=None,
            backend=default_backend())
    else:
        key = generate_private_key(u'rsa')
        acme_key_file.setContent(
            key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))
    return JWKRSA(key=key)
Ejemplo n.º 20
0
 def _generate_ca_cert(self):
     """
     Generate a CA cert/key.
     """
     if self._ca_key is None:
         self._ca_key = generate_private_key(u'rsa')
     self._ca_name = x509.Name(
         [x509.NameAttribute(NameOID.COMMON_NAME, u'ACME Snake Oil CA')])
     self._ca_cert = (
         x509.CertificateBuilder().subject_name(self._ca_name).issuer_name(
             self._ca_name).not_valid_before(self._now() -
                                             timedelta(seconds=3600)).
         not_valid_after(self._now() + timedelta(days=3650)).public_key(
             self._ca_key.public_key()).serial_number(int(
                 uuid4())).add_extension(
                     x509.BasicConstraints(ca=True, path_length=0),
                     critical=True).add_extension(
                         x509.SubjectKeyIdentifier.from_public_key(
                             self._ca_key.public_key()),
                         critical=False).sign(private_key=self._ca_key,
                                              algorithm=hashes.SHA256(),
                                              backend=default_backend()))
     self._ca_aki = x509.AuthorityKeyIdentifier.from_issuer_public_key(
         self._ca_key.public_key())
Ejemplo n.º 21
0
 def test_unknown_key_type(self, key_type):
     """
     Passing an unknown key type results in :exc:`.ValueError`.
     """
     with ExpectedException(ValueError):
         generate_private_key(key_type)
Ejemplo n.º 22
0
 def _test_create_client(self):
     with start_action(action_type=u'integration:create_client').context():
         self.key = JWKRSA(key=generate_private_key('rsa'))
         return (
             DeferredContext(self._create_client(self.key))
             .addActionFinish())
Ejemplo n.º 23
0
 def test_unknown_key_type(self):
     """
     Passing an unknown key type results in :exc:`.ValueError`.
     """
     with self.assertRaises(ValueError):
         generate_private_key(u'not-a-real-key-type')
Ejemplo n.º 24
0
 def test_unknown_key_type(self, key_type):
     """
     Passing an unknown key type results in :exc:`.ValueError`.
     """
     with ExpectedException(ValueError):
         generate_private_key(key_type)
Ejemplo n.º 25
0
def get_things_done():
    """
    Here is where the client part is setup and action is done.
    """
    responders = yield start_responders()

    # We first validate the directory.
    account_key = _get_account_key()
    try:
        client = yield Client.from_url(
            reactor,
            URL.fromText(acme_url.decode('utf-8')),
            key=JWKRSA(key=account_key),
            alg=RS256,
        )
    except Exception as error:
        print('\n\nFailed to connect to ACME directory. %s' % (error, ))
        yield reactor.stop()
        defer.returnValue(None)

    # Then we register a new account or update an existing account.
    # First register a new account with a contact set, then using the same
    # key call register with a different contact and see that it was updated.
    response = yield client.start(
        email='[email protected],[email protected]')

    print('Account URI: %s' % (response.uri, ))
    print('Account contact: %s' % (response.body.contact, ))

    # We request a single certificate for a list of domains and get an "order"
    cert_key = generate_private_key('rsa')
    orderr = yield client.submit_order(cert_key, requested_domains)

    # Each order had a list of "authorizations" for which the challenge needs
    # to be validated.
    for authorization in orderr.authorizations:
        try:
            # Make sure all ACME server requests are sequential.
            # For now, answering to the challenges in parallel will not work.
            yield answer_challenge(authorization,
                                   client,
                                   responders,
                                   clock=reactor)
        except Exception as error:
            print('\n\nFailed to validate a challenge. %s' % (error, ))
            yield reactor.stop()
            defer.returnValue(None)

    certificate = yield get_certificate(orderr, client, clock=reactor)

    print('Got a new cert:\n')
    print(certificate.body)

    cert_key_pem = cert_key.private_bytes(
        encoding=serialization.Encoding.PEM,
        format=serialization.PrivateFormat.PKCS8,
        encryption_algorithm=serialization.NoEncryption(),
    )

    # Cleanup the client and disconnect any persistent connection to the
    # ACME server.
    yield client.stop()

    # The new certificate is available and we can start a demo HTTPS server
    # using it.
    yield start_https_demo_server(cert_key_pem, certificate.body)
    print('txacme demo done.')