Example #1
0
def get_serial_from_cert(cert_path):
    """Retrieve the serial number of a certificate from certificate path

    :param str cert_path: path to a cert in PEM format

    :returns: serial number of the certificate
    :rtype: int
    """
    # pylint: disable=redefined-outer-name
    with open(cert_path) as f:
        x509 = crypto.load_certificate(crypto.FILETYPE_PEM, f.read())
    return x509.get_serial_number()
Example #2
0
def main():
    module = AnsibleModule(argument_spec=dict(
        ca_cert=dict(type='path'),
        host=dict(type='str', required=True),
        port=dict(type='int', required=True),
        proxy_host=dict(type='str'),
        proxy_port=dict(type='int', default=8080),
        timeout=dict(type='int', default=10),
        select_crypto_backend=dict(
            type='str',
            choices=['auto', 'pyopenssl', 'cryptography'],
            default='auto'),
    ), )

    ca_cert = module.params.get('ca_cert')
    host = module.params.get('host')
    port = module.params.get('port')
    proxy_host = module.params.get('proxy_host')
    proxy_port = module.params.get('proxy_port')
    timeout = module.params.get('timeout')

    backend = module.params.get('select_crypto_backend')
    if backend == 'auto':
        # Detection what is possible
        can_use_cryptography = CRYPTOGRAPHY_FOUND and CRYPTOGRAPHY_VERSION >= LooseVersion(
            MINIMAL_CRYPTOGRAPHY_VERSION)
        can_use_pyopenssl = PYOPENSSL_FOUND and PYOPENSSL_VERSION >= LooseVersion(
            MINIMAL_PYOPENSSL_VERSION)

        # First try cryptography, then pyOpenSSL
        if can_use_cryptography:
            backend = 'cryptography'
        elif can_use_pyopenssl:
            backend = 'pyopenssl'

        # Success?
        if backend == 'auto':
            module.fail_json(msg=(
                "Can't detect any of the required Python libraries "
                "cryptography (>= {0}) or PyOpenSSL (>= {1})"
            ).format(MINIMAL_CRYPTOGRAPHY_VERSION, MINIMAL_PYOPENSSL_VERSION))

    if backend == 'pyopenssl':
        if not PYOPENSSL_FOUND:
            module.fail_json(msg=missing_required_lib(
                'pyOpenSSL >= {0}'.format(MINIMAL_PYOPENSSL_VERSION)),
                             exception=PYOPENSSL_IMP_ERR)
        module.deprecate(
            'The module is using the PyOpenSSL backend. This backend has been deprecated',
            version='2.13')
    elif backend == 'cryptography':
        if not CRYPTOGRAPHY_FOUND:
            module.fail_json(msg=missing_required_lib(
                'cryptography >= {0}'.format(MINIMAL_CRYPTOGRAPHY_VERSION)),
                             exception=CRYPTOGRAPHY_IMP_ERR)

    result = dict(changed=False, )

    if not PYOPENSSL_FOUND:
        module.fail_json(msg=missing_required_lib('pyOpenSSL >= 0.15'),
                         exception=PYOPENSSL_IMP_ERR)

    if timeout:
        setdefaulttimeout(timeout)

    if ca_cert:
        if not isfile(ca_cert):
            module.fail_json(msg="ca_cert file does not exist")

    if proxy_host:
        if not HAS_CREATE_DEFAULT_CONTEXT:
            module.fail_json(
                msg=
                'To use proxy_host, you must run the get_certificate module with Python 2.7 or newer.',
                exception=CREATE_DEFAULT_CONTEXT_IMP_ERR)

        try:
            connect = "CONNECT %s:%s HTTP/1.0\r\n\r\n" % (host, port)
            sock = socket()
            atexit.register(sock.close)
            sock.connect((proxy_host, proxy_port))
            sock.send(connect.encode())
            sock.recv(8192)

            ctx = create_default_context()
            ctx.check_hostname = False
            ctx.verify_mode = CERT_NONE

            if ca_cert:
                ctx.verify_mode = CERT_OPTIONAL
                ctx.load_verify_locations(cafile=ca_cert)

            cert = ctx.wrap_socket(sock,
                                   server_hostname=host).getpeercert(True)
            cert = DER_cert_to_PEM_cert(cert)
        except Exception as e:
            module.fail_json(
                msg="Failed to get cert from port with error: {0}".format(e))

    else:
        try:
            cert = get_server_certificate((host, port), ca_certs=ca_cert)
        except Exception as e:
            module.fail_json(
                msg="Failed to get cert from port with error: {0}".format(e))

    result['cert'] = cert

    if backend == 'pyopenssl':
        x509 = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
        result['subject'] = {}
        for component in x509.get_subject().get_components():
            result['subject'][component[0]] = component[1]

        result['expired'] = x509.has_expired()

        result['extensions'] = []
        extension_count = x509.get_extension_count()
        for index in range(0, extension_count):
            extension = x509.get_extension(index)
            result['extensions'].append({
                'critical': extension.get_critical(),
                'asn1_data': extension.get_data(),
                'name': extension.get_short_name(),
            })

        result['issuer'] = {}
        for component in x509.get_issuer().get_components():
            result['issuer'][component[0]] = component[1]

        result['not_after'] = x509.get_notAfter()
        result['not_before'] = x509.get_notBefore()

        result['serial_number'] = x509.get_serial_number()
        result['signature_algorithm'] = x509.get_signature_algorithm()

        result['version'] = x509.get_version()

    elif backend == 'cryptography':
        x509 = cryptography.x509.load_pem_x509_certificate(
            to_bytes(cert), cryptography_backend())
        result['subject'] = {}
        for attribute in x509.subject:
            result['subject'][crypto_utils.cryptography_oid_to_name(
                attribute.oid, short=True)] = attribute.value

        result['expired'] = x509.not_valid_after < datetime.datetime.utcnow()

        result['extensions'] = []
        for dotted_number, entry in crypto_utils.cryptography_get_extensions_from_cert(
                x509).items():
            oid = cryptography.x509.oid.ObjectIdentifier(dotted_number)
            result['extensions'].append({
                'critical':
                entry['critical'],
                'asn1_data':
                base64.b64decode(entry['value']),
                'name':
                crypto_utils.cryptography_oid_to_name(oid, short=True),
            })

        result['issuer'] = {}
        for attribute in x509.issuer:
            result['issuer'][crypto_utils.cryptography_oid_to_name(
                attribute.oid, short=True)] = attribute.value

        result['not_after'] = x509.not_valid_after.strftime('%Y%m%d%H%M%SZ')
        result['not_before'] = x509.not_valid_before.strftime('%Y%m%d%H%M%SZ')

        result['serial_number'] = x509.serial_number
        result['signature_algorithm'] = crypto_utils.cryptography_oid_to_name(
            x509.signature_algorithm_oid)

        # We need the -1 offset to get the same values as pyOpenSSL
        if x509.version == cryptography.x509.Version.v1:
            result['version'] = 1 - 1
        elif x509.version == cryptography.x509.Version.v3:
            result['version'] = 3 - 1
        else:
            result['version'] = "unknown"

    module.exit_json(**result)
