Ejemplo n.º 1
0
 def _call_with_key(cls, *args, **kwargs):
     privkey = OpenSSL.crypto.PKey()
     privkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
     privkey_pem = OpenSSL.crypto.dump_privatekey(
         OpenSSL.crypto.FILETYPE_PEM, privkey)
     from acme.crypto_util import make_csr
     return make_csr(privkey_pem, *args, **kwargs)
Ejemplo n.º 2
0
def test_revoke_by_privkey():
    client = make_client(None)
    domains = [random_domain()]
    key = OpenSSL.crypto.PKey()
    key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
    key_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
    csr_pem = acme_crypto_util.make_csr(key_pem, domains, False)
    order = client.new_order(csr_pem)
    cleanup = do_http_challenges(client, order.authorizations)
    try:
        order = client.poll_and_finalize(order)
    finally:
        cleanup()

    # Create a new client with the JWK as the cert private key
    jwk = jose.JWKRSA(key=key)
    net = acme_client.ClientNetwork(key,
                                    user_agent="Boulder integration tester")

    directory = Directory.from_json(net.get(chisel2.DIRECTORY).json())
    new_client = acme_client.ClientV2(directory, net)

    cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                           order.fullchain_pem)
    client.revoke(jose.ComparableX509(cert), 0)
Ejemplo n.º 3
0
def perform(
    certificate: Certificate,
    storage: "StorageProtocol",
    acme_account_email: str,
    acme_directory_url: str,
    authenticators: typing.Sequence[AuthenticatorProtocol],
) -> None:
    client = setup_client(
        storage=storage,
        directory_url=acme_directory_url,
        account_email=acme_account_email,
    )

    orderr = client.new_order(
        crypto_util.make_csr(certificate.private_key, certificate.domains))
    auth_challs = select_challs(orderr, authenticators)
    for authenticator, challs in auth_challs:
        account_key = client.net.key
        authenticator.perform(challs, account_key)
        for challb, _ in challs:
            client.answer_challenge(challb, challb.response(account_key))
    try:
        finalized_orderr = client.poll_and_finalize(orderr)
        fullchain_pem = finalized_orderr.fullchain_pem.encode("utf8")
        certificate.set_fullchain(fullchain_pem)
        storage.save_certificate(certificate)
    finally:
        for authenticator, challs in auth_challs:
            authenticator.cleanup(challs, account_key)
Ejemplo n.º 4
0
def init_save_csr(privkey, names, path):
    """Initialize a CSR with the given private key.

    :param privkey: Key to include in the CSR
    :type privkey: :class:`certbot.util.Key`

    :param set names: `str` names to include in the CSR

    :param str path: Certificate save directory.

    :returns: CSR
    :rtype: :class:`certbot.util.CSR`

    """
    config = zope.component.getUtility(interfaces.IConfig)

    csr_pem = acme_crypto_util.make_csr(
        privkey.pem, names, must_staple=config.must_staple)

    # Save CSR
    util.make_or_verify_dir(path, 0o755, os.geteuid(),
                               config.strict_permissions)
    csr_f, csr_filename = util.unique_file(
        os.path.join(path, "csr-certbot.pem"), 0o644, "wb")
    with csr_f:
        csr_f.write(csr_pem)
    logger.debug("Creating CSR: %s", csr_filename)

    return util.CSR(csr_filename, csr_pem, "pem")
Ejemplo n.º 5
0
def request_new_certificate(hostname, accnt_key, priv_key, tmp_chall_dict, directory_url):
    """Runs the entire process of ACME registration and certificate request"""

    client = create_v2_client(directory_url, accnt_key)

    try:
        client.net.account = client.new_account(
            messages.NewRegistration.from_data(
                terms_of_service_agreed=True
            )
        )

    except errors.ConflictError as error:
        existing_reg = messages.RegistrationResource(uri=error.location)
        existing_reg = client.query_registration(existing_reg)
        client.update_registration(existing_reg)

    csr = crypto_util.make_csr(priv_key, [hostname], False)
    order = client.new_order(csr)

    log.info('Created a new order for the issuance of a certificate for %s', hostname)

    challb = select_http01_chall(order)

    _, chall_tok = challb.response_and_validation(client.net.key)
    v = challb.chall.encode("token")
    log.info('Exposing challenge on %s', v)
    tmp_chall_dict.set(v, ChallTok(chall_tok))

    cr = client.answer_challenge(challb, challb.response(client.net.key))
    log.debug('Acme CA responded to challenge request with: %s', cr)

    order = client.poll_and_finalize(order)

    return split_certificate_chain(order.fullchain_pem)
