Example #1
0
    def get_info(self):
        result = dict()
        self.csr = crypto_utils.load_certificate_request(self.path,
                                                         backend=self.backend)

        result['subject'] = self._get_subject()
        result['key_usage'], result[
            'key_usage_critical'] = self._get_key_usage()
        result['extended_key_usage'], result[
            'extended_key_usage_critical'] = self._get_extended_key_usage()
        result['basic_constraints'], result[
            'basic_constraints_critical'] = self._get_basic_constraints()
        result['ocsp_must_staple'], result[
            'ocsp_must_staple_critical'] = self._get_ocsp_must_staple()
        result['subject_alt_name'], result[
            'subject_alt_name_critical'] = self._get_subject_alt_name()

        result['public_key'] = self._get_public_key(binary=False)
        pk = self._get_public_key(binary=True)
        result[
            'public_key_fingerprints'] = crypto_utils.get_fingerprint_of_bytes(
                pk) if pk is not None else dict()

        result['extensions_by_oid'] = self._get_all_extensions()

        result['signature_valid'] = self._is_signature_valid()
        if not result['signature_valid']:
            self.module.fail_json(msg='CSR signature is invalid!', **result)
        return result
Example #2
0
 def __init__(self, module):
     super(SelfSignedCertificate, self).__init__(module)
     self.notBefore = module.params['selfsigned_notBefore']
     self.notAfter = module.params['selfsigned_notAfter']
     self.digest = module.params['selfsigned_digest']
     self.version = module.params['selfsigned_version']
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.privatekey = crypto_utils.load_privatekey(
         self.privatekey_path, self.privatekey_passphrase)
Example #3
0
 def __init__(self, module):
     super(SelfSignedCertificate, self).__init__(module)
     self.serial_number = randint(1000, 99999)
     self.notBefore = module.params['selfsigned_notBefore']
     self.notAfter = module.params['selfsigned_notAfter']
     self.digest = module.params['selfsigned_digest']
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.privatekey = crypto_utils.load_privatekey(
         self.privatekey_path, self.privatekey_passphrase)
     self.cert = None
Example #4
0
    def check(self, module):
        """Ensure the resource is in its desired state."""
        def _get_subject(csr):
            subject = csr.get_subject()
            components = dict(subject.get_components())
            for sub_key, sub_val in components.items():
                self.subject[sub_key] = sub_val
            for val in self.subject.values():
                if val == '':
                    self.subjectvalid = False

        def _get_san(csr):
            extensions = csr.get_extensions()
            for ext in extensions:
                if ext.get_short_name() == b"subjectAltName":
                    for altname in str(ext).split(','):
                        altname_data = altname.strip().split(':')
                        if altname_data[0] not in self.subjectAltName:
                            self.subjectAltName[altname_data[0]] = []
                        self.subjectAltName[altname_data[0]].append(
                            altname_data[1])

        def _get_key(csr):
            key = csr.get_pubkey()
            if key.type() == OpenSSL.crypto.TYPE_RSA:
                key_type = 'RSA'
            elif key.type() == OpenSSL.crypto.TYPE_DSA:
                key_type = 'DSA'
            elif key.type() == 408:
                key_type = 'EC'
            else:
                key_type = 'Unknown'

            self.key = {
                'type': key_type,
                'size': key.bits(),
            }

            # Minimums are being defined as 4096 for RSA/DSA & 384 for EC
            if (key_type == 'RSA' or key_type == 'DSA') and key.bits() >= 4096:
                self.keymin = True
            elif key_type == 'EC' and key.bits() >= 384:
                self.keymin = True

        if module.params['path']:
            csr = crypto_utils.load_certificate_request(self.path)
        else:
            try:
                csr = load_certificate_request(FILETYPE_PEM, self.csrdata)
            except (OpenSSL.crypto.Error) as exc:
                module.fail_json(msg=to_native(exc))

        _get_subject(csr)
        _get_key(csr)
        _get_san(csr)
 def __init__(self, module):
     super(SelfSignedCertificate, self).__init__(module)
     self.notBefore = module.params['selfsigned_notBefore']
     self.notAfter = module.params['selfsigned_notAfter']
     self.digest = module.params['selfsigned_digest']
     self.version = module.params['selfsigned_version']
     self.serial_number = randint(1000, 99999)
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.privatekey = crypto_utils.load_privatekey(
         self.privatekey_path, self.privatekey_passphrase
     )
