def _create_client(self) -> None: """Create new ACME client.""" if self.path_registration_info.exists(): _LOGGER.info("Load exists ACME registration") regr = messages.RegistrationResource.json_loads( self.path_registration_info.read_text()) acme_url = urllib.parse.urlparse(self._acme_server) regr_url = urllib.parse.urlparse(regr.uri) if acme_url[0] != regr_url[0] or acme_url[1] != regr_url[1]: _LOGGER.info("Reset new ACME registration") self.path_registration_info.unlink() self.path_account_key.unlink() # Make sure that account key is loaded self._load_account_key() # Load a exists registration if self.path_registration_info.exists(): try: network = client.ClientNetwork(self._account_jwk, account=regr, user_agent=USER_AGENT) directory = messages.Directory.from_json( network.get(self._acme_server).json()) self._acme_client = client.ClientV2(directory, net=network) except errors.Error as err: _LOGGER.error("Can't connect to ACME server: %s", err) raise AcmeClientError() return # Create a new registration try: network = client.ClientNetwork(self._account_jwk, user_agent=USER_AGENT) directory = messages.Directory.from_json( network.get(self._acme_server).json()) self._acme_client = client.ClientV2(directory, net=network) except errors.Error as err: _LOGGER.error("Can't connect to ACME server: %s", err) raise AcmeClientError() try: _LOGGER.info( "Register a ACME account with TOS: %s", self._acme_client.directory.meta.terms_of_service, ) regr = self._acme_client.new_account( messages.NewRegistration.from_data( email=self._email, terms_of_service_agreed=True)) except errors.Error as err: _LOGGER.error("Can't register to ACME server: %s", err) raise AcmeClientError() # Store registration info self.path_registration_info.write_text(regr.json_dumps_pretty()) self.path_registration_info.chmod(0o600)
def test_revoke_by_privkey(): client = chisel2.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 = chisel2.make_csr(domains) order = client.new_order(csr_pem) cleanup = chisel2.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 = josepy.JWKRSA(key=key) net = acme_client.ClientNetwork(key, user_agent="Boulder integration tester") directory = Directory.from_json(net.get(chisel2.DIRECTORY_V2).json()) new_client = acme_client.ClientV2(directory, net) cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, order.fullchain_pem) client.revoke(josepy.ComparableX509(cert), 0)
def main(): if sys.argv[1] == 'staging': directory = 'https://acme-staging.api.letsencrypt.org/directory' else: directory = 'https://acme-v01.api.letsencrypt.org/directory' key = josepy.JWKRSA(key=serialization.load_pem_private_key( sys.stdin.read(), password=None, backend=default_backend()) ) net = acme_client.ClientNetwork(key) client = acme_client.Client( directory=directory, key=key, net=net ) new_reg = messages.NewRegistration.from_data( email=sys.argv[2] ) acct = None try: regr = client.register(new_reg) except errors.ConflictError as e: acct = e.location print(json.dumps({'body': {}, 'uri': acct}))
def generateCertificate(domain, notification_email, directory_url=DIRECTORY_URL_PROD, cert_dir=None, debug=None): # Create account key acc_key = jose.JWKRSA( key=rsa.generate_private_key(public_exponent=65537, key_size=ACC_KEY_BITS, backend=default_backend())) # Create client configured to use our ACME server and trust our root cert net = client.ClientNetwork(acc_key, user_agent=USER_AGENT) if debug == True: directory_url = DIRECTORY_URL_STAGING directory = messages.Directory.from_json(net.get(directory_url).json()) client_acme = client.ClientV2(directory, net=net) # Register account and accept TOS regr = client_acme.new_account( messages.NewRegistration.from_data(email=notification_email, terms_of_service_agreed=True)) # Create domain private key and CSR pkey_pem, csr_pem = new_csr(domain) # Issue certificate orderr = client_acme.new_order(csr_pem) # Select HTTP-01 within offered challenges by the CA server challb = select_http01_chall(orderr) # The certificate is ready to be used in the variable "fullchain_pem". fullchain_pem = perform_http01(client_acme, challb, orderr) # Store the certificates if cert_dir is None: cert_dir = CERT_DIR cert_domain_dir = "{}/{}".format(cert_dir, domain) if not os.path.exists(cert_domain_dir): os.makedirs(cert_domain_dir) key_file = "{}/dsiprouter.key".format(cert_domain_dir) cert_file = "{}/dsiprouter.crt".format(cert_domain_dir) with os.fdopen(os.open(key_file, os.O_WRONLY | os.O_CREAT, 0o640), 'w') as keyfile: keyfile.write(pkey_pem.decode('utf-8')) with os.fdopen(os.open(cert_file, os.O_WRONLY | os.O_CREAT, 0o640), 'w') as certfile: certfile.write(fullchain_pem) # Change owner to root:kamailio so that Kamailio can load the configurations change_owner(cert_domain_dir, "root", "kamailio") change_owner(key_file, "root", "kamailio") change_owner(cert_file, "root", "kamailio") return pkey_pem.decode('utf-8'), fullchain_pem
def load_account(json_data): """ Loads an existing account from a JSON data string created by the `export_account()` method.\n - :param `json_data` [`str`]: the JSON account data string.\n - :return [`ACMEClient`]: the loaded ACMEClient object.\n\n ## Example\n ```python >>> client = simple_acme_dns.ACMEClient.load_account('{"account": {"body": {"key": {"n": "vtByzpW..."}}}}') ``` """ acct_data = json.loads(json_data) obj = ACMEClient() # Format the serialized data back into the object obj.directory = acct_data.get('directory', None) obj.domains = acct_data.get('domains', []) obj.certificate = acct_data.get('certificate', '').encode() obj.private_key = acct_data.get('private_key', '').encode() obj.email = acct_data['account']['body']['contact'][0].replace('mailto:', '') obj.account = messages.RegistrationResource.json_loads(json.dumps(acct_data['account'])) obj.account_key = jose.JWKRSA.json_loads(acct_data['account_key']) # Re-initialize the ACME client and registration obj.__net__ = client.ClientNetwork(obj.account_key, user_agent='simple_acme_dns/1.0.0') obj.__directory__ = messages.Directory.from_json(obj.__net__.get(obj.directory).json()) obj.__client__ = client.ClientV2(obj.__directory__, net=obj.__net__) obj.account = obj.__client__.query_registration(obj.account) return obj
def create_user(operation_id: int, **kwargs): db = kwargs["db"] acme_user = ACMEUser() operation = Operation.query.get(operation_id) service_instance = operation.service_instance service_instance.acme_user = acme_user key = josepy.JWKRSA( key=rsa.generate_private_key( public_exponent=65537, key_size=2048, backend=default_backend() ) ) private_key_pem_in_binary = key.key.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.TraditionalOpenSSL, encryption_algorithm=serialization.NoEncryption(), ) acme_user.private_key_pem = private_key_pem_in_binary.decode("utf-8") net = client.ClientNetwork(key, user_agent="cloud.gov external domain broker") directory = messages.Directory.from_json(net.get(config.ACME_DIRECTORY).json()) client_acme = client.ClientV2(directory, net=net) acme_user.email = "*****@*****.**" registration = client_acme.new_account( messages.NewRegistration.from_data( email=acme_user.email, terms_of_service_agreed=True ) ) acme_user.registration_json = registration.json_dumps() acme_user.uri = registration.uri db.session.add(operation) db.session.add(service_instance) db.session.add(acme_user) db.session.commit()
def acme_from_config_key(config, key): "Wrangle ACME client construction" # TODO: Allow for other alg types besides RS256 net = acme_client.ClientNetwork(key, verify_ssl=(not config.no_verify_ssl), user_agent=_determine_user_agent(config)) return acme_client.Client(config.server, key=key, net=net)
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_order_and_request_issuance(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, acme_version=2, user_agent="Boulder integration tester") new_client = acme_client.Client(os.getenv( 'DIRECTORY', 'http://localhost:4001/directory'), key=jwk, net=net, acme_version=2) cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, order.fullchain_pem) client.revoke(jose.ComparableX509(cert), 0)
def test_revoke_by_privkey(): client = chisel2.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 = chisel2.make_csr(domains) order = client.new_order(csr_pem) cleanup = chisel2.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 = josepy.JWKRSA(key=key) net = acme_client.ClientNetwork(key, user_agent="Boulder integration tester") directory = Directory.from_json(net.get(chisel2.DIRECTORY_V2).json()) new_client = acme_client.ClientV2(directory, net) cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, order.fullchain_pem) reset_akamai_purges() client.revoke(josepy.ComparableX509(cert), 0) cert_file_pem = os.path.join(tempdir, "revokeme.pem") with open(cert_file_pem, "w") as f: f.write( OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert).decode()) ee_ocsp_url = "http://localhost:4002" verify_ocsp(cert_file_pem, "test/test-ca2.pem", ee_ocsp_url, "revoked") verify_akamai_purge()
def answer_challenges(operation_id: int, **kwargs): db = kwargs["db"] operation = Operation.query.get(operation_id) service_instance = operation.service_instance acme_user = service_instance.acme_user time.sleep(int(config.DNS_PROPAGATION_SLEEP_TIME)) account_key = serialization.load_pem_private_key( acme_user.private_key_pem.encode(), password=None, backend=default_backend() ) wrapped_account_key = josepy.JWKRSA(key=account_key) registration = json.loads(acme_user.registration_json) net = client.ClientNetwork( wrapped_account_key, user_agent="cloud.gov external domain broker", account=registration, ) directory = messages.Directory.from_json(net.get(config.ACME_DIRECTORY).json()) client_acme = client.ClientV2(directory, net=net) for challenge in service_instance.challenges: challenge_body = messages.ChallengeBody.from_json( json.loads(challenge.body_json) ) challenge_response = challenge_body.response(wrapped_account_key) # Let the CA server know that we are ready for the challenge. client_acme.answer_challenge(challenge_body, challenge_response) challenge.answered = True db.session.add(challenge) db.session.commit()
def new_account(self): """ Registers a new ACME account at the set ACME `directory` URL. By running this method, you are agreeing to the ACME servers terms of use.\n - :return [`none`]: the account and account_key properties will be updated with the new account registration.\n - :raises `InvalidDirectory`: if this object does not contain a valid ACME directory URL.\n - :raises `InvalidEmail`: if this object does not contain a valid email address to use during registration.\n\n ## Example\n ```python >>> client.new_account() ``` """ self.__validate_directory__() self.__validate_email__() # Generate a new RSA2048 account key rsa_key = rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=(default_backend())) self.account_key = jose.JWKRSA(key=rsa_key) # Initialize our ACME client object self.__net__ = client.ClientNetwork(self.account_key, user_agent='simple_acme_dns/1.0.0') self.__directory__ = messages.Directory.from_json(self.__net__.get(self.directory).json()) self.__client__ = client.ClientV2(self.__directory__, net=self.__net__) # Complete registration registration = messages.NewRegistration.from_data(email=self.email, terms_of_service_agreed=True) self.account = self.__client__.new_account(registration)
def uninitialized_client(key=None): if key is None: key = josepy.JWKRSA( key=rsa.generate_private_key(65537, 2048, default_backend())) net = acme_client.ClientNetwork(key, user_agent="Boulder integration tester") directory = messages.Directory.from_json(net.get(DIRECTORY_V2).json()) return acme_client.ClientV2(directory, net)
def acme_from_config_key(config, key, regr=None): "Wrangle ACME client construction" # TODO: Allow for other alg types besides RS256 net = acme_client.ClientNetwork(key, account=regr, verify_ssl=(not config.no_verify_ssl), user_agent=determine_user_agent(config)) return acme_client.BackwardsCompatibleClientV2(net, key, config.server)
def create_v2_client(directory_url, accnt_key): """Creates an ACME v2 Client for making requests to Let's Encrypt with""" accnt_key = josepy.JWKRSA(key=accnt_key) net = client.ClientNetwork(accnt_key, user_agent="GlobaLeaks Let's Encrypt Client") directory = messages.Directory.from_json(net.get(directory_url).json()) return client.ClientV2(directory, net)
def create_acme_client(self, email=None): key = josepy.JWKRSA(key=rsa.generate_private_key(65537, 2048, default_backend())) net = acme_client.ClientNetwork(key, user_agent="Callback Catcher Client") directory = messages.Directory.from_json(net.get(LETSENCRYPTDIRECTORY).json()) client = acme_client.ClientV2(directory, net) tos = client.directory.meta.terms_of_service client.net.account = client.new_account(messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) return client
def answer_challenges(operation_id: int, **kwargs): operation = Operation.query.get(operation_id) service_instance = operation.service_instance acme_user = service_instance.acme_user operation.step_description = "Answering Lets Encrypt challenges" flag_modified(operation, "step_description") db.session.add(operation) db.session.commit() challenges = service_instance.new_certificate.challenges.all() unanswered = [challenge for challenge in challenges if not challenge.answered] if not unanswered: return time.sleep(int(config.DNS_PROPAGATION_SLEEP_TIME)) account_key = serialization.load_pem_private_key( acme_user.private_key_pem.encode(), password=None, backend=default_backend() ) wrapped_account_key = josepy.JWKRSA(key=account_key) registration = json.loads(acme_user.registration_json) net = client.ClientNetwork( wrapped_account_key, user_agent="cloud.gov external domain broker", account=registration, ) directory = messages.Directory.from_json(net.get(config.ACME_DIRECTORY).json()) client_acme = AcmeClient(directory, net=net) for challenge in unanswered: if json.loads(challenge.body_json)["status"] == "valid": # this covers an edge case where we run an update # shortly after initial provisioning or renewal # it arguably makes more sense to do when we get the challenges # but doing so makes testing worlds harder challenge.answered = True db.session.add(challenge) db.session.commit() continue challenge_body = messages.ChallengeBody.from_json( json.loads(challenge.body_json) ) challenge_response = challenge_body.response(wrapped_account_key) # Let the CA server know that we are ready for the challenge. response = client_acme.answer_challenge(challenge_body, challenge_response) print(response) if response.body.error is not None: # log the error for now. We haven't reproduced this locally, so we can't act on it yet # but it would be interesting in the real world logger.error( f"challenge for instance {service_instance.id} errored. Error: {response.body.error}" ) challenge.answered = True db.session.add(challenge) db.session.commit()
def _create_acme_client(self) -> acme_client.ClientV2: net = acme_client.ClientNetwork(key=josepy.JWKRSA( key=rsa.generate_private_key( public_exponent=ACME_RSA_PUBLIC_EXPONENT, key_size=ACME_RSA_KEY_SIZE, backend=default_backend(), ))) directory = acme_messages.Directory.from_json( net.get(self.options.acme_directory_url).json()) return acme_client.ClientV2(directory=directory, net=net)
def make_client(email=None): """Build an acme.Client and register a new account with a random key.""" key = josepy.JWKRSA(key=rsa.generate_private_key(65537, 2048, default_backend())) net = acme_client.ClientNetwork(key, user_agent="Boulder integration tester") client = acme_client.Client(DIRECTORY, key=key, net=net) account = client.register(messages.NewRegistration.from_data(email=email)) client.agree_to_tos(account) client.account = account return client
def _get_acme_client(jkey, regr=None, directory_url=DIRECTORY_URL): net = client.ClientNetwork(key=jkey, account=regr, verify_ssl=TLS_VERIFY) try: directory = messages.Directory.from_json( net.get(directory_url).json()) except (errors.Error, ValueError) as dir_error: raise ACMEError('Unable to fetch directory URLs') from dir_error return ACMEClient(directory, net)
def enroll(self, csr): """ enroll certificate """ self.logger.debug('CAhandler.enroll()') csr_pem = '-----BEGIN CERTIFICATE REQUEST-----\n{0}\n-----END CERTIFICATE REQUEST-----\n'.format(textwrap.fill(str(b64_url_recode(self.logger, csr)), 64)) cert_bundle = None error = None cert_raw = None poll_indentifier = None key = None try: self.logger.debug('CAhandler.enroll() opening key') with open(self.keyfile, "r") as keyf: key = josepy.JWKRSA.json_loads(keyf.read()) net = client.ClientNetwork(key) directory = messages.Directory.from_json(net.get(self.url).json()) acmeclient = client.ClientV2(directory, net=net) reg = messages.Registration.from_data(key=key, terms_of_service_agreed=True) regr = messages.RegistrationResource(uri="{}/account/{}".format(self.url, self.account), body=reg) self.logger.debug('CAhandler.enroll() checking remote registration status') regr = acmeclient.query_registration(regr) if regr.body.status != "valid": raise Exception("Bad ACME account: " + str(regr.body.error)) self.logger.debug('CAhandler.enroll() issuing signing order') self.logger.debug('CAhandler.enroll() CSR: ' + str(csr_pem)) order = acmeclient.new_order(csr_pem) self.logger.debug('CAhandler.enroll() polling for certificate') order = acmeclient.poll_and_finalize(order) if not order.fullchain_pem: raise Exception("Error getting certificate: " + str(order.error)) self.logger.debug('CAhandler.enroll() successful') cert_bundle = str(order.fullchain_pem) cert_raw = str(base64.b64encode(crypto.dump_certificate(crypto.FILETYPE_ASN1, crypto.load_certificate(crypto.FILETYPE_PEM, cert_bundle))), 'utf-8') except Exception as e: self.logger.error(str(e)) error = str(e) finally: del key self.logger.debug('Certificate.enroll() ended') return(error, cert_bundle, cert_raw, poll_indentifier)
def initiate_challenges(operation_id: int, **kwargs): operation = Operation.query.get(operation_id) service_instance = operation.service_instance acme_user = service_instance.acme_user certificate = service_instance.new_certificate operation.step_description = "Initiating Lets Encrypt challenges" flag_modified(operation, "step_description") db.session.add(operation) db.session.commit() if certificate.order_json is not None: return account_key = serialization.load_pem_private_key( acme_user.private_key_pem.encode(), password=None, backend=default_backend() ) wrapped_account_key = josepy.JWKRSA(key=account_key) registration = json.loads(acme_user.registration_json) net = client.ClientNetwork( wrapped_account_key, user_agent="cloud.gov external domain broker", account=registration, ) directory = messages.Directory.from_json(net.get(config.ACME_DIRECTORY).json()) client_acme = AcmeClient(directory, net=net) order = client_acme.new_order(certificate.csr_pem.encode()) order_json = json.dumps(order.to_json()) certificate.order_json = json.dumps(order.to_json()) for domain in service_instance.domain_names: challenge_body = dns_challenge(order, domain) ( challenge_response, challenge_validation_contents, ) = challenge_body.response_and_validation(wrapped_account_key) challenge = Challenge() challenge.body_json = challenge_body.json_dumps() challenge.domain = domain challenge.certificate = certificate challenge.validation_domain = challenge_body.validation_domain_name(domain) challenge.validation_contents = challenge_validation_contents db.session.add(challenge) db.session.commit()
def make_client(email=None): """Build an acme.Client and register a new account with a random key.""" key = josepy.JWKRSA(key=rsa.generate_private_key(65537, 2048, default_backend())) net = acme_client.ClientNetwork(key, acme_version=2, user_agent="Boulder integration tester") client = acme_client.Client(DIRECTORY, key=key, net=net, acme_version=2) tos = client.directory.meta.terms_of_service if tos == ACCEPTABLE_TOS: net.account = client.register(messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) else: raise Exception("Unrecognized terms of service URL %s" % tos) return client
def createAccount(user, dir_url, email): acc_key = jose.JWKRSA(key=rsa.generate_private_key(public_exponent=65537, key_size=2048, backend=default_backend()) ) # Register account and accept TOS net = client.ClientNetwork(acc_key, user_agent=user) directory = messages.Directory.from_json(net.get(dir_url).json()) client_acme = client.ClientV2(directory, net=net) #Terms of Service URL is in client_acme.directory.meta.terms_of_service # Registration Resource: regr # Creates account with contact information. email = (email) regr = client_acme.new_account(messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) return client_acme
def __init__(self, configuration, test=False): if test: self.key = None else: with open(configuration.cm_key, "r") as key_file: private_key = serialization.load_pem_private_key( key_file.read(), password=None, backend=default_backend() ) self.key = jose.JWKRSA(key=private_key) user_agent = 'bigacme (https://github.com/magnuswatn/bigacme/)' network = client.ClientNetwork(self.key, user_agent=user_agent) network.session.proxies = {'https': configuration.ca_proxy} acme_client = client.Client(directory=configuration.ca, key=self.key, net=network) self.client = acme_client
def get_client(): global __cached_client_acme if __cached_client_acme: return __cached_client_acme account_pkey = loadFile("le/account.pem") account_data = None if account_pkey: account_data = loadFile("le/account.json") acc_key_pkey = None if account_pkey: acc_key_pkey = serialization.load_pem_private_key( data=account_pkey, password=None, backend=default_backend()) else: acc_key_pkey = rsa.generate_private_key(public_exponent=65537, key_size=KEY_BITS, backend=default_backend()) account_pkey = acc_key_pkey.private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption()) acc_key = jose.JWKRSA(key=acc_key_pkey) net = client.ClientNetwork(acc_key, user_agent=USER_AGENT) directory = messages.Directory.from_json(net.get(DIRECTORY_URL).json()) client_acme = client.ClientV2(directory, net=net) if account_data != None: client_acme.net.account = messages.RegistrationResource.json_loads( account_data) try: if not client_acme.net.account: email = ('*****@*****.**') regr = client_acme.new_account( messages.NewRegistration.from_data( email=email, terms_of_service_agreed=True)) storeFile("le/account.json", regr.json_dumps().encode()) storeFile("le/account.pem", account_pkey) except errors.ConflictError: raise # TODO: Maybe handle? This happens when an account has been made with a key already __cached_client_acme = client_acme return client_acme
def make_client(email=None): """Build an acme.Client and register a new account with a random key.""" key = jose.JWKRSA( key=rsa.generate_private_key(65537, 2048, default_backend())) net = acme_client.ClientNetwork(key, verify_ssl=False, user_agent="Boulder integration tester") client = acme_client.Client(DIRECTORY, key=key, net=net) tos = client.directory.meta.terms_of_service if tos is not None and "Do%20what%20thou%20wilt" in tos: net.account = client.register( messages.NewRegistration.from_data(email=email, terms_of_service_agreed=True)) else: raise Exception("Unrecognized terms of service URL %s" % tos) return client
def revoke(self, _cert, _rev_reason, _rev_date): """ revoke certificate """ self.logger.debug('CAhandler.revoke()') certpem = '-----BEGIN CERTIFICATE-----\n{0}\n-----END CERTIFICATE-----\n'.format(textwrap.fill(str(b64_url_recode(self.logger, _cert)), 64)) cert = josepy.ComparableX509(crypto.load_certificate(crypto.FILETYPE_PEM, certpem)) code = 200 message = None detail = None try: self.logger.debug('CAhandler.revoke() opening key') with open(self.keyfile, "r") as keyf: key = josepy.JWKRSA.json_loads(keyf.read()) net = client.ClientNetwork(key) directory = messages.Directory.from_json(net.get(self.url).json()) acmeclient = client.ClientV2(directory, net=net) reg = messages.Registration.from_data(key=key, terms_of_service_agreed=True) regr = messages.RegistrationResource(uri="{}/account/{}".format(self.url, self.account), body=reg) self.logger.debug('CAhandler.revoke() checking remote registration status') regr = acmeclient.query_registration(regr) if regr.body.status != "valid": raise Exception("Bad ACME account: " + str(regr.body.error)) self.logger.debug('CAhandler.revoke() issuing revocation order') acmeclient.revoke(cert, 1) self.logger.debug('CAhandler.revoke() successfull') except Exception as e: self.logger.error(str(e)) code = 500 message = 'urn:ietf:params:acme:error:serverInternal' detail = str(e) finally: del key self.logger.debug('Certificate.revoke() ended') return(code, message, detail)
def acme_from_config_key(config, key, regr=None): "Wrangle ACME client construction" # TODO: Allow for other alg types besides RS256 net = acme_client.ClientNetwork(key, account=regr, verify_ssl=(not config.no_verify_ssl), user_agent=determine_user_agent(config)) with warnings.catch_warnings(): warnings.simplefilter("ignore", DeprecationWarning) client = acme_client.BackwardsCompatibleClientV2( net, key, config.server) if client.acme_version == 1: logger.warning( "Certbot is configured to use an ACMEv1 server (%s). ACMEv1 support is deprecated" " and will soon be removed. See https://community.letsencrypt.org/t/143839 for " "more information.", config.server) return client
def get_acme_client(conf, domain_conf): """ ACME Client """ account_key = load_letsencrypt_account_key(conf, domain_conf['account_uri']) a_key = jose.JWKRSA(key=account_key) net = client.ClientNetwork(a_key) directory_acme = messages.Directory.from_json( net.get(domain_conf['directory']).json()) client_acme = client.ClientV2(directory_acme, net) if not domain_conf['account_uri']: LOG.debug("Registering with ACME server with the new account key") new_reg = messages.NewRegistration.from_data( email=(', '.join(domain_conf['contact'])), terms_of_service_agreed=True) registration_resource = client_acme.new_account(new_reg) domain_conf['account_uri'] = registration_resource.uri LOG.debug("Write Account URI '%s' into Config file ", domain_conf['account_uri']) new_domain_conf = yaml.dump(domain_conf, default_flow_style=False) save_to_s3(conf, conf['config_file'], new_domain_conf) else: registration = messages.Registration(key=a_key, contact=tuple( domain_conf['contact'])) registration_resource = messages.RegistrationResource( body=registration, uri=domain_conf['account_uri']) LOG.debug( "Update the regristration: {0}".format(registration_resource)) registration_resource = client_acme.query_registration( registration_resource) net.account = registration_resource return client_acme
def account(): # Store account information in an JWKRSA formated json file reg_file = settings.LETSENCRYPT_STATE_FOLDER + '/regr.json' key_file = settings.LETSENCRYPT_STATE_FOLDER + '/private_key.json' try: # Read existing account data and private key with open(reg_file, 'r') as f: regr = messages.RegistrationResource.json_loads(f.read()) with open(key_file, 'r') as f: key = jose.JWK.json_loads(f.read()) except IOError as error: # Generate new private key, as we expect that the account doesn't exist private_key = rsa.generate_private_key( public_exponent = 65537, key_size = settings.LETSENCRYPT_ACCT_KEY_BITS, backend = default_backend() ) key = jose.JWKRSA(key=private_key) # Prepare ACME client connection with account private key net = client.ClientNetwork(key) directory = messages.Directory.from_json( net.get(settings.LETSENCRYPT_ACME_SERVER).json() ) client_acme = client.ClientV2(directory, net=net) # Generate a new account and store account information locally email = getattr(settings, 'KUMQUAT_EMAIL', None) regr = client_acme.new_account( messages.NewRegistration.from_data( email = email, terms_of_service_agreed = True ) ) # Store private key as json format with open(key_file, 'w') as f: f.write(key.json_dumps()) # Store regr information as json format with open(reg_file, 'w') as f: f.write(regr.json_dumps()) return key, regr