Example #3
0
    def get_certificates(self, options, **kwargs):

        certs = []
        issuer_dn = self.get_option("issuerdn", options)
        source_const = self.get_option("source_const", options)
        if source_const is not None:
            source_const = source_const.upper()

        # print("SOURCE**** " +str(source_const))
        session = requests.Session()
        session.mount('https://', HttpsAdapter())
        session.cert = current_app.config.get(
            "EJBCA_PEM_PATH_{0}".format(source_const),
            current_app.config.get("EJBCA_PEM_PATH"))
        session.verify = current_app.config.get("EJBCA_TRUSTSTORE")
        session.hooks = dict(response=log_status_code)

        source_expire_days = current_app.config.get("EJBCA_SOURCE_EXPIRE_DAYS",
                                                    7300)
        source_max_results = current_app.config.get("EJBCA_SOURCE_MAX_RESULTS",
                                                    100000)

        request_data = {
            'arg0': source_expire_days,
            'arg1': issuer_dn,
            'arg2': source_max_results,
        }

        transport = Transport(session=session)
        url = current_app.config.get(
            "EJBCA_URL") + "/ejbca/ejbcaws/ejbcaws?wsdl"

        client = Client(url, transport=transport)

        response = client.service.getCertificatesByExpirationTimeAndIssuer(
            **request_data)
        num_certs = len(response)

        for x in range(num_certs):
            encoded_cert = response[x].certificateData

            decoded_cert = encoded_cert.decode('utf-8')
            pem = "-----BEGIN CERTIFICATE-----\n"
            pem += decoded_cert
            pem += "\n-----END CERTIFICATE-----"

            x509 = load_certificate(FILETYPE_PEM, pem)
            # get SubjectDN string from CSR
            serial = x509.get_serial_number()
            # External ID required for revocation
            # Generate a random ID
            rand_external_id = random.randrange(10**11, 10**12)
            external_id = str(rand_external_id)

            chain = '{}\n{}'.format(
                current_app.config.get('EJBCA_INTERMEDIATE', '').strip(),
                current_app.config.get('EJBCA_ROOT', '').strip())
            cert = {
                "body": "\n".join(str(pem).splitlines()),
                "serial": serial,
                "external_id": external_id,
                "chain": chain,
            }
            certs.append(cert)

        return certs