Example #6
0
    def check(self, module, perms_required=True):
        """Ensure the resource is in its desired state."""

        state_and_perms = super(Certificate,
                                self).check(module, perms_required)

        def _validate_privatekey():
            if self.privatekey_path:
                ctx = OpenSSL.SSL.Context(OpenSSL.SSL.TLSv1_2_METHOD)
                ctx.use_privatekey(self.privatekey)
                ctx.use_certificate(self.cert)
                try:
                    ctx.check_privatekey()
                    return True
                except OpenSSL.SSL.Error:
                    return False

        def _validate_csr():
            try:
                self.csr.verify(self.cert.get_pubkey())
            except OpenSSL.crypto.Error:
                return False
            if self.csr.get_subject() != self.cert.get_subject():
                return False
            csr_extensions = self.csr.get_extensions()
            cert_extension_count = self.cert.get_extension_count()
            if len(csr_extensions) != cert_extension_count:
                return False
            for extension_number in range(0, cert_extension_count):
                cert_extension = self.cert.get_extension(extension_number)
                csr_extension = filter(
                    lambda extension: extension.get_short_name() ==
                    cert_extension.get_short_name(), csr_extensions)
                if cert_extension.get_data() != list(
                        csr_extension)[0].get_data():
                    return False
            return True

        if not state_and_perms:
            return False

        self.cert = crypto_utils.load_certificate(self.path)

        if self.privatekey_path:
            self.privatekey = crypto_utils.load_privatekey(
                self.privatekey_path, self.privatekey_passphrase)
            return _validate_privatekey()

        if self.csr_path:
            self.csr = crypto_utils.load_certificate_request(self.csr_path)
            if not _validate_csr():
                return False

        return True
Example #7
0
 def __init__(self, module):
     super(SelfSignedCertificate, self).__init__(module)
     self.notBefore = self.get_relative_time_option(module.params['selfsigned_not_before'], 'selfsigned_not_before')
     self.notAfter = self.get_relative_time_option(module.params['selfsigned_not_after'], 'selfsigned_not_after')
     self.digest = module.params['selfsigned_digest']
     self.version = module.params['selfsigned_version']
     self.serial_number = randint(1000, 99999)
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.privatekey = crypto_utils.load_privatekey(
         self.privatekey_path, self.privatekey_passphrase
     )
Example #8
0
 def __init__(self, module):
     super(SelfSignedCertificate, self).__init__(module)
     self.notBefore = module.params['selfsigned_notBefore']
     self.notAfter = module.params['selfsigned_notAfter']
     self.digest = module.params['selfsigned_digest']
     self.version = module.params['selfsigned_version']
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.privatekey = crypto_utils.load_privatekey(
         self.privatekey_path, self.privatekey_passphrase)
     if module.params['provider'] == 'localsigned':
         self.cacert = crypto_utils.load_certificate(
             module.params['cacert_path'])
     else:
         self.cacert = None
