def verify_cert_chain(certs, error_class=ValidationError): """ Verifies that the certificates in the chain are correct. We don't bother with full cert validation but just check that certs in the chain are signed by the next, to avoid basic human errors -- such as pasting the wrong certificate. :param certs: List of parsed certificates, use parse_cert_chain() :param error_class: Exception class to raise on error """ cert = certs[0] for issuer in certs[1:]: # Use the current cert's public key to verify the previous signature. # "certificate validation is a complex problem that involves much more than just signature checks" try: check_cert_signature(cert, issuer.public_key()) except InvalidSignature: # Avoid circular import. from lemur.common import defaults raise error_class("Incorrect chain certificate(s) provided: '%s' is not signed by '%s'" % (defaults.common_name(cert) or 'Unknown', defaults.common_name(issuer))) except UnsupportedAlgorithm as err: current_app.logger.warning("Skipping chain validation: %s", err) # Next loop will validate that *this issuer* cert is signed by the next chain cert. cert = issuer
def verify_cert_chain(certs, error_class=ValidationError): """ Verifies that the certificates in the chain are correct. We don't bother with full cert validation but just check that certs in the chain are signed by the next, to avoid basic human errors -- such as pasting the wrong certificate. :param certs: List of parsed certificates, use parse_cert_chain() :param error_class: Exception class to raise on error """ cert = certs[0] for issuer in certs[1:]: # Use the current cert's public key to verify the previous signature. # "certificate validation is a complex problem that involves much more than just signature checks" try: check_cert_signature(cert, issuer.public_key()) except InvalidSignature: # Avoid circular import. from lemur.common import defaults raise error_class( "Incorrect chain certificate(s) provided: '%s' is not signed by '%s'" % ( defaults.common_name(cert) or "Unknown", defaults.common_name(issuer), )) except UnsupportedAlgorithm as err: current_app.logger.warning("Skipping chain validation: %s", err) # Next loop will validate that *this issuer* cert is signed by the next chain cert. cert = issuer
def upload(self, name, body, private_key, cert_chain, options, **kwargs): try: k8_base_uri = self.get_option('kubernetesURL', options) secret_format = self.get_option('secretFormat', options) k8s_api = K8sSession( self.k8s_bearer(options), self.k8s_cert(options) ) cn = common_name(parse_certificate(body)) secret_name_format = self.get_option('secretNameFormat', options) secret_name = secret_name_format.format(common_name=cn) secret = build_secret(secret_format, secret_name, body, private_key, cert_chain) err = ensure_resource( k8s_api, k8s_base_uri=k8_base_uri, namespace=self.k8s_namespace(options), kind="secret", name=secret_name, data=secret ) except Exception as e: current_app.logger.exception("Exception in upload: {}".format(e), exc_info=True) raise if err is not None: current_app.logger.error("Error deploying resource: %s", err) raise Exception("Error uploading secret: " + err)
def upload(self, name, body, private_key, cert_chain, options, **kwargs): try: k8_base_uri = self.get_option("kubernetesURL", options) secret_format = self.get_option("secretFormat", options) k8s_api = K8sSession(self.k8s_bearer(options), self.k8s_cert(options)) cn = common_name(parse_certificate(body)) secret_name_format = self.get_option("secretNameFormat", options) secret_name = secret_name_format.format(common_name=cn) secret = build_secret(secret_format, secret_name, body, private_key, cert_chain) err = ensure_resource( k8s_api, k8s_base_uri=k8_base_uri, namespace=self.k8s_namespace(options), kind="secret", name=secret_name, data=secret, ) except Exception as e: current_app.logger.exception("Exception in upload: {}".format(e), exc_info=True) raise if err is not None: current_app.logger.error("Error deploying resource: %s", err) raise Exception("Error uploading secret: " + err)
def __init__(self, **kwargs): cert = defaults.parse_certificate(kwargs['body']) self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = kwargs['name'] else: self.name = get_or_increase_name(defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san)) self.owner = kwargs['owner'] self.body = kwargs['body'] self.private_key = kwargs.get('private_key') self.chain = kwargs.get('chain') self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replacements', []) self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.serial = defaults.serial(cert) for domain in defaults.domains(cert): self.domains.append(Domain(name=domain))
def __init__(self, **kwargs): cert = defaults.parse_certificate(kwargs['body']) self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = kwargs['name'] else: self.name = get_or_increase_name( defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san)) self.owner = kwargs['owner'] self.body = kwargs['body'] self.private_key = kwargs.get('private_key') self.chain = kwargs.get('chain') self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replacements', []) self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.serial = defaults.serial(cert) for domain in defaults.domains(cert): self.domains.append(Domain(name=domain))
def __init__(self, **kwargs): self.body = kwargs["body"].strip() cert = self.parsed_cert self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) self.serial = defaults.serial(cert) self.owner = kwargs["owner"] if kwargs.get("private_key"): self.private_key = kwargs["private_key"].strip() if kwargs.get("chain"): self.chain = kwargs["chain"].strip() if kwargs.get("csr"): self.csr = kwargs["csr"].strip() self.notify = kwargs.get("notify", True) self.notifications = kwargs.get("notifications", []) self.description = kwargs.get("description") self.roles = list(set(kwargs.get("roles", []))) self.replaces = kwargs.get("replaces", []) self.rotation = kwargs.get("rotation") self.rotation_policy = kwargs.get("rotation_policy") self.key_type = kwargs.get("key_type") self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.external_id = kwargs.get("external_id") self.authority_id = kwargs.get("authority_id") self.dns_provider_id = kwargs.get("dns_provider_id") for domain in defaults.domains(cert): self.domains.append(Domain(name=domain)) # when destinations are appended they require a valid name # do not attempt to modify self.destinations before this step if kwargs.get("name"): self.name = get_or_increase_name( defaults.text_to_slug(kwargs["name"]), self.serial) else: self.name = get_or_increase_name( defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san, self.domains), self.serial, ) self.destinations = kwargs.get("destinations", []) # Check integrity before saving anything into the database. # For user-facing API calls, validation should also be done in schema validators. self.check_integrity()
def upload(self, name, body, private_key, cert_chain, options, **kwargs): """ Upload certificate and private key :param private_key: :param cert_chain: :return: """ # we use the common name to identify the certificate # Azure does not allow "." in the certificate name we replace them with "-" cert = parse_certificate(body) certificate_name = common_name(cert).replace(".", "-") vault_URI = self.get_option("vaultUrl", options) tenant = self.get_option("azureTenant", options) app_id = self.get_option("appID", options) password = self.get_option("azurePassword", options) access_token = get_access_token(tenant, app_id, password, self) cert_url = f"{vault_URI}/certificates/{certificate_name}/import?api-version=7.1" post_header = {"Authorization": f"Bearer {access_token}"} key_pkcs8 = parse_private_key(private_key).private_bytes( encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8, encryption_algorithm=serialization.NoEncryption(), ) key_pkcs8 = key_pkcs8.decode("utf-8").replace('\\n', '\n') cert_package = f"{body}\n{key_pkcs8}" post_body = { "value": cert_package, "policy": { "key_props": { "exportable": True, "kty": "RSA", "key_size": bitstrength(cert), "reuse_key": True }, "secret_props": { "contentType": "application/x-pem-file" } } } try: response = self.session.post(cert_url, headers=post_header, json=post_body) except requests.exceptions.RequestException as e: current_app.logger.exception(f"AZURE: Error for POST {e}") return_value = handle_response(response)
def __init__(self, **kwargs): self.body = kwargs['body'].strip() cert = self.parsed_cert self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) self.serial = defaults.serial(cert) # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = get_or_increase_name( defaults.text_to_slug(kwargs['name']), self.serial) else: self.name = get_or_increase_name( defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san), self.serial) self.owner = kwargs['owner'] if kwargs.get('private_key'): self.private_key = kwargs['private_key'].strip() if kwargs.get('chain'): self.chain = kwargs['chain'].strip() if kwargs.get('csr'): self.csr = kwargs['csr'].strip() self.notify = kwargs.get('notify', True) self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replaces', []) self.rotation = kwargs.get('rotation') self.rotation_policy = kwargs.get('rotation_policy') self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.external_id = kwargs.get('external_id') self.authority_id = kwargs.get('authority_id') self.dns_provider_id = kwargs.get('dns_provider_id') for domain in defaults.domains(cert): self.domains.append(Domain(name=domain)) # Check integrity before saving anything into the database. # For user-facing API calls, validation should also be done in schema validators. self.check_integrity()
def upload(self, name, body, private_key, cert_chain, options, **kwargs): """ Upload certificate and private key :param private_key: :param cert_chain: :return: """ cname = common_name(parse_certificate(body)) url = self.get_option('vaultUrl', options) token_file = self.get_option('vaultAuthTokenFile', options) mount = self.get_option('vaultMount', options) path = self.get_option('vaultPath', options) bundle = self.get_option('bundleChain', options) obj_name = self.get_option('objectName', options) api_version = self.get_option('vaultKvApiVersion', options) with open(token_file, 'r') as file: token = file.readline().rstrip('\n') client = hvac.Client(url=url, token=token) client.secrets.kv.default_kv_version = api_version if obj_name: path = '{0}/{1}'.format(path, obj_name) else: path = '{0}/{1}'.format(path, cname) secret = get_secret(client, mount, path) secret['data'][cname] = {} if bundle == 'Nginx' and cert_chain: secret['data'][cname]['crt'] = '{0}\n{1}'.format(body, cert_chain) elif bundle == 'Apache' and cert_chain: secret['data'][cname]['crt'] = body secret['data'][cname]['chain'] = cert_chain else: secret['data'][cname]['crt'] = body secret['data'][cname]['key'] = private_key san_list = get_san_list(body) if isinstance(san_list, list): secret['data'][cname]['san'] = san_list try: client.secrets.kv.create_or_update_secret(path=path, mount_point=mount, secret=secret['data']) except ConnectionError as err: current_app.logger.exception( "Exception uploading secret to vault: {0}".format(err), exc_info=True)
def __init__(self, **kwargs): self.body = kwargs['body'].strip() cert = self.parsed_cert self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) self.serial = defaults.serial(cert) # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = get_or_increase_name(defaults.text_to_slug(kwargs['name']), self.serial) else: self.name = get_or_increase_name( defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san), self.serial) self.owner = kwargs['owner'] if kwargs.get('private_key'): self.private_key = kwargs['private_key'].strip() if kwargs.get('chain'): self.chain = kwargs['chain'].strip() if kwargs.get('csr'): self.csr = kwargs['csr'].strip() self.notify = kwargs.get('notify', True) self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replaces', []) self.rotation = kwargs.get('rotation') self.rotation_policy = kwargs.get('rotation_policy') self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.external_id = kwargs.get('external_id') self.authority_id = kwargs.get('authority_id') self.dns_provider_id = kwargs.get('dns_provider_id') for domain in defaults.domains(cert): self.domains.append(Domain(name=domain)) # Check integrity before saving anything into the database. # For user-facing API calls, validation should also be done in schema validators. self.check_integrity()
def upload(self, name, body, private_key, cert_chain, options, **kwargs): """ Upload certificate and private key :param private_key: :param cert_chain: :return: """ priv_id = None cert_id = None name_found = False cname = common_name(parse_certificate(body)) priv_keys = get_all_private_keys() cert_keys = get_all_certificates() log_data = { "function": inspect.currentframe().f_code.co_name } for each in priv_keys: if each['name'] == cname: name_found = True if each['sha1'] == get_public_key_sha1(private_key): priv_id = None break else: priv_id = each['id'] for cert in cert_keys: if cert['name'] == cname: cert_id = cert['id'] if priv_id or not name_found: post_private_key(private_key, name=cname) time.sleep(2) new_cert_id = post_certificate(body, cert_chain, name=cname) log_data["message"] = f"Certificate updated: {cname}" act_id = get_activation(cert_id) if len(act_id) > 0 and new_cert_id: for each in act_id: patch_activation(each, new_cert_id) log_data["message"] = f"Certificate updated: {new_cert_id} activated: {act_id}" if cert_id: delete_certificate(cert_id) if priv_id: delete_private_key(priv_id) else: log_data["message"] = f"Certificate up to data, no changes made" current_app.logger.debug(log_data)
def __init__(self, **kwargs): self.csr = kwargs.get("csr") self.private_key = kwargs.get("private_key", "") if self.private_key: # If the request does not send private key, the key exists but the value is None self.private_key = self.private_key.strip() self.external_id = kwargs.get("external_id") # when destinations are appended they require a valid name. if kwargs.get("name"): self.name = get_or_increase_name(defaults.text_to_slug(kwargs["name"]), 0) self.rename = False else: # TODO: Fix auto-generated name, it should be renamed on creation self.name = get_or_increase_name( defaults.certificate_name( kwargs["common_name"], kwargs["authority"].name, dt.now(), dt.now(), False, ), self.external_id, ) self.rename = True self.cn = defaults.common_name(utils.parse_csr(self.csr)) self.owner = kwargs["owner"] self.number_attempts = 0 if kwargs.get("chain"): self.chain = kwargs["chain"].strip() self.notify = kwargs.get("notify", True) self.destinations = kwargs.get("destinations", []) self.notifications = kwargs.get("notifications", []) self.description = kwargs.get("description") self.roles = list(set(kwargs.get("roles", []))) self.replaces = kwargs.get("replaces", []) self.rotation = kwargs.get("rotation") self.rotation_policy = kwargs.get("rotation_policy") try: self.dns_provider_id = kwargs.get("dns_provider").id except (AttributeError, KeyError, TypeError, Exception): pass
def __init__(self, **kwargs): cert = lemur.common.utils.parse_certificate(kwargs['body']) self.issuer = defaults.issuer(cert) self.cn = defaults.common_name(cert) self.san = defaults.san(cert) self.not_before = defaults.not_before(cert) self.not_after = defaults.not_after(cert) self.serial = defaults.serial(cert) # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = get_or_increase_name( defaults.text_to_slug(kwargs['name']), self.serial) else: self.name = get_or_increase_name( defaults.certificate_name(self.cn, self.issuer, self.not_before, self.not_after, self.san), self.serial) self.owner = kwargs['owner'] self.body = kwargs['body'].strip() if kwargs.get('private_key'): self.private_key = kwargs['private_key'].strip() if kwargs.get('chain'): self.chain = kwargs['chain'].strip() self.notify = kwargs.get('notify', True) self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replaces', []) self.rotation = kwargs.get('rotation') self.rotation_policy = kwargs.get('rotation_policy') self.signing_algorithm = defaults.signing_algorithm(cert) self.bits = defaults.bitstrength(cert) self.external_id = kwargs.get('external_id') self.authority_id = kwargs.get('authority_id') self.dns_provider_id = kwargs.get('dns_provider_id') for domain in defaults.domains(cert): self.domains.append(Domain(name=domain))
def export(self, body, chain, key, options, **kwargs): """ Generates a Java Truststore """ if self.get_option("alias", options): alias = self.get_option("alias", options) else: alias = common_name(parse_certificate(body)) if self.get_option("passphrase", options): passphrase = self.get_option("passphrase", options) else: passphrase = Fernet.generate_key().decode("utf-8") raw = create_truststore(body, chain, alias, passphrase) return "jks", passphrase, raw
def export(self, body, chain, key, options, **kwargs): """ Generates a Java Keystore """ if self.get_option('passphrase', options): passphrase = self.get_option('passphrase', options) else: passphrase = Fernet.generate_key().decode('utf-8') if self.get_option('alias', options): alias = self.get_option('alias', options) else: alias = common_name(parse_certificate(body)) raw = create_keystore(body, chain, key, alias, passphrase) return 'jks', passphrase, raw
def export(self, body, chain, key, options, **kwargs): """ Generates a Java Truststore """ if self.get_option('alias', options): alias = self.get_option('alias', options) else: alias = common_name(parse_certificate(body)) if self.get_option('passphrase', options): passphrase = self.get_option('passphrase', options) else: passphrase = Fernet.generate_key().decode('utf-8') raw = create_truststore(body, chain, alias, passphrase) return 'jks', passphrase, raw
def __init__(self, **kwargs): self.csr = kwargs.get('csr') self.private_key = kwargs.get('private_key', "") if self.private_key: # If the request does not send private key, the key exists but the value is None self.private_key = self.private_key.strip() self.external_id = kwargs.get('external_id') # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = get_or_increase_name( defaults.text_to_slug(kwargs['name']), 0) self.rename = False else: # TODO: Fix auto-generated name, it should be renamed on creation self.name = get_or_increase_name( defaults.certificate_name(kwargs['common_name'], kwargs['authority'].name, dt.now(), dt.now(), False), self.external_id) self.rename = True self.cn = defaults.common_name(utils.parse_csr(self.csr)) self.owner = kwargs['owner'] self.number_attempts = 0 if kwargs.get('chain'): self.chain = kwargs['chain'].strip() self.notify = kwargs.get('notify', True) self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replaces', []) self.rotation = kwargs.get('rotation') self.rotation_policy = kwargs.get('rotation_policy') try: self.dns_provider_id = kwargs.get('dns_provider').id except (AttributeError, KeyError, TypeError, Exception): pass
def upload(self, name, body, private_key, cert_chain, options, **kwargs): current_app.logger.debug("SFTP destination plugin is started") cn = common_name(parse_certificate(body)) dst_path = self.get_option("destinationPath", options) dst_path_cn = dst_path + "/" + cn export_format = self.get_option("exportFormat", options) # prepare files for upload files = {cn + ".key": private_key, cn + ".pem": body} if cert_chain: if export_format == "NGINX": # assemble body + chain in the single file files[cn + ".pem"] += "\n" + cert_chain elif export_format == "Apache": # store chain in the separate file files[cn + ".ca.bundle.pem"] = cert_chain self.upload_file(dst_path_cn, files, options)
def __init__(self, **kwargs): self.csr = kwargs.get('csr') self.private_key = kwargs.get('private_key', "") if self.private_key: # If the request does not send private key, the key exists but the value is None self.private_key = self.private_key.strip() self.external_id = kwargs.get('external_id') # when destinations are appended they require a valid name. if kwargs.get('name'): self.name = get_or_increase_name(defaults.text_to_slug(kwargs['name']), 0) self.rename = False else: # TODO: Fix auto-generated name, it should be renamed on creation self.name = get_or_increase_name( defaults.certificate_name(kwargs['common_name'], kwargs['authority'].name, dt.now(), dt.now(), False), self.external_id) self.rename = True self.cn = defaults.common_name(utils.parse_csr(self.csr)) self.owner = kwargs['owner'] self.number_attempts = 0 if kwargs.get('chain'): self.chain = kwargs['chain'].strip() self.notify = kwargs.get('notify', True) self.destinations = kwargs.get('destinations', []) self.notifications = kwargs.get('notifications', []) self.description = kwargs.get('description') self.roles = list(set(kwargs.get('roles', []))) self.replaces = kwargs.get('replaces', []) self.rotation = kwargs.get('rotation') self.rotation_policy = kwargs.get('rotation_policy') try: self.dns_provider_id = kwargs.get('dns_provider').id except (AttributeError, KeyError, TypeError, Exception): pass
def export(self, body, chain, key, options, **kwargs): """ Generates a PKCS#12 archive. :param key: :param chain: :param body: :param options: :param kwargs: """ if self.get_option('passphrase', options): passphrase = self.get_option('passphrase', options) else: passphrase = get_psuedo_random_string() if self.get_option('alias', options): alias = self.get_option('alias', options) else: alias = common_name(parse_certificate(body)) type = self.get_option('type', options) with mktemppath() as output_tmp: if type == 'PKCS12 (.p12)': if not key: raise Exception("Private Key required by {0}".format(type)) create_pkcs12(body, chain, output_tmp, key, alias, passphrase) extension = "p12" else: raise Exception( "Unable to export, unsupported type: {0}".format(type)) with open(output_tmp, 'rb') as f: raw = f.read() return extension, passphrase, raw
def upload(self, name, body, private_key, cert_chain, options, **kwargs): """ Upload certificate and private key :param private_key: :param cert_chain: :return: """ cname = common_name(parse_certificate(body)) url = self.get_option("vaultUrl", options) auth_method = self.get_option("authenticationMethod", options) auth_key = self.get_option("tokenFile/vaultRole", options) mount = self.get_option("vaultMount", options) path = self.get_option("vaultPath", options) bundle = self.get_option("bundleChain", options) obj_name = self.get_option("objectName", options) api_version = self.get_option("vaultKvApiVersion", options) san_filter = self.get_option("sanFilter", options) san_list = get_san_list(body) if san_filter: for san in san_list: try: if not re.match(san_filter, san, flags=re.IGNORECASE): current_app.logger.exception( "Exception uploading secret to vault: invalid SAN: {}" .format(san), exc_info=True, ) os._exit(1) except re.error: current_app.logger.exception( "Exception compiling regex filter: invalid filter", exc_info=True, ) client = hvac.Client(url=url) if auth_method == 'token': with open(auth_key, "r") as tfile: token = tfile.readline().rstrip("\n") client.token = token if auth_method == 'kubernetes': token_path = '/var/run/secrets/kubernetes.io/serviceaccount/token' with open(token_path, 'r') as f: jwt = f.read() client.auth_kubernetes(auth_key, jwt) client.secrets.kv.default_kv_version = api_version if obj_name: path = "{0}/{1}".format(path, obj_name) else: path = "{0}/{1}".format(path, cname) secret = get_secret(client, mount, path) secret["data"][cname] = {} if not cert_chain: chain = '' else: chain = cert_chain if bundle == "Nginx": secret["data"][cname]["crt"] = "{0}\n{1}".format(body, chain) secret["data"][cname]["key"] = private_key elif bundle == "Apache": secret["data"][cname]["crt"] = body secret["data"][cname]["chain"] = chain secret["data"][cname]["key"] = private_key elif bundle == "PEM": secret["data"][cname]["pem"] = "{0}\n{1}\n{2}".format( body, chain, private_key) else: secret["data"][cname]["crt"] = body secret["data"][cname]["key"] = private_key if isinstance(san_list, list): secret["data"][cname]["san"] = san_list try: client.secrets.kv.create_or_update_secret(path=path, mount_point=mount, secret=secret["data"]) except ConnectionError as err: current_app.logger.exception( "Exception uploading secret to vault: {0}".format(err), exc_info=True)
def test_cert_get_cn(client): from lemur.common.defaults import common_name assert common_name(SAN_CERT) == 'san.example.org'
def test_cert_get_cn(client): from .vectors import INTERNAL_VALID_LONG_CERT from lemur.common.defaults import common_name assert common_name(INTERNAL_VALID_LONG_CERT) == 'long.lived.com'
def upload(self, name, body, private_key, cert_chain, options, **kwargs): current_app.logger.debug('SFTP destination plugin is started') cn = common_name(parse_certificate(body)) host = self.get_option('host', options) port = self.get_option('port', options) user = self.get_option('user', options) password = self.get_option('password', options) ssh_priv_key = self.get_option('privateKeyPath', options) ssh_priv_key_pass = self.get_option('privateKeyPass', options) dst_path = self.get_option('destinationPath', options) export_format = self.get_option('exportFormat', options) # prepare files for upload files = {cn + '.key': private_key, cn + '.pem': body} if cert_chain: if export_format == 'NGINX': # assemble body + chain in the single file files[cn + '.pem'] += '\n' + cert_chain elif export_format == 'Apache': # store chain in the separate file files[cn + '.ca.bundle.pem'] = cert_chain # upload files try: current_app.logger.debug('Connecting to {0}@{1}:{2}'.format(user, host, port)) ssh = paramiko.SSHClient() # allow connection to the new unknown host ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # open the ssh connection if password: current_app.logger.debug('Using password') ssh.connect(host, username=user, port=port, password=password) elif ssh_priv_key: current_app.logger.debug('Using RSA private key') pkey = paramiko.RSAKey.from_private_key_file(ssh_priv_key, ssh_priv_key_pass) ssh.connect(host, username=user, port=port, pkey=pkey) else: current_app.logger.error("No password or private key provided. Can't proceed") raise paramiko.ssh_exception.AuthenticationException # open the sftp session inside the ssh connection sftp = ssh.open_sftp() # make sure that the destination path exist try: current_app.logger.debug('Creating {0}'.format(dst_path)) sftp.mkdir(dst_path) except IOError: current_app.logger.debug('{0} already exist, resuming'.format(dst_path)) try: dst_path_cn = dst_path + '/' + cn current_app.logger.debug('Creating {0}'.format(dst_path_cn)) sftp.mkdir(dst_path_cn) except IOError: current_app.logger.debug('{0} already exist, resuming'.format(dst_path_cn)) # upload certificate files to the sftp destination for filename, data in files.items(): current_app.logger.debug('Uploading {0} to {1}'.format(filename, dst_path_cn)) with sftp.open(dst_path_cn + '/' + filename, 'w') as f: f.write(data) # read only for owner, -r-------- sftp.chmod(dst_path_cn + '/' + filename, 0o400) ssh.close() except Exception as e: current_app.logger.error('ERROR in {0}: {1}'.format(e.__class__, e)) try: ssh.close() except BaseException: pass
def upload(self, name, body, private_key, cert_chain, options, **kwargs): current_app.logger.debug("SFTP destination plugin is started") cn = common_name(parse_certificate(body)) host = self.get_option("host", options) port = self.get_option("port", options) user = self.get_option("user", options) password = self.get_option("password", options) ssh_priv_key = self.get_option("privateKeyPath", options) ssh_priv_key_pass = self.get_option("privateKeyPass", options) dst_path = self.get_option("destinationPath", options) export_format = self.get_option("exportFormat", options) # prepare files for upload files = {cn + ".key": private_key, cn + ".pem": body} if cert_chain: if export_format == "NGINX": # assemble body + chain in the single file files[cn + ".pem"] += "\n" + cert_chain elif export_format == "Apache": # store chain in the separate file files[cn + ".ca.bundle.pem"] = cert_chain # upload files try: current_app.logger.debug("Connecting to {0}@{1}:{2}".format( user, host, port)) ssh = paramiko.SSHClient() # allow connection to the new unknown host ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # open the ssh connection if password: current_app.logger.debug("Using password") ssh.connect(host, username=user, port=port, password=password) elif ssh_priv_key: current_app.logger.debug("Using RSA private key") pkey = paramiko.RSAKey.from_private_key_file( ssh_priv_key, ssh_priv_key_pass) ssh.connect(host, username=user, port=port, pkey=pkey) else: current_app.logger.error( "No password or private key provided. Can't proceed") raise paramiko.ssh_exception.AuthenticationException # open the sftp session inside the ssh connection sftp = ssh.open_sftp() # make sure that the destination path exist try: current_app.logger.debug("Creating {0}".format(dst_path)) sftp.mkdir(dst_path) except IOError: current_app.logger.debug( "{0} already exist, resuming".format(dst_path)) try: dst_path_cn = dst_path + "/" + cn current_app.logger.debug("Creating {0}".format(dst_path_cn)) sftp.mkdir(dst_path_cn) except IOError: current_app.logger.debug( "{0} already exist, resuming".format(dst_path_cn)) # upload certificate files to the sftp destination for filename, data in files.items(): current_app.logger.debug("Uploading {0} to {1}".format( filename, dst_path_cn)) with sftp.open(dst_path_cn + "/" + filename, "w") as f: f.write(data) # read only for owner, -r-------- sftp.chmod(dst_path_cn + "/" + filename, 0o400) ssh.close() except Exception as e: current_app.logger.error("ERROR in {0}: {1}".format( e.__class__, e)) try: ssh.close() except BaseException: pass