import re import unicodedata from cryptography import x509 from flask import current_app from lemur.common.utils import is_selfsigned from lemur.extensions import sentry from lemur.constants import SAN_NAMING_TEMPLATE, DEFAULT_NAMING_TEMPLATE def text_to_slug(value, joiner="-"): """ Normalize a string to a "slug" value, stripping character accents and removing non-alphanum characters. A series of non-alphanumeric characters is replaced with the joiner character. """ # Strip all character accents: decompose Unicode characters and then drop combining chars. value = "".join( c for c in unicodedata.normalize("NFKD", value) if not unicodedata.combining(c) ) # Replace all remaining non-alphanumeric characters with joiner string. Multiple characters get collapsed into a # single joiner. Except, keep 'xn--' used in IDNA domain names as is. value = re.sub(r"[^A-Za-z0-9.]+(? 1: return True def is_wildcard(cert): """ Determines if certificate is a wildcard certificate. :param cert: :return: Bool """ d = domains(cert) if len(d) == 1 and d[0][0:1] == "*": return True if cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value[0:1] == "*": return True def bitstrength(cert): """ Calculates a certificates public key bit length. :param cert: :return: Integer """ try: return cert.public_key().key_size except AttributeError: sentry.captureException() current_app.logger.debug("Unable to get bitstrength.") def issuer(cert): """ Gets a sane issuer slug from a given certificate, stripping non-alphanumeric characters. For self-signed certificates, the special value '' is returned. If issuer cannot be determined, '' is returned. :param cert: Parsed certificate object :return: Issuer slug """ # If certificate is self-signed, we return a special value -- there really is no distinct "issuer" for it if is_selfsigned(cert): return "" # Try Common Name or fall back to Organization name attrs = cert.issuer.get_attributes_for_oid( x509.OID_COMMON_NAME ) or cert.issuer.get_attributes_for_oid(x509.OID_ORGANIZATION_NAME) if not attrs: current_app.logger.error( "Unable to get issuer! Cert serial {:x}".format(cert.serial_number) ) return "" return text_to_slug(attrs[0].value, "") def not_before(cert): """ Gets the naive datetime of the certificates 'not_before' field. This field denotes the first date in time which the given certificate is valid. :param cert: :return: Datetime """ return cert.not_valid_before def not_after(cert): """ Gets the naive datetime of the certificates 'not_after' field. This field denotes the last date in time which the given certificate is valid. :return: Datetime """ return cert.not_valid_after