Example #9
0
    def get_info(self):
        result = dict()
        self.csr = crypto_utils.load_certificate_request(self.path,
                                                         content=self.content,
                                                         backend=self.backend)

        subject = self._get_subject_ordered()
        result['subject'] = dict()
        for k, v in subject:
            result['subject'][k] = v
        result['subject_ordered'] = subject
        result['key_usage'], result[
            'key_usage_critical'] = self._get_key_usage()
        result['extended_key_usage'], result[
            'extended_key_usage_critical'] = self._get_extended_key_usage()
        result['basic_constraints'], result[
            'basic_constraints_critical'] = self._get_basic_constraints()
        result['ocsp_must_staple'], result[
            'ocsp_must_staple_critical'] = self._get_ocsp_must_staple()
        result['subject_alt_name'], result[
            'subject_alt_name_critical'] = self._get_subject_alt_name()

        result['public_key'] = self._get_public_key(binary=False)
        pk = self._get_public_key(binary=True)
        result[
            'public_key_fingerprints'] = crypto_utils.get_fingerprint_of_bytes(
                pk) if pk is not None else dict()

        if self.backend != 'pyopenssl':
            ski = self._get_subject_key_identifier()
            if ski is not None:
                ski = to_native(binascii.hexlify(ski))
                ski = ':'.join([ski[i:i + 2] for i in range(0, len(ski), 2)])
            result['subject_key_identifier'] = ski

            aki, aci, acsn = self._get_authority_key_identifier()
            if aki is not None:
                aki = to_native(binascii.hexlify(aki))
                aki = ':'.join([aki[i:i + 2] for i in range(0, len(aki), 2)])
            result['authority_key_identifier'] = aki
            result['authority_cert_issuer'] = aci
            result['authority_cert_serial_number'] = acsn

        result['extensions_by_oid'] = self._get_all_extensions()

        result['signature_valid'] = self._is_signature_valid()
        if not result['signature_valid']:
            self.module.fail_json(msg='CSR signature is invalid!', **result)
        return result
 def __init__(self, module):
     super(OwnCACertificate, self).__init__(module)
     self.notBefore = module.params['ownca_not_before']
     self.notAfter = module.params['ownca_not_after']
     self.digest = module.params['ownca_digest']
     self.version = module.params['ownca_version']
     self.serial_number = randint(1000, 99999)
     self.ca_cert_path = module.params['ownca_path']
     self.ca_privatekey_path = module.params['ownca_privatekey_path']
     self.ca_privatekey_passphrase = module.params['ownca_privatekey_passphrase']
     self.csr = crypto_utils.load_certificate_request(self.csr_path)
     self.ca_cert = crypto_utils.load_certificate(self.ca_cert_path)
     self.ca_privatekey = crypto_utils.load_privatekey(
         self.ca_privatekey_path, self.ca_privatekey_passphrase
     )