Ejemplo n.º 6
0
def generate_csr(domains, key_path, csr_path, key_type=RSA_KEY_TYPE):
    """
    Generate a private key, and a CSR for the given domains using this key.
    :param domains: the domain names to include in the CSR
    :type domains: `list` of `str`
    :param str key_path: path to the private key that will be generated
    :param str csr_path: path to the CSR that will be generated
    :param str key_type: type of the key (misc.RSA_KEY_TYPE or misc.ECDSA_KEY_TYPE)
    """
    if key_type == RSA_KEY_TYPE:
        key = crypto.PKey()
        key.generate_key(crypto.TYPE_RSA, 2048)
    elif key_type == ECDSA_KEY_TYPE:
        key = ec.generate_private_key(ec.SECP384R1(), default_backend())
        key = key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL,
                                encryption_algorithm=NoEncryption())
        key = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
    else:
        raise ValueError('Invalid key type: {0}'.format(key_type))

    key_bytes = crypto.dump_privatekey(crypto.FILETYPE_PEM, key)
    with open(key_path, 'wb') as file:
        file.write(key_bytes)

    csr_bytes = crypto_util.make_csr(key_bytes, domains)
    with open(csr_path, 'wb') as file:
        file.write(csr_bytes)
Ejemplo n.º 7
0
def init_save_csr(privkey, names, path):
    """Initialize a CSR with the given private key.

    :param privkey: Key to include in the CSR
    :type privkey: :class:`certbot.util.Key`

    :param set names: `str` names to include in the CSR

    :param str path: Certificate save directory.

    :returns: CSR
    :rtype: :class:`certbot.util.CSR`

    """
    config = zope.component.getUtility(interfaces.IConfig)

    csr_pem = acme_crypto_util.make_csr(privkey.pem,
                                        names,
                                        must_staple=config.must_staple)

    # Save CSR
    util.make_or_verify_dir(path, 0o755, config.strict_permissions)
    csr_f, csr_filename = util.unique_file(
        os.path.join(path, "csr-certbot.pem"), 0o644, "wb")
    with csr_f:
        csr_f.write(csr_pem)
    logger.debug("Creating CSR: %s", csr_filename)

    return util.CSR(csr_filename, csr_pem, "pem")
Ejemplo n.º 8
0
def generate_csr(domains, key_path, csr_path, key_type=RSA_KEY_TYPE):
    """
    Generate a private key, and a CSR for the given domains using this key.
    :param domains: the domain names to include in the CSR
    :type domains: `list` of `str`
    :param str key_path: path to the private key that will be generated
    :param str csr_path: path to the CSR that will be generated
    :param str key_type: type of the key (misc.RSA_KEY_TYPE or misc.ECDSA_KEY_TYPE)
    """
    if key_type == RSA_KEY_TYPE:
        key = crypto.PKey()
        key.generate_key(crypto.TYPE_RSA, 2048)
    elif key_type == ECDSA_KEY_TYPE:
        with warnings.catch_warnings():
            # Ignore a warning on some old versions of cryptography
            warnings.simplefilter('ignore', category=PendingDeprecationWarning)
            key = ec.generate_private_key(ec.SECP384R1(), default_backend())
        key = key.private_bytes(encoding=Encoding.PEM, format=PrivateFormat.TraditionalOpenSSL,
                                encryption_algorithm=NoEncryption())
        key = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
    else:
        raise ValueError('Invalid key type: {0}'.format(key_type))

    key_bytes = crypto.dump_privatekey(crypto.FILETYPE_PEM, key)
    with open(key_path, 'wb') as file:
        file.write(key_bytes)

    csr_bytes = crypto_util.make_csr(key_bytes, domains)
    with open(csr_path, 'wb') as file:
        file.write(csr_bytes)
Ejemplo n.º 9
0
def new_csr(domain_name, pkey_pem=None):
    """Create certificate signing request."""
    if pkey_pem is None:
        pkey = OpenSSL.crypto.PKey()
        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS)
        pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
                                                  pkey)
    csr_pem = crypto_util.make_csr(pkey_pem, [domain_name])
    return pkey_pem, csr_pem
Ejemplo n.º 10
0
def gen_csr(domain_names, pkey_pem=None):
	if pkey_pem is None:
		pkey = OpenSSL.crypto.PKey()
		pkey.generate_key(OpenSSL.crypto.TYPE_RSA, settings.LETSENCRYPT_CERT_KEY_BITS)
		pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey).decode()

	# Generate CSR based on the domains
	csr_pem = crypto_util.make_csr(pkey_pem, domain_names)
	return pkey_pem, csr_pem
Ejemplo n.º 11
0
def new_csr_comp(domain_name, pkey_pem=None):
    """Create certificate signing request."""
    if pkey_pem is None:
        # Create private key.
        pkey = OpenSSL.crypto.PKey()
        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS)
        pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
                                                  pkey)
    csr_pem = crypto_util.make_csr(pkey_pem, [domain_name])
    return pkey_pem, csr_pem
