def revoke_certificate(self, cert_id, delete=False): cert_db = Certificate.query.get(cert_id) order_db = Order.query.get(cert_db.order_id) if cert_db.status == 'revoked': status = "This certificate is already revoked" print(status) return False, status certificate = crypto.load_pem_certificate(cert_db.body.encode('ASCII')) print("Revoking certificate for:") for domain in crypto.get_certificate_domains(certificate): print(" {}".format(domain)) certificate = crypto.load_cert_for_revoke(cert_db.body.encode('ASCII')) try: self.client.revoke(certificate, 0) print("Certificate {} revoked.".format(cert_db.id)) order_db.status = 'revoked' cert_db.status = 'revoked' if delete: print("Deleting certificate from database") database.delete(cert_db) order_db.resolved_cert_id = None else: database.add(cert_db) database.add(order_db) status = 'Revoked' print(status) return True, status except IOError: status = "Revoke failed" print(status) return False, status
def revoke_certificate(account_id: int, cert_id: int, delete: bool = False): account = Account.query.get(account_id) cert_db = Certificate.query.get(cert_id) if cert_db: order_db = Order.query.get(cert_db.order_id) if cert_db.status == 'revoked': if delete: database.delete(cert_db) order_db.resolved_cert_id = None database.add(order_db) status = "Deleted already revoked certificate" print(status) return True, status status = "This certificate is already revoked" print(status) return False, status if order_db.account_id != account_id: status = "This certificate does not belong to this account" print(status) return False, status acme = AcmeDnsHandler(account.id) return acme.revoke_certificate(cert_id, delete) else: status = "Certificate with id: {} does not exist".format(cert_id) print(status) return False, status
def setUp(self): self.app = create_app(config_name="testing") self.client = self.app.test_client with self.app.app_context(): db.create_all() user = users.User('admin', 'admin', True) database.add(user)
def init(pwd='changeme'): """Creates the db tables and admin user""" db.create_all() if users.User.query.filter_by(username='******').first() is not None: print("Admin user already exists") else: if not pwd: pwd = input("Enter password for admin user: ") user = users.User('admin', pwd, True) database.add(user)
def setup_acme_account(self, user_id, email=None, server=None, rsa_key=None, organization: str = None, organizational_unit: str = None, country: str = None, state: str = None, location: str = None): if not email: email = config.CERTIFIRE_EMAIL if not server: server = config.LETS_ENCRYPT_PRODUCTION if not rsa_key: rsa_key = crypto.generate_rsa_key() account = Account(user_id, email, server, organization=organization, organizational_unit=organizational_unit, country=country, state=state, location=location) key = jose.JWKRSA(key=rsa_key) net = ClientNetwork(key, account=None, timeout=3600) client = BackwardsCompatibleClientV2(net, key, account.directory_uri) registration = client.new_account_and_tos( messages.NewRegistration.from_data(email=email)) account.key = crypto.export_private_key(rsa_key).decode("utf-8") account.uri = registration.uri account.contents = json.dumps(registration.to_json()) database.add(account) self.account = account self.key = key self.client = client return account
def issue_certificate(self, final_order, order_id, destination_id=None): order_db = Order.query.get(order_id) cert_db = Certificate(user_id=order_db.user_id, order_id=order_db.id, status='pending', csr=order_db.csr, private_key=order_db.key) database.add(cert_db) pem_certificate, pem_chain = crypto.extract_cert_and_chain( final_order.fullchain_pem) certificate = crypto.load_pem_certificate(pem_certificate.encode()) chain = crypto.load_pem_certificate(pem_chain.encode()) cert_db.body = crypto.export_pem_certificate(certificate).decode( 'UTF-8') cert_db.chain = crypto.export_pem_certificate(certificate).decode( 'UTF-8') cert_db.chain += crypto.export_pem_certificate(chain).decode('UTF-8') cert_db.intermediate = crypto.export_pem_certificate(chain).decode( 'UTF-8') cert_db.expiry = certificate.not_valid_after.strftime( config.EXPIRATION_FORMAT) cert_db.fingerprint = binascii.hexlify( certificate.fingerprint(crypto.hashes.SHA256())).decode('ascii') print("Expires: {}".format(cert_db.expiry)) print("SHA256: {}".format(cert_db.fingerprint)) order_db.status = 'valid' cert_db.status = 'valid' order_db.resolved_cert_id = cert_db.id print("Resolved certificate id: {}".format(order_db.resolved_cert_id)) if destination_id: destination_db = Destination.query.get(destination_id) if destination_db.certDestinationPath: destination_db.upload(cert_db.body, cert_db.private_key, cert_db.intermediate) database.add(order_db) database.add(cert_db) return cert_db.id
def create_order(self, csr_pem, provider, order_id, destination_id, reissue=False): order_db = Order.query.get(order_id) destination_db = Destination.query.get(destination_id) if order_db.status == 'revoked' and not reissue: print("Cannot issue for order with revoked certificate {}".format( order_db.resolved_cert_id)) return order_db.resolved_cert_id if order_db.status == 'valid' and reissue: print("Revoking existing certificate {}".format( order_db.resolved_cert_id)) self.revoke_certificate(order_db.resolved_cert_id) order = self.client.new_order(csr_pem) pending_challenges = self.get_pending_challenges(order, 'http-01') if not pending_challenges: if reissue: deadline = datetime.datetime.now() + datetime.timedelta( seconds=10) final_order = self.client.poll_and_finalize(order, deadline) order_db.contents = json.dumps(final_order.to_json()) order_db.status = 'ready' database.add(order_db) cert_id = self.issue_certificate(final_order, order_id, destination_id) return cert_id print("No pending challenges, reusing existing order") orderr = self.get_orderResource(order_id) if orderr.fullchain_pem is not None: if order_db.resolved_cert_id: print("Certificate already issued") return order_db.resolved_cert_id else: print("Generating Certificate") return self.issue_certificate(orderr, order_id, destination_id) else: print("Reissuing certificate") order_db.uri = order.uri order_db.contents = json.dumps(order.to_json()) database.add(order_db) destination_db = Destination.query.get(destination_id) print("Writing TXT Records") for domain, challenge in pending_challenges.items(): chall_path = challenge.chall.path response, validation = challenge.response_and_validation(self.key) destination_db.upload_acme_token(chall_path, validation) time.sleep(5) for domain, challenge in pending_challenges.items(): response = challenge.response(self.key) verified = response.simple_verify(challenge.chall, domain, self.key.public_key()) if not verified: print("{} not verified".format(domain)) #res = self.client.answer_challenge(challenge, response) time.sleep(5) print("Ansering challenge {} with response {}".format( challenge.validation(self.key), response.key_authorization)) res = self.client.answer_challenge(challenge, response) print("Got response: {}".format(res.body.status.name)) print("Finalizing order") deadline = datetime.datetime.now() + datetime.timedelta( seconds=10 * len(pending_challenges)) #final_order = self.client.finalize_order(order, deadline) final_order = self.client.poll_and_finalize(order, deadline) order_db.contents = json.dumps(final_order.to_json()) order_db.status = 'ready' database.add(order_db) print("Deleting TXT Records") for domain, challenge in pending_challenges.items(): chall_path = challenge.chall.path destination_db.delete_acme_token(chall_path) cert_id = self.issue_certificate(final_order, order_id, destination_id) return cert_id
def create_order(account_id: int, destination_id: int = None, domains: list = None, type: str = None, provider: str = None, email: str = None, organization: str = None, organizational_unit: str = None, country: str = None, state: str = None, location: str = None, reissue: bool = False, csr: str = None, key: str = None): account = Account.query.get(account_id) if not account: print("Account {} not found".format(account_id)) return False, 0 type = type if type else config.DEFAULT_AUTH_TYPE provider = provider if provider else config.DEFAULT_DNS email = email if email else account.email organization = organization if organization else account.organization organizational_unit = organizational_unit if organizational_unit else account.organizational_unit country = country if country else account.country state = state if state else account.state location = location if location else account.location if type == 'dns': if provider not in config.VALID_DNS_PROVIDERS: print("Invalid DNS Provider") return False, 0 acme = AcmeDnsHandler(account.id) if type == 'sftp': acme = AcmeHttpHandler(account.id) if not domains: if not destination_id: print("No domains or destinations provided") return False, 0 destination_db = Destination.query.get(destination_id) domains = [destination_db.host] else: if destination_id: destination_db = Destination.query.get(destination_id) if destination_db.host not in domains: domains = [destination_db.host] + domains domains_hash = hashlib.sha256( "_".join(domains).encode("ascii")).hexdigest() check = database.get_all(Order, domains_hash, 'hash') for order in check: if order.email == email and order.type == type and order.account_id == account.id: print("Order {} exists for given email: {} and account_id: {}.".format( order.uri, email, account.id)) #acme_order = acme.create_order(order.csr, order.provider, order.id) AppContextThread(target=acme.create_order, args=( order.csr, order.provider, order.id, destination_id, reissue)).start() return False, order.id if not csr or key: csr, key = acme.generate_csr( domains, email, organization, organizational_unit, country, state, location) order = Order(destination_id, domains, type, provider, account.id, account.user_id, domains_hash, csr, key, email, organization, organizational_unit, country, state, location) database.add(order) #acme_order = acme.create_order(csr, provider, order.id) AppContextThread(target=acme.create_order, args=( csr, provider, order.id, destination_id)).start() return True, order.id