Example #11
0
    def _check_csr(self):
        def _check_subject(csr):
            subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])), to_bytes(sub[1])) for sub in self.subject]
            current_subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])), to_bytes(sub[1])) for sub in csr.get_subject().get_components()]
            if not set(subject) == set(current_subject):
                return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions if ext.get_short_name() == b'subjectAltName'), '')
            altnames = [altname.strip() for altname in str(altnames_ext).split(',')]
            # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string
            # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004)
            altnames = [name if not name.startswith('IP Address:') else "IP:" + name.split(':', 1)[1] for name in altnames]
            if self.subjectAltName:
                if set(altnames) != set(self.subjectAltName) or altnames_ext.get_critical() != self.subjectAltName_critical:
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [ext for ext in extensions if ext.get_short_name() == extName]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip())) for usage in str(usages_ext[0]).split(',')]
                expected = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage)) for usage in expected]
                return set(current) == set(expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            usages_ext = [ext for ext in extensions if ext.get_short_name() == b'keyUsage']
            if (not usages_ext and self.keyUsage) or (usages_ext and not self.keyUsage):
                return False
            elif not usages_ext and not self.keyUsage:
                return True
            else:
                # OpenSSL._util.lib.OBJ_txt2nid() always returns 0 for all keyUsage values
                # (since keyUsage has a fixed bitfield for these values and is not extensible).
                # Therefore, we create an extension for the wanted values, and compare the
                # data of the extensions (which is the serialized bitfield).
                expected_ext = crypto.X509Extension(b"keyUsage", False, ', '.join(self.keyUsage).encode('ascii'))
                return usages_ext[0].get_data() == expected_ext.get_data() and usages_ext[0].get_critical() == self.keyUsage_critical

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage', self.extendedKeyUsage, self.extendedKeyUsage_critical)

        def _check_basicConstraints(extensions):
            return _check_keyUsage_(extensions, b'basicConstraints', self.basicConstraints, self.basicConstraints_critical)

        def _check_ocspMustStaple(extensions):
            oms_ext = [ext for ext in extensions if to_bytes(ext.get_short_name()) == OPENSSL_MUST_STAPLE_NAME and to_bytes(ext) == OPENSSL_MUST_STAPLE_VALUE]
            if OpenSSL.SSL.OPENSSL_VERSION_NUMBER < 0x10100000:
                # Older versions of libssl don't know about OCSP Must Staple
                oms_ext.extend([ext for ext in extensions if ext.get_short_name() == b'UNDEF' and ext.get_data() == b'\x30\x03\x02\x01\x05'])
            if self.ocspMustStaple:
                return len(oms_ext) > 0 and oms_ext[0].get_critical() == self.ocspMustStaple_critical
            else:
                return len(oms_ext) == 0

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return (_check_subjectAltName(extensions) and _check_keyUsage(extensions) and
                    _check_extenededKeyUsage(extensions) and _check_basicConstraints(extensions) and
                    _check_ocspMustStaple(extensions))

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        csr = crypto_utils.load_certificate_request(self.path)

        return _check_subject(csr) and _check_extensions(csr) and _check_signature(csr)
Example #12
0
    def check(self, module, perms_required=True):
        """Ensure the resource is in its desired state."""
        state_and_perms = super(CertificateSigningRequest,
                                self).check(module, perms_required)

        self.privatekey = crypto_utils.load_privatekey(
            self.privatekey_path, self.privatekey_passphrase)

        def _check_subject(csr):
            subject = csr.get_subject()
            for (key, value) in self.subject.items():
                if getattr(subject, key, None) != value:
                    return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions
                                 if ext.get_short_name() == b'subjectAltName'),
                                '')
            altnames = [
                altname.strip() for altname in str(altnames_ext).split(',')
            ]
            # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string
            # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004)
            altnames = [
                name if not name.startswith('IP Address:') else "IP:" +
                name.split(':', 1)[1] for name in altnames
            ]
            if self.subjectAltName:
                if set(altnames) != set(
                        self.subjectAltName) or altnames_ext.get_critical(
                        ) != self.subjectAltName_critical:
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [
                ext for ext in extensions if ext.get_short_name() == extName
            ]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip()))
                    for usage in str(usages_ext[0]).split(',')
                ]
                expected = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage))
                    for usage in expected
                ]
                return set(current) == set(
                    expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            return _check_keyUsage_(extensions, b'keyUsage', self.keyUsage,
                                    self.keyUsage_critical)

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage',
                                    self.extendedKeyUsage,
                                    self.extendedKeyUsage_critical)

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return _check_subjectAltName(extensions) and _check_keyUsage(
                extensions) and _check_extenededKeyUsage(extensions)

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        if not state_and_perms:
            return False

        csr = crypto_utils.load_certificate_request(self.path)

        return _check_subject(csr) and _check_extensions(
            csr) and _check_signature(csr)