Ejemplo n.º 12
0
    def submit_order(self, key, names):
        """
        Create a new order and return the OrderResource for that order with
        all the authorizations resolved.

        It will automatically create a new private key and CSR for the
        domain 'names'.

        :param key: Key for the future certificate.
        :param list of str names: Sequence of DNS names for which to request
            a new certificate.

        :return: The new authorization resource.
        :rtype: Deferred[`~acme.messages.Order`]
        """
        # certbot helper API needs PEM.
        pem_key = key.private_bytes(
            encoding=serialization.Encoding.PEM,
            format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption(),
        )
        csr_pem = make_csr(pem_key, names)
        identifiers = [fqdn_identifier(name) for name in names]

        message = messages.NewOrder(identifiers=identifiers)
        response = yield self._client.post(self.directory.newOrder, message)
        self._expect_response(response, [http.CREATED])

        order_uri = self._maybe_location(response)

        authorizations = []
        order_body = yield response.json()
        for uri in order_body['authorizations']:
            # We do a POST-as-GET
            respose = yield self._client.post(uri, obj=None)
            self._expect_response(response, [http.CREATED])
            body = yield respose.json()
            authorizations.append(
                messages.AuthorizationResource(
                    body=messages.Authorization.from_json(body),
                    uri=uri,
                ))

        order = messages.OrderResource(
            body=messages.Order.from_json(order_body),
            uri=order_uri,
            authorizations=authorizations,
            csr_pem=csr_pem,
        )

        # TODO: Not sure if all these sanity checks are required.
        for identifier in order.body.identifiers:
            if identifier not in identifiers:
                raise errors.UnexpectedUpdate(order)
        defer.returnValue(order)
Ejemplo n.º 13
0
def new_csr_comp(domain_names, pkey_pem):
    '''Create certificate signing request.'''

    if not pkey_pem:
        pkey = OpenSSL.crypto.PKey()
        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, KEY_BITS)
        pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
                                                  pkey)

    csr_pem = crypto_util.make_csr(pkey_pem, domain_names)
    return pkey_pem, csr_pem
Ejemplo n.º 14
0
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname, tmp_chall_dict, directory_url):
    """Runs the entire process of ACME registeration"""

    client = create_v2_client(directory_url, accnt_key)

    # First we need to create a registration with the email address provided
    # and accept the terms of service
    log.info("Using boulder server %s", directory_url)

    client.net.account = client.new_account(
        messages.NewRegistration.from_data(
            terms_of_service_agreed=True
        )
    )

    # Now we need to open an order and request our certificate

    # NOTE: We'll let ACME generate a CSR for our private key as there's
    # a lot of utility code it uses to generate the CSR in a specific
    # fashion. Better to use what LE provides than to roll our own as we
    # we doing with the v1 code
    #
    # This will also let us support multi-domain certificat requests in the
    # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server
    # supports it
    csr = crypto_util.make_csr(priv_key, [hostname], False)
    order = client.new_order(csr)
    authzr = order.authorizations

    log.info('Created a new order for %s', hostname)

    # authrz is a list of Authorization resources, we need to find the
    # HTTP-01 challenge and use it
    for auth_req in authzr:  # pylint: disable=not-an-iterable
        for chall_body in auth_req.body.challenges:
            if isinstance(chall_body.chall, challenges.HTTP01):
                challb = chall_body
                break

    if challb is None:
        raise Exception("HTTP01 challenge unavailable!")

    _, chall_tok = challb.response_and_validation(client.net.key)
    v = chall_body.chall.encode("token")
    log.info('Exposing challenge on %s', v)
    tmp_chall_dict.set(v, ChallTok(chall_tok))

    cr = client.answer_challenge(challb, challb.response(client.net.key))
    log.debug('Acme CA responded to challenge request with: %s', cr)

    order = client.poll_and_finalize(order)

    return split_certificate_chain(order.fullchain_pem)
Ejemplo n.º 15
0
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname, tmp_chall_dict, directory_url):
    """Runs the entire process of ACME registeration"""

    client = create_v2_client(directory_url, accnt_key)

    # First we need to create a registration with the email address provided
    # and accept the terms of service
    log.info("Using boulder server %s", directory_url)

    client.net.account = client.new_account(
        messages.NewRegistration.from_data(
            terms_of_service_agreed=True
        )
    )

    # Now we need to open an order and request our certificate

    # NOTE: We'll let ACME generate a CSR for our private key as there's
    # a lot of utility code it uses to generate the CSR in a specific
    # fashion. Better to use what LE provides than to roll our own as we
    # we doing with the v1 code
    #
    # This will also let us support multi-domain certificat requests in the
    # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server
    # supports it
    csr = crypto_util.make_csr(priv_key, [hostname], False)
    order = client.new_order(csr)
    authzr = order.authorizations

    log.info('Created a new order for %s', hostname)

    # authrz is a list of Authorization resources, we need to find the
    # HTTP-01 challenge and use it
    for auth_req in authzr: # pylint: disable=not-an-iterable
       for chall_body in auth_req.body.challenges:
            if isinstance(chall_body.chall, challenges.HTTP01):
                challb = chall_body
                break

    if challb is None:
        raise Exception("HTTP01 challenge unavailable!")

    response, chall_tok = challb.response_and_validation(client.net.key)
    v = chall_body.chall.encode("token")
    log.info('Exposing challenge on %s', v)
    tmp_chall_dict.set(v, ChallTok(chall_tok))

    cr = client.answer_challenge(challb, challb.response(client.net.key))
    log.debug('Acme CA responded to challenge request with: %s', cr)

    order = client.poll_and_finalize(order)

    return split_certificate_chain(order.fullchain_pem)
