def generate(self, module): """Generate PKCS#12 file archive.""" self.pkcs12 = crypto.PKCS12() if self.other_certificates: other_certs = [ crypto_utils.load_certificate(other_cert) for other_cert in self.other_certificates ] self.pkcs12.set_ca_certificates(other_certs) if self.certificate_path: self.pkcs12.set_certificate( crypto_utils.load_certificate(self.certificate_path)) if self.friendly_name: self.pkcs12.set_friendlyname(to_bytes(self.friendly_name)) if self.privatekey_path: try: self.pkcs12.set_privatekey( crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)) except crypto_utils.OpenSSLBadPassphraseError as exc: raise PkcsError(exc) return self.pkcs12.export(self.passphrase, self.iter_size, self.maciter_size)
def generate(self, module): """Generate PKCS#12 file archive.""" self.pkcs12 = crypto.PKCS12() if self.ca_certificates: ca_certs = [crypto_utils.load_certificate(ca_cert) for ca_cert in self.ca_certificates] self.pkcs12.set_ca_certificates(ca_certs) if self.certificate_path: self.pkcs12.set_certificate(crypto_utils.load_certificate( self.certificate_path)) if self.friendly_name: self.pkcs12.set_friendlyname(to_bytes(self.friendly_name)) if self.privatekey_path: try: self.pkcs12.set_privatekey(crypto_utils.load_privatekey( self.privatekey_path, self.privatekey_passphrase) ) except crypto_utils.OpenSSLBadPassphraseError as exc: raise PkcsError(exc) if self.backup: self.backup_file = module.backup_local(self.path) crypto_utils.write_file( module, self.pkcs12.export(self.passphrase, self.iter_size, self.maciter_size), 0o600 )
def generate(self, module): """Generate PKCS#12 file archive.""" self.pkcs12 = crypto.PKCS12() if self.ca_certificates: ca_certs = [ crypto_utils.load_certificate( os.path.expanduser(os.path.expandvars(ca_cert))) for ca_cert in self.ca_certificates ] self.pkcs12.set_ca_certificates(ca_certs) if self.certificate_path: self.pkcs12.set_certificate( crypto_utils.load_certificate(self.certificate_path)) if self.friendly_name: self.pkcs12.set_friendlyname(to_bytes(self.friendly_name)) if self.privatekey_path: self.pkcs12.set_privatekey( crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)) crypto_utils.write_file( module, self.pkcs12.export(self.passphrase, self.iter_size, self.maciter_size), 0o600)
def get_info(self): result = dict() self.cert = crypto_utils.load_certificate(self.path, backend=self.backend) result['signature_algorithm'] = self._get_signature_algorithm() result['subject'] = self._get_subject() result['issuer'] = self._get_issuer() result['version'] = self._get_version() 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() not_before = self._get_not_before() not_after = self._get_not_after() result['not_before'] = not_before.strftime(TIMESTAMP_FORMAT) result['not_after'] = not_after.strftime(TIMESTAMP_FORMAT) result['expired'] = not_after < datetime.datetime.utcnow() result['valid_at'] = dict() if self.valid_at: for k, v in self.valid_at.items(): result['valid_at'][k] = not_before <= v <= not_after 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['serial_number'] = self._get_serial_number() result['extensions_by_oid'] = self._get_all_extensions() return result
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 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() return True
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 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() return True
def get_info(self): result = dict() self.cert = crypto_utils.load_certificate(self.path, backend=self.backend) result['signature_algorithm'] = self._get_signature_algorithm() subject = self._get_subject_ordered() issuer = self._get_issuer_ordered() result['subject'] = dict() for k, v in subject: result['subject'][k] = v result['subject_ordered'] = subject result['issuer'] = dict() for k, v in issuer: result['issuer'][k] = v result['issuer_ordered'] = issuer result['version'] = self._get_version() 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() not_before = self._get_not_before() not_after = self._get_not_after() result['not_before'] = not_before.strftime(TIMESTAMP_FORMAT) result['not_after'] = not_after.strftime(TIMESTAMP_FORMAT) result['expired'] = not_after < datetime.datetime.utcnow() result['valid_at'] = dict() if self.valid_at: for k, v in self.valid_at.items(): result['valid_at'][k] = not_before <= v <= not_after 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['serial_number'] = self._get_serial_number() result['extensions_by_oid'] = self._get_all_extensions() result['ocsp_uri'] = self._get_ocsp_uri() return result
def generate(self, module): """Generate PKCS#12 file archive.""" self.pkcs12 = crypto.PKCS12() try: self.remove(module) except PkcsError as exc: module.fail_json(msg=to_native(exc)) if self.ca_certificates: ca_certs = [ crypto_utils.load_certificate(ca_cert) for ca_cert in self.ca_certificates ] self.pkcs12.set_ca_certificates(ca_certs) if self.certificate_path: self.pkcs12.set_certificate( crypto_utils.load_certificate(self.certificate_path)) if self.friendly_name: self.pkcs12.set_friendlyname(to_bytes(self.friendly_name)) if self.privatekey_path: try: self.pkcs12.set_privatekey( crypto_utils.load_privatekey(self.privatekey_path, self.privatekey_passphrase)) except crypto_utils.OpenSSLBadPassphraseError as exc: raise PkcsError(exc) try: pkcs12_file = os.open(self.path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, self.mode) os.write( pkcs12_file, self.pkcs12.export(self.passphrase, self.iter_size, self.maciter_size)) os.close(pkcs12_file) except (IOError, OSError) as exc: self.remove(module) raise PkcsError(exc)
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
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
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 )
def __init__(self, module): self.path = module.params['path'] self.full_chain_path = module.params['full_chain_path'] self.force = module.params['force'] self.backup = module.params['backup'] self.request_type = module.params['request_type'] self.csr = module.params['csr'] # All return values self.changed = False self.filename = None self.tracking_id = None self.cert_status = None self.serial_number = None self.cert_days = None self.cert_details = None self.backup_file = None self.backup_full_chain_file = None self.cert = None self.ecs_client = None if self.path and os.path.exists(self.path): try: self.cert = crypto_utils.load_certificate( self.path, backend='cryptography') except Exception as dummy: self.cert = None # Instantiate the ECS client and then try a no-op connection to verify credentials are valid try: self.ecs_client = ECSClient( entrust_api_user=module.params['entrust_api_user'], entrust_api_key=module.params['entrust_api_key'], entrust_api_cert=module.params['entrust_api_client_cert_path'], entrust_api_cert_key=module. params['entrust_api_client_cert_key_path'], entrust_api_specification_path=module. params['entrust_api_specification_path']) except SessionConfigurationException as e: module.fail_json( msg='Failed to initialize Entrust Provider: {0}'.format( to_native(e))) try: self.ecs_client.GetAppVersion() except RestOperationException as e: module.fail_json( msg= 'Please verify credential information. Received exception when testing ECS connection: {0}' .format(to_native(e.message)))
def assertonly(self): self.cert = crypto_utils.load_certificate(self.path) def _validate_signature_algorithms(): if self.signature_algorithms: if self.cert.get_signature_algorithm( ) not in self.signature_algorithms: self.message.append( 'Invalid signature algorithm (got %s, expected one of %s)' % (self.cert.get_signature_algorithm(), self.signature_algorithms)) def _validate_subject(): if self.subject: cert_subject = self.cert.get_subject().get_components() diff = [ item for item in self.subject.items() if item not in cert_subject ] if diff: self.message.append( 'Invalid subject component (got %s, expected all of %s to be present)' % (cert_subject, self.subject.items())) def _validate_issuer(): if self.issuer: cert_issuer = self.cert.get_issuer().get_components() diff = [ item for item in self.issuer.items() if item not in cert_issuer ] if diff: self.message.append( 'Invalid issuer component (got %s, expected all of %s to be present)' % (cert_issuer, self.issuer.items())) def _validate_has_expired(): if self.has_expired: if self.has_expired != self.cert.has_expired(): self.message.append( 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (self.cert.has_expired(), self.has_expired)) def _validate_version(): if self.version: # Version numbers in certs are off by one: # v1: 0, v2: 1, v3: 2 ... if self.version != self.cert.get_version() + 1: self.message.append( 'Invalid certificate version number (got %s, expected %s)' % (self.cert.get_version() + 1, self.version)) def _validate_keyUsage(): if self.keyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'keyUsage': keyUsage = [ crypto_utils.keyUsageLong.get(keyUsage, keyUsage) for keyUsage in self.keyUsage ] if (not self.keyUsage_strict and not all(x in str(extension).split(', ') for x in keyUsage)) or \ (self.keyUsage_strict and not set(keyUsage) == set(str(extension).split(', '))): self.message.append( 'Invalid keyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), keyUsage)) def _validate_extendedKeyUsage(): if self.extendedKeyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'extendedKeyUsage': extKeyUsage = [ crypto_utils.extendedKeyUsageLong.get( keyUsage, keyUsage) for keyUsage in self.extendedKeyUsage ] if (not self.extendedKeyUsage_strict and not all(x in str(extension).split(', ') for x in extKeyUsage)) or \ (self.extendedKeyUsage_strict and not set(extKeyUsage) == set(str(extension).split(', '))): self.message.append( 'Invalid extendedKeyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), extKeyUsage)) def _validate_subjectAltName(): if self.subjectAltName: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'subjectAltName': l_subjectAltName = [ altname.replace('IP', 'IP Address') for altname in self.subjectAltName ] if (not self.subjectAltName_strict and not all(x in str(extension).split(', ') for x in l_subjectAltName)) or \ (self.subjectAltName_strict and not set(l_subjectAltName) == set(str(extension).split(', '))): self.message.append( 'Invalid subjectAltName component (got %s, expected all of %s to be present)' % (str(extension).split(', '), l_subjectAltName)) def _validate_notBefore(): if self.notBefore: if self.cert.get_notBefore() != self.notBefore: self.message.append( 'Invalid notBefore component (got %s, expected %s to be present)' % (self.cert.get_notBefore(), self.notBefore)) def _validate_notAfter(): if self.notAfter: if self.cert.get_notAfter() != self.notAfter: self.message.append( 'Invalid notAfter component (got %s, expected %s to be present)' % (self.cert.get_notAfter(), self.notAfter)) def _validate_valid_at(): if self.valid_at: if not (self.valid_at >= self.cert.get_notBefore() and self.valid_at <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.valid_at, self.cert.get_notBefore(), self.cert.get_notAfter())) def _validate_invalid_at(): if self.invalid_at: if not (self.invalid_at <= self.cert.get_notBefore() or self.invalid_at >= self.cert.get_notAfter()): self.message.append( 'Certificate is not invalid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.invalid_at, self.cert.get_notBefore(), self.cert.get_notAfter())) def _validate_valid_in(): if self.valid_in: valid_in_date = datetime.datetime.utcnow( ) + datetime.timedelta(seconds=self.valid_in) valid_in_date = valid_in_date.strftime('%Y%m%d%H%M%SZ') if not (valid_in_date >= self.cert.get_notBefore() and valid_in_date <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid in %s seconds from now (%s) - notBefore: %s - notAfter: %s' % (self.valid_in, valid_in_date, self.cert.get_notBefore(), self.cert.get_notAfter())) for validation in [ 'signature_algorithms', 'subject', 'issuer', 'has_expired', 'version', 'keyUsage', 'extendedKeyUsage', 'subjectAltName', 'notBefore', 'notAfter', 'valid_at', 'invalid_at', 'valid_in' ]: f_name = locals()['_validate_%s' % validation] f_name()
def assertonly(self): self.cert = crypto_utils.load_certificate(self.path) def _validate_signature_algorithms(): if self.signature_algorithms: if self.cert.get_signature_algorithm( ) not in self.signature_algorithms: self.message.append( 'Invalid signature algorithm (got %s, expected one of %s)' % (self.cert.get_signature_algorithm(), self.signature_algorithms)) def _validate_subject(): if self.subject: expected_subject = [(OpenSSL._util.lib.OBJ_txt2nid(sub[0]), sub[1]) for sub in self.subject] cert_subject = self.cert.get_subject().get_components() current_subject = [(OpenSSL._util.lib.OBJ_txt2nid(sub[0]), sub[1]) for sub in cert_subject] if (not self.subject_strict and not all(x in current_subject for x in expected_subject)) or \ (self.subject_strict and not set(expected_subject) == set(current_subject)): self.message.append( 'Invalid subject component (got %s, expected all of %s to be present)' % (cert_subject, self.subject)) def _validate_issuer(): if self.issuer: expected_issuer = [(OpenSSL._util.lib.OBJ_txt2nid(iss[0]), iss[1]) for iss in self.issuer] cert_issuer = self.cert.get_issuer().get_components() current_issuer = [(OpenSSL._util.lib.OBJ_txt2nid(iss[0]), iss[1]) for iss in cert_issuer] if (not self.issuer_strict and not all(x in current_issuer for x in expected_issuer)) or \ (self.issuer_strict and not set(expected_issuer) == set(current_issuer)): self.message.append( 'Invalid issuer component (got %s, expected all of %s to be present)' % (cert_issuer, self.issuer)) def _validate_has_expired(): # The following 3 lines are the same as the current PyOpenSSL code for cert.has_expired(). # Older version of PyOpenSSL have a buggy implementation, # to avoid issues with those we added the code from a more recent release here. time_string = to_native(self.cert.get_notAfter()) not_after = datetime.datetime.strptime(time_string, "%Y%m%d%H%M%SZ") cert_expired = not_after < datetime.datetime.utcnow() if self.has_expired != cert_expired: self.message.append( 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (cert_expired, self.has_expired)) def _validate_version(): if self.version: # Version numbers in certs are off by one: # v1: 0, v2: 1, v3: 2 ... if self.version != self.cert.get_version() + 1: self.message.append( 'Invalid certificate version number (got %s, expected %s)' % (self.cert.get_version() + 1, self.version)) def _validate_keyUsage(): if self.keyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'keyUsage': keyUsage = [ OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.keyUsage ] current_ku = [ OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in to_bytes( extension, errors='surrogate_or_strict').split( b',') ] if (not self.keyUsage_strict and not all(x in current_ku for x in keyUsage)) or \ (self.keyUsage_strict and not set(keyUsage) == set(current_ku)): self.message.append( 'Invalid keyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), self.keyUsage)) def _validate_extendedKeyUsage(): if self.extendedKeyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'extendedKeyUsage': extKeyUsage = [ OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.extendedKeyUsage ] current_xku = [ OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in to_bytes( extension, errors='surrogate_or_strict').split( b',') ] if (not self.extendedKeyUsage_strict and not all(x in current_xku for x in extKeyUsage)) or \ (self.extendedKeyUsage_strict and not set(extKeyUsage) == set(current_xku)): self.message.append( 'Invalid extendedKeyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), self.extendedKeyUsage)) def _validate_subjectAltName(): if self.subjectAltName: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'subjectAltName': l_altnames = [ altname.replace(b'IP Address', b'IP') for altname in to_bytes( extension, errors='surrogate_or_strict').split( b', ') ] if (not self.subjectAltName_strict and not all(x in l_altnames for x in self.subjectAltName)) or \ (self.subjectAltName_strict and not set(self.subjectAltName) == set(l_altnames)): self.message.append( 'Invalid subjectAltName component (got %s, expected all of %s to be present)' % (l_altnames, self.subjectAltName)) def _validate_notBefore(): if self.notBefore: if self.cert.get_notBefore() != self.notBefore: self.message.append( 'Invalid notBefore component (got %s, expected %s to be present)' % (self.cert.get_notBefore(), self.notBefore)) def _validate_notAfter(): if self.notAfter: if self.cert.get_notAfter() != self.notAfter: self.message.append( 'Invalid notAfter component (got %s, expected %s to be present)' % (self.cert.get_notAfter(), self.notAfter)) def _validate_valid_at(): if self.valid_at: if not (self.cert.get_notBefore() <= self.valid_at <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.valid_at, self.cert.get_notBefore(), self.cert.get_notAfter())) def _validate_invalid_at(): if self.invalid_at: if not (self.invalid_at <= self.cert.get_notBefore() or self.invalid_at >= self.cert.get_notAfter()): self.message.append( 'Certificate is not invalid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.invalid_at, self.cert.get_notBefore(), self.cert.get_notAfter())) def _validate_valid_in(): if self.valid_in: if not self.valid_in.startswith( "+") and not self.valid_in.startswith("-"): try: int(self.valid_in) except ValueError: raise CertificateError( 'The supplied value for "valid_in" (%s) is not an integer or a valid timespec' % self.valid_in) self.valid_in = "+" + self.valid_in + "s" valid_in_asn1 = self.get_relative_time_option( self.valid_in, "valid_in") valid_in_date = to_bytes(valid_in_asn1, errors='surrogate_or_strict') if not (self.cert.get_notBefore() <= valid_in_date <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid in %s from now (that would be %s) - notBefore: %s - notAfter: %s' % (self.valid_in, valid_in_date, self.cert.get_notBefore(), self.cert.get_notAfter())) for validation in [ 'signature_algorithms', 'subject', 'issuer', 'has_expired', 'version', 'keyUsage', 'extendedKeyUsage', 'subjectAltName', 'notBefore', 'notAfter', 'valid_at', 'invalid_at', 'valid_in' ]: f_name = locals()['_validate_%s' % validation] f_name()
def assertonly(self): self.cert = crypto_utils.load_certificate(self.path) def _validate_signature_algorithms(): if self.signature_algorithms: if self.cert.get_signature_algorithm() not in self.signature_algorithms: self.message.append( 'Invalid signature algorithm (got %s, expected one of %s)' % (self.cert.get_signature_algorithm(), self.signature_algorithms) ) def _validate_subject(): if self.subject: cert_subject = self.cert.get_subject().get_components() diff = [item for item in self.subject.items() if item not in cert_subject] if diff: self.message.append( 'Invalid subject component (got %s, expected all of %s to be present)' % (cert_subject, self.subject.items()) ) def _validate_issuer(): if self.issuer: cert_issuer = self.cert.get_issuer().get_components() diff = [item for item in self.issuer.items() if item not in cert_issuer] if diff: self.message.append( 'Invalid issuer component (got %s, expected all of %s to be present)' % (cert_issuer, self.issuer.items()) ) def _validate_has_expired(): if self.has_expired: if self.has_expired != self.cert.has_expired(): self.message.append( 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (self.cert.has_expired(), self.has_expired) ) def _validate_version(): if self.version: # Version numbers in certs are off by one: # v1: 0, v2: 1, v3: 2 ... if self.version != self.cert.get_version() + 1: self.message.append( 'Invalid certificate version number (got %s, expected %s)' % (self.cert.get_version() + 1, self.version) ) def _validate_keyUsage(): if self.keyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'keyUsage': keyUsage = [OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.keyUsage] current_ku = [OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in str(extension).split(',')] if (not self.keyUsage_strict and not all(x in current_ku for x in keyUsage)) or \ (self.keyUsage_strict and not set(keyUsage) == set(current_ku)): self.message.append( 'Invalid keyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), keyUsage) ) def _validate_extendedKeyUsage(): if self.extendedKeyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'extendedKeyUsage': extKeyUsage = [OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.extendedKeyUsage] current_xku = [OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in str(extension).split(',')] if (not self.extendedKeyUsage_strict and not all(x in current_xku for x in extKeyUsage)) or \ (self.extendedKeyUsage_strict and not set(extKeyUsage) == set(current_xku)): self.message.append( 'Invalid extendedKeyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), extKeyUsage) ) def _validate_subjectAltName(): if self.subjectAltName: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == 'subjectAltName': l_altnames = [altname.replace('IP Address', 'IP') for altname in str(extension).split(', ')] if (not self.subjectAltName_strict and not all(x in l_altnames for x in self.subjectAltName)) or \ (self.subjectAltName_strict and not set(self.subjectAltName) == set(l_altnames)): self.message.append( 'Invalid subjectAltName component (got %s, expected all of %s to be present)' % (l_altnames, self.subjectAltName) ) def _validate_notBefore(): if self.notBefore: if self.cert.get_notBefore() != self.notBefore: self.message.append( 'Invalid notBefore component (got %s, expected %s to be present)' % (self.cert.get_notBefore(), self.notBefore) ) def _validate_notAfter(): if self.notAfter: if self.cert.get_notAfter() != self.notAfter: self.message.append( 'Invalid notAfter component (got %s, expected %s to be present)' % (self.cert.get_notAfter(), self.notAfter) ) def _validate_valid_at(): if self.valid_at: if not (self.valid_at >= self.cert.get_notBefore() and self.valid_at <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.valid_at, self.cert.get_notBefore(), self.cert.get_notAfter()) ) def _validate_invalid_at(): if self.invalid_at: if not (self.invalid_at <= self.cert.get_notBefore() or self.invalid_at >= self.cert.get_notAfter()): self.message.append( 'Certificate is not invalid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.invalid_at, self.cert.get_notBefore(), self.cert.get_notAfter()) ) def _validate_valid_in(): if self.valid_in: valid_in_date = datetime.datetime.utcnow() + datetime.timedelta(seconds=self.valid_in) valid_in_date = valid_in_date.strftime('%Y%m%d%H%M%SZ') if not (valid_in_date >= self.cert.get_notBefore() and valid_in_date <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid in %s seconds from now (%s) - notBefore: %s - notAfter: %s' % (self.valid_in, valid_in_date, self.cert.get_notBefore(), self.cert.get_notAfter()) ) for validation in ['signature_algorithms', 'subject', 'issuer', 'has_expired', 'version', 'keyUsage', 'extendedKeyUsage', 'subjectAltName', 'notBefore', 'notAfter', 'valid_at', 'invalid_at', 'valid_in']: f_name = locals()['_validate_%s' % validation] f_name()
def assertonly(self): self.cert = crypto_utils.load_certificate(self.path) def _validate_signature_algorithms(): if self.signature_algorithms: if self.cert.get_signature_algorithm() not in self.signature_algorithms: self.message.append( 'Invalid signature algorithm (got %s, expected one of %s)' % (self.cert.get_signature_algorithm(), self.signature_algorithms) ) def _validate_subject(): if self.subject: expected_subject = [(OpenSSL._util.lib.OBJ_txt2nid(sub[0]), sub[1]) for sub in self.subject] cert_subject = self.cert.get_subject().get_components() current_subject = [(OpenSSL._util.lib.OBJ_txt2nid(sub[0]), sub[1]) for sub in cert_subject] if (not self.subject_strict and not all(x in current_subject for x in expected_subject)) or \ (self.subject_strict and not set(expected_subject) == set(current_subject)): self.message.append( 'Invalid subject component (got %s, expected all of %s to be present)' % (cert_subject, self.subject) ) def _validate_issuer(): if self.issuer: expected_issuer = [(OpenSSL._util.lib.OBJ_txt2nid(iss[0]), iss[1]) for iss in self.issuer] cert_issuer = self.cert.get_issuer().get_components() current_issuer = [(OpenSSL._util.lib.OBJ_txt2nid(iss[0]), iss[1]) for iss in cert_issuer] if (not self.issuer_strict and not all(x in current_issuer for x in expected_issuer)) or \ (self.issuer_strict and not set(expected_issuer) == set(current_issuer)): self.message.append( 'Invalid issuer component (got %s, expected all of %s to be present)' % (cert_issuer, self.issuer) ) def _validate_has_expired(): if self.has_expired: if self.has_expired != self.cert.has_expired(): self.message.append( 'Certificate expiration check failed (certificate expiration is %s, expected %s)' % (self.cert.has_expired(), self.has_expired) ) def _validate_version(): if self.version: # Version numbers in certs are off by one: # v1: 0, v2: 1, v3: 2 ... if self.version != self.cert.get_version() + 1: self.message.append( 'Invalid certificate version number (got %s, expected %s)' % (self.cert.get_version() + 1, self.version) ) def _validate_keyUsage(): if self.keyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'keyUsage': keyUsage = [OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.keyUsage] current_ku = [OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in to_bytes(extension, errors='surrogate_or_strict').split(b',')] if (not self.keyUsage_strict and not all(x in current_ku for x in keyUsage)) or \ (self.keyUsage_strict and not set(keyUsage) == set(current_ku)): self.message.append( 'Invalid keyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), self.keyUsage) ) def _validate_extendedKeyUsage(): if self.extendedKeyUsage: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'extendedKeyUsage': extKeyUsage = [OpenSSL._util.lib.OBJ_txt2nid(keyUsage) for keyUsage in self.extendedKeyUsage] current_xku = [OpenSSL._util.lib.OBJ_txt2nid(usage.strip()) for usage in to_bytes(extension, errors='surrogate_or_strict').split(b',')] if (not self.extendedKeyUsage_strict and not all(x in current_xku for x in extKeyUsage)) or \ (self.extendedKeyUsage_strict and not set(extKeyUsage) == set(current_xku)): self.message.append( 'Invalid extendedKeyUsage component (got %s, expected all of %s to be present)' % (str(extension).split(', '), self.extendedKeyUsage) ) def _validate_subjectAltName(): if self.subjectAltName: for extension_idx in range(0, self.cert.get_extension_count()): extension = self.cert.get_extension(extension_idx) if extension.get_short_name() == b'subjectAltName': l_altnames = [altname.replace(b'IP Address', b'IP') for altname in to_bytes(extension, errors='surrogate_or_strict').split(b', ')] if (not self.subjectAltName_strict and not all(x in l_altnames for x in self.subjectAltName)) or \ (self.subjectAltName_strict and not set(self.subjectAltName) == set(l_altnames)): self.message.append( 'Invalid subjectAltName component (got %s, expected all of %s to be present)' % (l_altnames, self.subjectAltName) ) def _validate_notBefore(): if self.notBefore: if self.cert.get_notBefore() != self.notBefore: self.message.append( 'Invalid notBefore component (got %s, expected %s to be present)' % (self.cert.get_notBefore(), self.notBefore) ) def _validate_notAfter(): if self.notAfter: if self.cert.get_notAfter() != self.notAfter: self.message.append( 'Invalid notAfter component (got %s, expected %s to be present)' % (self.cert.get_notAfter(), self.notAfter) ) def _validate_valid_at(): if self.valid_at: if not (self.valid_at >= self.cert.get_notBefore() and self.valid_at <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.valid_at, self.cert.get_notBefore(), self.cert.get_notAfter()) ) def _validate_invalid_at(): if self.invalid_at: if not (self.invalid_at <= self.cert.get_notBefore() or self.invalid_at >= self.cert.get_notAfter()): self.message.append( 'Certificate is not invalid for the specified date (%s) - notBefore: %s - notAfter: %s' % (self.invalid_at, self.cert.get_notBefore(), self.cert.get_notAfter()) ) def _validate_valid_in(): if self.valid_in: valid_in_date = datetime.datetime.utcnow() + datetime.timedelta(seconds=self.valid_in) valid_in_date = valid_in_date.strftime('%Y%m%d%H%M%SZ') if not (valid_in_date >= self.cert.get_notBefore() and valid_in_date <= self.cert.get_notAfter()): self.message.append( 'Certificate is not valid in %s seconds from now (%s) - notBefore: %s - notAfter: %s' % (self.valid_in, valid_in_date, self.cert.get_notBefore(), self.cert.get_notAfter()) ) for validation in ['signature_algorithms', 'subject', 'issuer', 'has_expired', 'version', 'keyUsage', 'extendedKeyUsage', 'subjectAltName', 'notBefore', 'notAfter', 'valid_at', 'invalid_at', 'valid_in']: f_name = locals()['_validate_%s' % validation] f_name()
def __init__(self, module): super(CRL, self).__init__( module.params['path'], module.params['state'], module.params['force'], module.check_mode ) self.update = module.params['mode'] == 'update' self.ignore_timestamps = module.params['ignore_timestamps'] self.return_content = module.params['return_content'] self.crl_content = None self.privatekey_path = module.params['privatekey_path'] self.privatekey_content = module.params['privatekey_content'] if self.privatekey_content is not None: self.privatekey_content = self.privatekey_content.encode('utf-8') self.privatekey_passphrase = module.params['privatekey_passphrase'] self.issuer = crypto_utils.parse_name_field(module.params['issuer']) self.issuer = [(entry[0], entry[1]) for entry in self.issuer if entry[1]] self.last_update = crypto_utils.get_relative_time_option(module.params['last_update'], 'last_update') self.next_update = crypto_utils.get_relative_time_option(module.params['next_update'], 'next_update') self.digest = crypto_utils.select_message_digest(module.params['digest']) if self.digest is None: raise CRLError('The digest "{0}" is not supported'.format(module.params['digest'])) self.revoked_certificates = [] for i, rc in enumerate(module.params['revoked_certificates']): result = { 'serial_number': None, 'revocation_date': None, 'issuer': None, 'issuer_critical': False, 'reason': None, 'reason_critical': False, 'invalidity_date': None, 'invalidity_date_critical': False, } path_prefix = 'revoked_certificates[{0}].'.format(i) if rc['path'] is not None or rc['content'] is not None: # Load certificate from file or content try: if rc['content'] is not None: rc['content'] = rc['content'].encode('utf-8') cert = crypto_utils.load_certificate(rc['path'], content=rc['content'], backend='cryptography') try: result['serial_number'] = cert.serial_number except AttributeError: # The property was called "serial" before cryptography 1.4 result['serial_number'] = cert.serial except crypto_utils.OpenSSLObjectError as e: if rc['content'] is not None: module.fail_json( msg='Cannot parse certificate from {0}content: {1}'.format(path_prefix, to_native(e)) ) else: module.fail_json( msg='Cannot read certificate "{1}" from {0}path: {2}'.format(path_prefix, rc['path'], to_native(e)) ) else: # Specify serial_number (and potentially issuer) directly result['serial_number'] = rc['serial_number'] # All other options if rc['issuer']: result['issuer'] = [crypto_utils.cryptography_get_name(issuer) for issuer in rc['issuer']] result['issuer_critical'] = rc['issuer_critical'] result['revocation_date'] = crypto_utils.get_relative_time_option( rc['revocation_date'], path_prefix + 'revocation_date' ) if rc['reason']: result['reason'] = crypto_utils.REVOCATION_REASON_MAP[rc['reason']] result['reason_critical'] = rc['reason_critical'] if rc['invalidity_date']: result['invalidity_date'] = crypto_utils.get_relative_time_option( rc['invalidity_date'], path_prefix + 'invalidity_date' ) result['invalidity_date_critical'] = rc['invalidity_date_critical'] self.revoked_certificates.append(result) self.module = module self.backup = module.params['backup'] self.backup_file = None try: self.privatekey = crypto_utils.load_privatekey( path=self.privatekey_path, content=self.privatekey_content, passphrase=self.privatekey_passphrase, backend='cryptography' ) except crypto_utils.OpenSSLBadPassphraseError as exc: raise CRLError(exc) self.crl = None try: with open(self.path, 'rb') as f: data = f.read() self.crl = x509.load_pem_x509_crl(data, default_backend()) if self.return_content: self.crl_content = data except Exception as dummy: self.crl_content = None