Example #13
0
    def _check_csr(self):
        def _check_subject(csr):
            subject = [(crypto_utils.cryptography_name_to_oid(entry[0]),
                        entry[1]) for entry in self.subject]
            current_subject = [(sub.oid, sub.value) for sub in csr.subject]
            return set(subject) == set(current_subject)

        def _find_extension(extensions, type):
            return next(
                (ext for ext in extensions if isinstance(ext.value, type)),
                None)

        def _check_subjectAltName(extensions):
            current_altnames_ext = _find_extension(
                extensions, cryptography.x509.SubjectAlternativeName)
            current_altnames = [
                str(altname) for altname in current_altnames_ext.value
            ] if current_altnames_ext else []
            altnames = [
                str(crypto_utils.cryptography_get_name(altname))
                for altname in self.subjectAltName
            ] if self.subjectAltName else []
            if set(altnames) != set(current_altnames):
                return False
            if altnames:
                if current_altnames_ext.critical != self.subjectAltName_critical:
                    return False
            return True

        def _check_keyUsage(extensions):
            current_keyusage_ext = _find_extension(extensions,
                                                   cryptography.x509.KeyUsage)
            if not self.keyUsage:
                return current_keyusage_ext is None
            elif current_keyusage_ext is None:
                return False
            params = crypto_utils.cryptography_parse_key_usage_params(
                self.keyUsage)
            for param in params:
                if getattr(current_keyusage_ext.value,
                           '_' + param) != params[param]:
                    return False
            if current_keyusage_ext.critical != self.keyUsage_critical:
                return False
            return True

        def _check_extenededKeyUsage(extensions):
            current_usages_ext = _find_extension(
                extensions, cryptography.x509.ExtendedKeyUsage)
            current_usages = [
                str(usage) for usage in current_usages_ext.value
            ] if current_usages_ext else []
            usages = [
                str(crypto_utils.cryptography_name_to_oid(usage))
                for usage in self.extendedKeyUsage
            ] if self.extendedKeyUsage else []
            if set(current_usages) != set(usages):
                return False
            if usages:
                if current_usages_ext.critical != self.extendedKeyUsage_critical:
                    return False
            return True

        def _check_basicConstraints(extensions):
            bc_ext = _find_extension(extensions,
                                     cryptography.x509.BasicConstraints)
            current_ca = bc_ext.value.ca if bc_ext else False
            current_path_length = bc_ext.value.path_length if bc_ext else None
            ca, path_length = crypto_utils.cryptography_get_basic_constraints(
                self.basicConstraints)
            # Check CA flag
            if ca != current_ca:
                return False
            # Check path length
            if path_length != current_path_length:
                return False
            # Check criticality
            if self.basicConstraints:
                if bc_ext.critical != self.basicConstraints_critical:
                    return False
            return True

        def _check_ocspMustStaple(extensions):
            try:
                # This only works with cryptography >= 2.1
                tlsfeature_ext = _find_extension(extensions,
                                                 cryptography.x509.TLSFeature)
                has_tlsfeature = True
            except AttributeError as dummy:
                tlsfeature_ext = next(
                    (ext for ext in extensions
                     if ext.value.oid == CRYPTOGRAPHY_MUST_STAPLE_NAME), None)
                has_tlsfeature = False
            if self.ocspMustStaple:
                if not tlsfeature_ext or tlsfeature_ext.critical != self.ocspMustStaple_critical:
                    return False
                if has_tlsfeature:
                    return cryptography.x509.TLSFeatureType.status_request in tlsfeature_ext.value
                else:
                    return tlsfeature_ext.value.value == CRYPTOGRAPHY_MUST_STAPLE_VALUE
            else:
                return tlsfeature_ext is None

        def _check_extensions(csr):
            extensions = csr.extensions
            return (_check_subjectAltName(extensions)
                    and _check_keyUsage(extensions)
                    and _check_extenededKeyUsage(extensions)
                    and _check_basicConstraints(extensions)
                    and _check_ocspMustStaple(extensions))

        def _check_signature(csr):
            if not csr.is_signature_valid:
                return False
            # To check whether public key of CSR belongs to private key,
            # encode both public keys and compare PEMs.
            key_a = csr.public_key().public_bytes(
                cryptography.hazmat.primitives.serialization.Encoding.PEM,
                cryptography.hazmat.primitives.serialization.PublicFormat.
                SubjectPublicKeyInfo)
            key_b = self.privatekey.public_key().public_bytes(
                cryptography.hazmat.primitives.serialization.Encoding.PEM,
                cryptography.hazmat.primitives.serialization.PublicFormat.
                SubjectPublicKeyInfo)
            return key_a == key_b

        try:
            csr = crypto_utils.load_certificate_request(self.path,
                                                        backend='cryptography')
        except Exception as dummy:
            return False

        return _check_subject(csr) and _check_extensions(
            csr) and _check_signature(csr)