Ejemplo n.º 16
0
def _new_csr_comp(domain_name, pkey_pem=None):
    """
    Create certificate signing request.
    Создание ключей для подписания запросов
    """
    if pkey_pem is None:
        # Create private key.
        pkey = OpenSSL.crypto.PKey()
        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, CERT_PKEY_BITS)
        pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
                                                  pkey)
    csr_pem = crypto_util.make_csr(pkey_pem, domain_name)
    return pkey_pem, csr_pem
Ejemplo n.º 17
0
def new_csr_comp(domain_name, pkey_pem=None):
    """Create certificate signing request."""
    if pkey_pem is None:
        # Create private key.
        pkey = OpenSSL.crypto.PKey()
        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
        pkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey)
        kf = open(account_key, "wb")
        kf.write(pkey_pem)
        kf.close()
    csr_pem = crypto_util.make_csr(pkey_pem, [domain_name])
    cf = open(csr, "wb")
    cf.write(csr_pem)
    cf.close()
    return pkey_pem, csr_pem, pkey
Ejemplo n.º 18
0
    def _generate_csr(self) -> bytes:
        """Load or create private key."""
        if self.path_private_key.exists():
            _LOGGER.debug("Load private keyfile: %s", self.path_private_key)
            key_pem = self.path_private_key.read_bytes()
        else:
            _LOGGER.debug("create private keyfile: %s", self.path_private_key)
            key = OpenSSL.crypto.PKey()
            key.generate_key(OpenSSL.crypto.TYPE_RSA, PRIVATE_KEY_SIZE)
            key_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)

            self.path_private_key.write_bytes(key_pem)
            self.path_private_key.chmod(0o600)

        return crypto_util.make_csr(key_pem, [self._domain])
    def handle(self, *args, **kwargs):
        try:
            d = "*." + DOMAIN
            domains = list(set([d, DOMAIN, kwargs['domain'],]))
            letsencryptkey = os.path.join(FILES_DIR, 'ssl/account.pem')
            servercertpath = os.path.join(FILES_DIR, 'ssl/server.crt')
            serverkeypath = os.path.join(FILES_DIR, 'ssl/server.key')
    
            sys.stdout.write("[+] Writting to: {}\n".format(FILES_DIR))

            self.start_verify_server(EXTERNAL_IP)
            TXTRECORDS.append("test123")
    
            client = self.create_acme_client(EMAIL)
            
            #Generate csr
            sys.stdout.write("[+] Generating server csr\t")
            serverkey = self.gen_key()
            pem = crypto.dump_privatekey(crypto.FILETYPE_PEM, serverkey)
            with open(serverkeypath, 'w') as f:
                f.write(pem.decode('utf-8'))
            csr = acme_crypto_util.make_csr(pem, domains, False)
            sys.stdout.write("OK!\n")
            
            sys.stdout.write("[+] Generating server cert\t")
            order = client.new_order(csr)
            
            for a in order.authorizations:
                c = self.get_challenge(a, challenges.DNS01)
                name, value = (c.validation_domain_name(a.body.identifier.value), c.validation(client.net.key))
                TXTRECORDS.append(value)
                client.answer_challenge(c, c.response(client.net.key))
           
            print(TXTRECORDS)
            order = client.poll_and_finalize(order)
            print(order)
            cert = crypto.load_certificate(crypto.FILETYPE_PEM, order.fullchain_pem)
            with open(servercertpath, 'w') as file:
                print("writting file")
                file.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert).decode('utf-8'))
            sys.stdout.write("OK!\n")
                
            sys.stdout.write("[+] Successfully signed certificate for '{}'\n".format(d))
            sys.stdout.write("[+] Certificate and keys can be found under {}\n".format(os.path.join(FILES_DIR, 'ssl/')))
        except acme.errors.ValidationError as e:
            raise
            sys.stdout.write("FAILED!\n")