Example #14
0
    def check(self, module, perms_required=True):
        """Ensure the resource is in its desired state."""
        state_and_perms = super(CertificateSigningRequest, self).check(module, perms_required)

        self.privatekey = crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)

        def _check_subject(csr):
            subject = csr.get_subject()
            for (key, value) in self.subject.items():
                if getattr(subject, key, None) != value:
                    return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions if ext.get_short_name() == b'subjectAltName'), '')
            altnames = [altname.strip() for altname in str(altnames_ext).split(',')]
            # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string
            # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004)
            altnames = [name if not name.startswith('IP Address:') else "IP:" + name.split(':', 1)[1] for name in altnames]
            if self.subjectAltName:
                if set(altnames) != set(self.subjectAltName) or altnames_ext.get_critical() != self.subjectAltName_critical:
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [ext for ext in extensions if ext.get_short_name() == extName]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip())) for usage in str(usages_ext[0]).split(',')]
                expected = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage)) for usage in expected]
                return set(current) == set(expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            return _check_keyUsage_(extensions, b'keyUsage', self.keyUsage, self.keyUsage_critical)

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage', self.extendedKeyUsage, self.extendedKeyUsage_critical)

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return _check_subjectAltName(extensions) and _check_keyUsage(extensions) and _check_extenededKeyUsage(extensions)

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        if not state_and_perms:
            return False

        csr = crypto_utils.load_certificate_request(self.path)

        return _check_subject(csr) and _check_extensions(csr) and _check_signature(csr)
Example #15
0
    def check(self, module, perms_required=True):
        """Ensure the resource is in its desired state."""
        state_and_perms = super(CertificateSigningRequest, self).check(module, perms_required)

        self.privatekey = crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)

        def _check_subject(csr):
            subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])), to_bytes(sub[1])) for sub in self.subject]
            current_subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])), to_bytes(sub[1])) for sub in csr.get_subject().get_components()]
            if not set(subject) == set(current_subject):
                return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions if ext.get_short_name() == b'subjectAltName'), '')
            altnames = [altname.strip() for altname in str(altnames_ext).split(',')]
            # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string
            # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004)
            altnames = [name if not name.startswith('IP Address:') else "IP:" + name.split(':', 1)[1] for name in altnames]
            if self.subjectAltName:
                if set(altnames) != set(self.subjectAltName) or altnames_ext.get_critical() != self.subjectAltName_critical:
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [ext for ext in extensions if ext.get_short_name() == extName]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip())) for usage in str(usages_ext[0]).split(',')]
                expected = [OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage)) for usage in expected]
                return set(current) == set(expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            return _check_keyUsage_(extensions, b'keyUsage', self.keyUsage, self.keyUsage_critical)

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage', self.extendedKeyUsage, self.extendedKeyUsage_critical)

        def _check_basicConstraints(extensions):
            return _check_keyUsage_(extensions, b'basicConstraints', self.basicConstraints, self.basicConstraints_critical)

        def _check_ocspMustStaple(extensions):
            oms_ext = [ext for ext in extensions if ext.get_short_name() == MUST_STAPLE_NAME and str(ext) == MUST_STAPLE_VALUE]
            if OpenSSL.SSL.OPENSSL_VERSION_NUMBER < 0x10100000:
                # Older versions of libssl don't know about OCSP Must Staple
                oms_ext.extend([ext for ext in extensions if ext.get_short_name() == b'UNDEF' and ext.get_data() == b'\x30\x03\x02\x01\x05'])
            if self.ocspMustStaple:
                return len(oms_ext) > 0 and oms_ext[0].get_critical() == self.ocspMustStaple_critical
            else:
                return len(oms_ext) == 0

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return (_check_subjectAltName(extensions) and _check_keyUsage(extensions) and
                    _check_extenededKeyUsage(extensions) and _check_basicConstraints(extensions) and
                    _check_ocspMustStaple(extensions))

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        if not state_and_perms:
            return False

        csr = crypto_utils.load_certificate_request(self.path)

        return _check_subject(csr) and _check_extensions(csr) and _check_signature(csr)
Example #16
0
    def check(self, module, perms_required=True):
        """Ensure the resource is in its desired state."""
        state_and_perms = super(CertificateSigningRequest,
                                self).check(module, perms_required)

        self.privatekey = crypto_utils.load_privatekey(
            self.privatekey_path, self.privatekey_passphrase)

        def _check_subject(csr):
            subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])),
                        to_bytes(sub[1])) for sub in self.subject]
            current_subject = [
                (OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])),
                 to_bytes(sub[1]))
                for sub in csr.get_subject().get_components()
            ]
            if not set(subject) == set(current_subject):
                return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions
                                 if ext.get_short_name() == b'subjectAltName'),
                                '')
            altnames = [
                altname.strip() for altname in str(altnames_ext).split(',')
            ]
            # apperently openssl returns 'IP address' not 'IP' as specifier when converting the subjectAltName to string
            # although it won't accept this specifier when generating the CSR. (https://github.com/openssl/openssl/issues/4004)
            altnames = [
                name if not name.startswith('IP Address:') else "IP:" +
                name.split(':', 1)[1] for name in altnames
            ]
            if self.subjectAltName:
                if set(altnames) != set(
                        self.subjectAltName) or altnames_ext.get_critical(
                        ) != self.subjectAltName_critical:
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [
                ext for ext in extensions if ext.get_short_name() == extName
            ]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip()))
                    for usage in str(usages_ext[0]).split(',')
                ]
                expected = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage))
                    for usage in expected
                ]
                return set(current) == set(
                    expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            return _check_keyUsage_(extensions, b'keyUsage', self.keyUsage,
                                    self.keyUsage_critical)

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage',
                                    self.extendedKeyUsage,
                                    self.extendedKeyUsage_critical)

        def _check_basicConstraints(extensions):
            return _check_keyUsage_(extensions, b'basicConstraints',
                                    self.basicConstraints,
                                    self.basicConstraints_critical)

        def _check_ocspMustStaple(extensions):
            oms_ext = [
                ext for ext in extensions
                if ext.get_short_name() == MUST_STAPLE_NAME
                and str(ext) == MUST_STAPLE_VALUE
            ]
            if OpenSSL.SSL.OPENSSL_VERSION_NUMBER < 0x10100000:
                # Older versions of libssl don't know about OCSP Must Staple
                oms_ext.extend([
                    ext for ext in extensions
                    if ext.get_short_name() == b'UNDEF'
                    and ext.get_data() == b'\x30\x03\x02\x01\x05'
                ])
            if self.ocspMustStaple:
                return len(oms_ext) > 0 and oms_ext[0].get_critical(
                ) == self.ocspMustStaple_critical
            else:
                return len(oms_ext) == 0

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return (_check_subjectAltName(extensions)
                    and _check_keyUsage(extensions)
                    and _check_extenededKeyUsage(extensions)
                    and _check_basicConstraints(extensions)
                    and _check_ocspMustStaple(extensions))

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        if not state_and_perms:
            return False

        csr = crypto_utils.load_certificate_request(self.path)

        return _check_subject(csr) and _check_extensions(
            csr) and _check_signature(csr)