Ejemplo n.º 20
0
    def obtain_certificate(self, domains):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: certificate as PEM string, chain as PEM string,
            newly generated private key (`.util.Key`), and DER-encoded
            Certificate Signing Request (`.util.CSR`).
        :rtype: tuple

        """
        # Create CSR from names
        if self.config.dry_run:
            key = util.Key(file=None,
                           pem=crypto_util.make_key(self.config.rsa_key_size))
            csr = util.CSR(file=None,
                           form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = crypto_util.init_save_key(self.config.rsa_key_size,
                                            self.config.key_dir)
            csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)

        orderr = self._get_order_and_authorizations(
            csr.data, self.config.allow_subset_of_names)
        authzr = orderr.authorizations
        auth_domains = set(a.body.identifier.value for a in authzr)
        successful_domains = [d for d in domains if d in auth_domains]

        # allow_subset_of_names is currently disabled for wildcard
        # certificates. The reason for this and checking allow_subset_of_names
        # below is because successful_domains == domains is never true if
        # domains contains a wildcard because the ACME spec forbids identifiers
        # in authzs from containing a wildcard character.
        if self.config.allow_subset_of_names and successful_domains != domains:
            if not self.config.dry_run:
                os.remove(key.file)
                os.remove(csr.file)
            return self.obtain_certificate(successful_domains)
        else:
            cert, chain = self.obtain_certificate_from_csr(csr, orderr)

            return cert, chain, key, csr
Ejemplo n.º 21
0
    def generate_csr(self):
        """
        Generates a new CSR using the object's `domains` and `private_key` values.\n
        - :return [`bytes`]: the encoded CSR PEM data string. This method will update the `csr` property of the object
        with the same value.\n
        - :raises `InvalidDomain`: when no valid `domains` are set.\n
        - :raises `InvalidPrivateKey`: when no `private_key` exists for this object.\n\n

        ## Example\n
        ```python
        >>> client.generate_csr()
        b'-----BEGIN CERTIFICATE REQUEST-----\\nMIHxMIGZAgECMAAwWTATBgckjkn...'
        ```
        """
        self.__validate_domains__()
        self.__validate_private_key__()
        self.csr = crypto_util.make_csr(self.private_key, self.domains)
        return self.csr
Ejemplo n.º 22
0
    def obtain_certificate(self, domains):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: certificate as PEM string, chain as PEM string,
            newly generated private key (`.util.Key`), and DER-encoded
            Certificate Signing Request (`.util.CSR`).
        :rtype: tuple

        """
        # Create CSR from names
        if self.config.dry_run:
            key = util.Key(file=None,
                           pem=crypto_util.make_key(self.config.rsa_key_size))
            csr = util.CSR(file=None,
                           form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = crypto_util.init_save_key(self.config.rsa_key_size,
                                            self.config.key_dir)
            csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)

        orderr = self.acme.new_order(csr.data)
        authzr = self.auth_handler.handle_authorizations(
            orderr, self.config.allow_subset_of_names)
        orderr = orderr.update(authorizations=authzr)
        auth_domains = set(a.body.identifier.value for a in authzr)
        successful_domains = [d for d in domains if d in auth_domains]

        if successful_domains != domains:
            if not self.config.dry_run:
                os.remove(key.file)
                os.remove(csr.file)
            return self.obtain_certificate(successful_domains)
        else:
            cert, chain = self.obtain_certificate_from_csr(csr, orderr)

            return cert, chain, key, csr
Ejemplo n.º 23
0
def generate_private_key(operation_id: int, **kwargs):
    operation = Operation.query.get(operation_id)
    service_instance = operation.service_instance

    operation.step_description = "Creating credentials for Lets Encrypt"
    flag_modified(operation, "step_description")
    db.session.add(operation)
    db.session.commit()

    if service_instance.new_certificate is not None:
        return

    certificate = Certificate()
    certificate.service_instance = service_instance
    service_instance.new_certificate = certificate
    certificate.subject_alternative_names = service_instance.domain_names

    # Create private key.
    private_key = OpenSSL.crypto.PKey()
    private_key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)

    # Get the PEM
    private_key_pem_in_binary = OpenSSL.crypto.dump_privatekey(
        OpenSSL.crypto.FILETYPE_PEM, private_key
    )

    # Get the CSR for the domains
    csr_pem_in_binary = crypto_util.make_csr(
        private_key_pem_in_binary, service_instance.domain_names
    )

    # Store them as text for later
    certificate.private_key_pem = private_key_pem_in_binary.decode("utf-8")
    certificate.csr_pem = csr_pem_in_binary.decode("utf-8")

    db.session.add(service_instance)
    db.session.add(operation)
    db.session.add(certificate)
    db.session.commit()
Ejemplo n.º 24
0
    def obtain_certificate(self, domains):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: `.CertificateResource`, certificate chain (as
            returned by `.fetch_chain`), and newly generated private key
            (`.util.Key`) and DER-encoded Certificate Signing Request
            (`.util.CSR`).
        :rtype: tuple

        """
        authzr = self.auth_handler.get_authorizations(
            domains, self.config.allow_subset_of_names)

        auth_domains = set(a.body.identifier.value for a in authzr)
        domains = [d for d in domains if d in auth_domains]

        # Create CSR from names
        if self.config.dry_run:
            key = util.Key(file=None,
                           pem=crypto_util.make_key(self.config.rsa_key_size))
            csr = util.CSR(file=None,
                           form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = crypto_util.init_save_key(self.config.rsa_key_size,
                                            self.config.key_dir)
            csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)

        certr, chain = self.obtain_certificate_from_csr(domains,
                                                        csr,
                                                        authzr=authzr)

        return certr, chain, key, csr
Ejemplo n.º 25
0
def test_blocked_key_cert():
    # Only config-next has a blocked keys file configured.
    if not CONFIG_NEXT:
        return

    with open("test/test-ca.key", "r") as f:
        pemBytes = f.read()

    domains = [random_domain(), random_domain()]
    csr = acme_crypto_util.make_csr(pemBytes, domains, False)

    client = chisel2.make_client(None)
    order = client.new_order(csr)
    authzs = order.authorizations

    testPass = False
    cleanup = chisel2.do_http_challenges(client, authzs)
    try:
        order = client.poll_and_finalize(order)
    except acme_errors.Error as e:
        # TODO(@cpu): this _should_ be type
        # urn:ietf:params:acme:error:badPublicKey but this will require
        # refactoring the `csr` package error handling.
        # See https://github.com/letsencrypt/boulder/issues/4418
        if e.typ != "urn:ietf:params:acme:error:malformed":
            raise Exception(
                "problem did not have correct error type, had {0}".format(
                    e.typ))
        if e.detail != "Error finalizing order :: invalid public key in CSR: public key is forbidden":
            raise Exception(
                "problem did not have correct error detail, had {0}".format(
                    e.detail))
        testPass = True

    if testPass is False:
        raise Exception(
            "expected cert creation to fail with Error when using blocked key")
Ejemplo n.º 26
0
    def obtain_certificate(self, domains):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: `.CertificateResource`, certificate chain (as
            returned by `.fetch_chain`), and newly generated private key
            (`.util.Key`) and DER-encoded Certificate Signing Request
            (`.util.CSR`).
        :rtype: tuple

        """
        authzr = self.auth_handler.get_authorizations(
                domains,
                self.config.allow_subset_of_names)

        auth_domains = set(a.body.identifier.value for a in authzr)
        domains = [d for d in domains if d in auth_domains]

        # Create CSR from names
        if self.config.dry_run:
            key = util.Key(file=None,
                           pem=crypto_util.make_key(self.config.rsa_key_size))
            csr = util.CSR(file=None, form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = crypto_util.init_save_key(
                self.config.rsa_key_size, self.config.key_dir)
            csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)

        certr, chain = self.obtain_certificate_from_csr(
            domains, csr, authzr=authzr)

        return certr, chain, key, csr
Ejemplo n.º 27
0
    def obtain_certificate(self, domains, old_keypath=None):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: certificate as PEM string, chain as PEM string,
            newly generated private key (`.util.Key`), and DER-encoded
            Certificate Signing Request (`.util.CSR`).
        :rtype: tuple

        """
        # We need to determine the key path, key PEM data, CSR path,
        # and CSR PEM data.  For a dry run, the paths are None because
        # they aren't permanently saved to disk.  For a lineage with
        # --reuse-key, the key path and PEM data are derived from an
        # existing file.

        if old_keypath is not None:
            # We've been asked to reuse a specific existing private key.
            # Therefore, we'll read it now and not generate a new one in
            # either case below.
            #
            # We read in bytes here because the type of `key.pem`
            # created below is also bytes.
            with open(old_keypath, "rb") as f:
                keypath = old_keypath
                keypem = f.read()
            key: Optional[util.Key] = util.Key(file=keypath, pem=keypem)
            logger.info("Reusing existing private key from %s.", old_keypath)
        else:
            # The key is set to None here but will be created below.
            key = None

        key_size = self.config.rsa_key_size
        elliptic_curve = "secp256r1"

        # key-type defaults to a list, but we are only handling 1 currently
        if isinstance(self.config.key_type, list):
            self.config.key_type = self.config.key_type[0]
        if self.config.elliptic_curve and self.config.key_type == 'ecdsa':
            elliptic_curve = self.config.elliptic_curve
            self.config.auth_chain_path = "./chain-ecdsa.pem"
            self.config.auth_cert_path = "./cert-ecdsa.pem"
            self.config.key_path = "./key-ecdsa.pem"
        elif self.config.rsa_key_size and self.config.key_type.lower(
        ) == 'rsa':
            key_size = self.config.rsa_key_size

        # Create CSR from names
        if self.config.dry_run:
            key = key or util.Key(
                file=None,
                pem=crypto_util.make_key(
                    bits=key_size,
                    elliptic_curve=elliptic_curve,
                    key_type=self.config.key_type,
                ),
            )
            csr = util.CSR(file=None,
                           form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = key or crypto_util.generate_key(
                key_size=key_size,
                key_dir=self.config.key_dir,
                key_type=self.config.key_type,
                elliptic_curve=elliptic_curve,
                strict_permissions=self.config.strict_permissions,
            )
            csr = crypto_util.generate_csr(key, domains, self.config.csr_dir,
                                           self.config.must_staple,
                                           self.config.strict_permissions)

        orderr = self._get_order_and_authorizations(
            csr.data, self.config.allow_subset_of_names)
        authzr = orderr.authorizations
        auth_domains = set(a.body.identifier.value for a in authzr)
        successful_domains = [d for d in domains if d in auth_domains]

        # allow_subset_of_names is currently disabled for wildcard
        # certificates. The reason for this and checking allow_subset_of_names
        # below is because successful_domains == domains is never true if
        # domains contains a wildcard because the ACME spec forbids identifiers
        # in authzs from containing a wildcard character.
        if self.config.allow_subset_of_names and successful_domains != domains:
            if not self.config.dry_run:
                os.remove(key.file)
                os.remove(csr.file)
            return self.obtain_certificate(successful_domains)
        else:
            cert, chain = self.obtain_certificate_from_csr(csr, orderr)
            return cert, chain, key, csr
Ejemplo n.º 28
0
def make_csr(domains):
    key = OpenSSL.crypto.PKey()
    key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
    pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
    return acme_crypto_util.make_csr(pem, domains, False)
Ejemplo n.º 29
0
def make_csr(domains):
    key = OpenSSL.crypto.PKey()
    key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
    pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
    return acme_crypto_util.make_csr(pem, domains, False)
Ejemplo n.º 30
0
    def obtain_certificate(self, domains, old_keypath=None):
        """Obtains a certificate from the ACME server.

        `.register` must be called before `.obtain_certificate`

        :param list domains: domains to get a certificate

        :returns: certificate as PEM string, chain as PEM string,
            newly generated private key (`.util.Key`), and DER-encoded
            Certificate Signing Request (`.util.CSR`).
        :rtype: tuple

        """

        # We need to determine the key path, key PEM data, CSR path,
        # and CSR PEM data.  For a dry run, the paths are None because
        # they aren't permanently saved to disk.  For a lineage with
        # --reuse-key, the key path and PEM data are derived from an
        # existing file.

        if old_keypath is not None:
            # We've been asked to reuse a specific existing private key.
            # Therefore, we'll read it now and not generate a new one in
            # either case below.
            #
            # We read in bytes here because the type of `key.pem`
            # created below is also bytes.
            with open(old_keypath, "rb") as f:
                keypath = old_keypath
                keypem = f.read()
            key = util.Key(file=keypath, pem=keypem) # type: Optional[util.Key]
            logger.info("Reusing existing private key from %s.", old_keypath)
        else:
            # The key is set to None here but will be created below.
            key = None

        # Create CSR from names
        if self.config.dry_run:
            key = key or util.Key(file=None,
                                  pem=crypto_util.make_key(self.config.rsa_key_size))
            csr = util.CSR(file=None, form="pem",
                           data=acme_crypto_util.make_csr(
                               key.pem, domains, self.config.must_staple))
        else:
            key = key or crypto_util.init_save_key(self.config.rsa_key_size,
                                                   self.config.key_dir)
            csr = crypto_util.init_save_csr(key, domains, self.config.csr_dir)

        orderr = self._get_order_and_authorizations(csr.data, self.config.allow_subset_of_names)
        authzr = orderr.authorizations
        auth_domains = set(a.body.identifier.value for a in authzr)  # pylint: disable=not-an-iterable
        successful_domains = [d for d in domains if d in auth_domains]

        # allow_subset_of_names is currently disabled for wildcard
        # certificates. The reason for this and checking allow_subset_of_names
        # below is because successful_domains == domains is never true if
        # domains contains a wildcard because the ACME spec forbids identifiers
        # in authzs from containing a wildcard character.
        if self.config.allow_subset_of_names and successful_domains != domains:
            if not self.config.dry_run:
                os.remove(key.file)
                os.remove(csr.file)
            return self.obtain_certificate(successful_domains)
        else:
            cert, chain = self.obtain_certificate_from_csr(csr, orderr)

            return cert, chain, key, csr
Ejemplo n.º 31
0
 def _call_with_key(cls, *args, **kwargs):
     privkey = OpenSSL.crypto.PKey()
     privkey.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
     privkey_pem = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, privkey)
     from acme.crypto_util import make_csr
     return make_csr(privkey_pem, *args, **kwargs)
Ejemplo n.º 32
0
def run_acme_reg_to_finish(domain, accnt_key, priv_key, hostname,
                           tmp_chall_dict, directory_url):
    '''Runs the entire process of ACME registeration'''

    client = create_v2_client(directory_url, accnt_key)

    # First we need to create a registration with the email address provided
    # and accept the terms of service
    log.info("Using boulder server %s", directory_url)

    client.net.account = client.new_account(
        messages.NewRegistration.from_data(terms_of_service_agreed=True))

    # Now we need to open an order and request our certificate

    # NOTE: We'll let ACME generate a CSR for our private key as there's
    # a lot of utility code it uses to generate the CSR in a specific
    # fashion. Better to use what LE provides than to roll our own as we
    # we doing with the v1 code
    #
    # This will also let us support multi-domain certificat requests in the
    # future, as well as mandate OCSP-Must-Staple if/when GL's HTTPS server
    # supports it
    csr = crypto_util.make_csr(priv_key, [hostname], False)
    order = client.new_order(csr)
    authzr = order.authorizations

    log.info('Created a new order for %s', hostname)

    # authrz is a list of Authorization resources, we need to find the
    # HTTP-01 challenge and use it
    for auth_req in authzr:  # pylint: disable=not-an-iterable
        for chall_body in auth_req.body.challenges:
            if isinstance(chall_body.chall, challenges.HTTP01):
                challb = chall_body
                break

    if challb is None:
        raise Exception("HTTP01 challenge unavailable!")

    response, chall_tok = challb.response_and_validation(client.net.key)
    v = chall_body.chall.encode("token")
    log.info('Exposing challenge on %s', v)
    tmp_chall_dict.set(v, ChallTok(chall_tok))

    cr = client.answer_challenge(challb, challb.response(client.net.key))
    log.debug('Acme CA responded to challenge request with: %s', cr)

    # Wrap this step and log the failure particularly here because this is
    # the expected point of failure for applications that are not reachable
    # from the public internet.
    try:
        order = client.poll_and_finalize(order)

    except messages.Error as error:
        log.err("Failed in request issuance step %s", error)
        raise

    # ACME V2 returns a full chain certificate, and ACME doesn't ship with
    # helper functions out of the box. Fortunately, searching through cerbot
    # this is easily enough to do with pyOpenSSL

    cert = load_certificate(FILETYPE_PEM, order.fullchain_pem)
    cert_str = dump_certificate(FILETYPE_PEM, cert).decode()
    chain_str = order.fullchain_pem[len(cert_str):].lstrip()

    # pylint: disable=no-member
    expr_date = convert_asn1_date(cert.get_notAfter())
    log.info('Retrieved cert using ACME that expires on %s', expr_date)

    return cert_str, chain_str
Ejemplo n.º 33
0
def wildcard_request(cn, account):
    def dns_check_ns1():
        recieved_data_dup = []
        recieved_data = []

        ns1_resolver = dns.resolver.Resolver()
        #ns1_resolver.nameservers = ['130.193.8.82','2a03:b780::1:1']
        ns1_resolver.nameservers = ['173.245.58.51']

        for data in validation_data:
            domainname = data[1]
            #challenge = data[0]
            answers = ns1_resolver.query(domainname, 'txt')
            for rdata in answers:
                recieved_data_dup.append(
                    [str(rdata).replace('"', ''), domainname])

        #Deduplication of ns records (in case of more cnames)
        for i in recieved_data_dup:
            if i not in recieved_data:
                recieved_data.append(i)

        # print sorted(recieved_data)
        # print sorted(validation_data)
        if sorted(validation_data) == sorted(recieved_data):
            return True
        else:
            return False

    #Check if CN is valid domain
    domain_regex = re.compile(
        "^([a-zA-Z0-9]([\-a-zA-Z0-9]{0,61}[a-zA-Z0-9])?\.)*([a-zA-Z0-9]([\-a-zA-Z0-9]{0,61}[a-zA-Z0-9])+\.)([a-zA-Z0-9]+([\-a-zA-Z0-9]{0,61}[a-zA-Z])+)$"
    )
    if not domain_regex.match(cn):
        print 'First argument is not valid CN'
        sys.exit(1)

    #Check if registrar exists
    if account not in os.listdir(REG_DIRECTORY):
        print "This account does not exists, register it first with new_account.py"
        sys.exit(1)

    #Load files from disk
    with open(REG_DIRECTORY + "/" + account + "/private.key",
              "rb") as key_file:
        privkey = serialization.load_pem_private_key(key_file.read(),
                                                     password=None,
                                                     backend=default_backend())
    with open(REG_DIRECTORY + "/" + account + "/reguri.txt",
              "r") as reguri_file:
        reg_uri = reguri_file.read()

    #Compose regr
    key = jose.JWKRSA(key=privkey)
    regr = messages.RegistrationResource(
        body=messages.Registration(key=key.public_key()), uri=reg_uri)

    #Init ACME
    net = ClientNetwork(key)
    directory = net.get(DIRECTORY_URL).json()

    acme = client.ClientV2(directory, net)

    #Check if registration is valid
    if acme.query_registration(regr).body.status == u'valid':
        print "Registration valid"
    else:
        print "Registration invalid"
        sys.exit(1)

    #Generate private key for certificate
    pkey = OpenSSL.crypto.PKey()
    pkey.generate_key(OpenSSL.crypto.TYPE_RSA, BITS)

    #Serialize key for output
    pkey_printable = OpenSSL.crypto.dump_privatekey(
        OpenSSL.crypto.FILETYPE_PEM, pkey, cipher=None, passphrase=None)

    #Compose request for acme
    req = crypto_util.make_csr(
        OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, pkey),
        [cn, '*.' + cn])

    #begin order
    orderr = acme.new_order(req)

    validation_data = []

    for authr in orderr.authorizations:
        for chalr in authr.body.challenges:
            if type(chalr.chall) == type(challenges.DNS01()):
                validation_data.append([
                    str(chalr.chall.validation(key)),
                    chalr.chall.validation_domain_name(cn)
                ])
    #print validation_data
    #Now, call DNS writing function to apply challenges
    dns_apply(cn, validation_data)

    #Check if DNS is valid on our server
    sys.stdin.readline()  #DEBUG: wait for manual DNS input
    limiter = 2
    while not dns_check_ns1():
        if limiter != 0:
            print "DNS records are not correct, trying again in few seconds"
            limiter = limiter - 1
            time.sleep(5)
        else:
            print "DNS are not correct even after several tries. Aborting"
            sys.exit(1)

    for authr in orderr.authorizations:
        for chalr in authr.body.challenges:
            if type(chalr.chall) == type(challenges.DNS01()):
                try:
                    acme.answer_challenge(chalr, challenges.DNS01Response())
                except:
                    print chalr.chall.encode(
                        'token'
                    ) + " already answered (challenge failed, you have to generate new one)"

    #After filling DNS and waiting for propagation, finalize order
    try:
        res = acme.poll_and_finalize(orderr)
    finally:
        dns_remove(cn)
    #logging.info(res)

    cert = x509.load_pem_x509_certificate(str(res.fullchain_pem),
                                          default_backend())

    output_data = {
        'wildcard': {
            'cn': cn,
            'private_key': str(pkey_printable),
            'certificate': str(res.fullchain_pem),
            'expiration': cert.not_valid_after.strftime(
                "%x %X"
            )  #Locale-specific time+date representation. Edit to your need
        }
    }

    print json.dumps(output_data)