Example #17
0
    def _check_csr(self):
        def _check_subject(csr):
            subject = [(OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])),
                        to_bytes(sub[1])) for sub in self.subject]
            current_subject = [
                (OpenSSL._util.lib.OBJ_txt2nid(to_bytes(sub[0])),
                 to_bytes(sub[1]))
                for sub in csr.get_subject().get_components()
            ]
            if not set(subject) == set(current_subject):
                return False

            return True

        def _check_subjectAltName(extensions):
            altnames_ext = next((ext for ext in extensions
                                 if ext.get_short_name() == b'subjectAltName'),
                                '')
            altnames = [
                self._normalize_san(altname.strip())
                for altname in to_text(altnames_ext,
                                       errors='surrogate_or_strict').split(',')
                if altname.strip()
            ]
            if self.subjectAltName:
                if (set(altnames) != set([
                        self._normalize_san(to_text(name))
                        for name in self.subjectAltName
                ]) or altnames_ext.get_critical() !=
                        self.subjectAltName_critical):
                    return False
            else:
                if altnames:
                    return False

            return True

        def _check_keyUsage_(extensions, extName, expected, critical):
            usages_ext = [
                ext for ext in extensions if ext.get_short_name() == extName
            ]
            if (not usages_ext and expected) or (usages_ext and not expected):
                return False
            elif not usages_ext and not expected:
                return True
            else:
                current = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage.strip()))
                    for usage in str(usages_ext[0]).split(',')
                ]
                expected = [
                    OpenSSL._util.lib.OBJ_txt2nid(to_bytes(usage))
                    for usage in expected
                ]
                return set(current) == set(
                    expected) and usages_ext[0].get_critical() == critical

        def _check_keyUsage(extensions):
            usages_ext = [
                ext for ext in extensions
                if ext.get_short_name() == b'keyUsage'
            ]
            if (not usages_ext and self.keyUsage) or (usages_ext
                                                      and not self.keyUsage):
                return False
            elif not usages_ext and not self.keyUsage:
                return True
            else:
                # OpenSSL._util.lib.OBJ_txt2nid() always returns 0 for all keyUsage values
                # (since keyUsage has a fixed bitfield for these values and is not extensible).
                # Therefore, we create an extension for the wanted values, and compare the
                # data of the extensions (which is the serialized bitfield).
                expected_ext = crypto.X509Extension(
                    b"keyUsage", False,
                    ', '.join(self.keyUsage).encode('ascii'))
                return usages_ext[0].get_data() == expected_ext.get_data(
                ) and usages_ext[0].get_critical() == self.keyUsage_critical

        def _check_extenededKeyUsage(extensions):
            return _check_keyUsage_(extensions, b'extendedKeyUsage',
                                    self.extendedKeyUsage,
                                    self.extendedKeyUsage_critical)

        def _check_basicConstraints(extensions):
            return _check_keyUsage_(extensions, b'basicConstraints',
                                    self.basicConstraints,
                                    self.basicConstraints_critical)

        def _check_ocspMustStaple(extensions):
            oms_ext = [
                ext for ext in extensions
                if to_bytes(ext.get_short_name()) == OPENSSL_MUST_STAPLE_NAME
                and to_bytes(ext) == OPENSSL_MUST_STAPLE_VALUE
            ]
            if OpenSSL.SSL.OPENSSL_VERSION_NUMBER < 0x10100000:
                # Older versions of libssl don't know about OCSP Must Staple
                oms_ext.extend([
                    ext for ext in extensions
                    if ext.get_short_name() == b'UNDEF'
                    and ext.get_data() == b'\x30\x03\x02\x01\x05'
                ])
            if self.ocspMustStaple:
                return len(oms_ext) > 0 and oms_ext[0].get_critical(
                ) == self.ocspMustStaple_critical
            else:
                return len(oms_ext) == 0

        def _check_extensions(csr):
            extensions = csr.get_extensions()
            return (_check_subjectAltName(extensions)
                    and _check_keyUsage(extensions)
                    and _check_extenededKeyUsage(extensions)
                    and _check_basicConstraints(extensions)
                    and _check_ocspMustStaple(extensions))

        def _check_signature(csr):
            try:
                return csr.verify(self.privatekey)
            except crypto.Error:
                return False

        try:
            csr = crypto_utils.load_certificate_request(self.path,
                                                        backend='pyopenssl')
        except Exception as dummy:
            return False

        return _check_subject(csr) and _check_extensions(
            csr) and _check_signature(csr)