class certmap(Object): """ virtual object for certmatch_map API """ takes_params = ( DNSNameParam( 'domain', label=_('Domain'), flags={'no_search'}, ), Str( 'uid*', label=_('User logins'), flags={'no_search'}, ), )
class BaseCertObject(Object): takes_params = ( Str( 'cacn?', cli_name='ca', default=IPA_CA_CN, autofill=True, label=_('Issuing CA'), doc=_('Name of issuing CA'), flags={'no_create', 'no_update', 'no_search'}, ), Bytes( 'certificate', validate_certificate, label=_("Certificate"), doc=_("Base-64 encoded certificate."), normalizer=x509.normalize_certificate, flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'subject', label=_('Subject'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_rfc822name*', label=_('Subject email address'), flags={'no_create', 'no_update', 'no_search'}, ), DNSNameParam( 'san_dnsname*', label=_('Subject DNS name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_x400address*', label=_('Subject X.400 address'), flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'san_directoryname*', label=_('Subject directory name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_edipartyname*', label=_('Subject EDI Party name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_uri*', label=_('Subject URI'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_ipaddress*', label=_('Subject IP Address'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_oid*', label=_('Subject OID'), flags={'no_create', 'no_update', 'no_search'}, ), Principal( 'san_other_upn*', label=_('Subject UPN'), flags={'no_create', 'no_update', 'no_search'}, ), Principal( 'san_other_kpn*', label=_('Subject Kerberos principal name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_other*', label=_('Subject Other Name'), flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'issuer', label=_('Issuer'), doc=_('Issuer DN'), flags={'no_create', 'no_update', 'no_search'}, ), DateTime( 'valid_not_before', label=_('Not Before'), flags={'no_create', 'no_update', 'no_search'}, ), DateTime( 'valid_not_after', label=_('Not After'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'md5_fingerprint', label=_('Fingerprint (MD5)'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'sha1_fingerprint', label=_('Fingerprint (SHA1)'), flags={'no_create', 'no_update', 'no_search'}, ), Int( 'serial_number', label=_('Serial number'), doc=_( 'Serial number in decimal or if prefixed with 0x in hexadecimal' ), normalizer=normalize_serial_number, flags={'no_create', 'no_update', 'no_search'}, ), Str( 'serial_number_hex', label=_('Serial number (hex)'), flags={'no_create', 'no_update', 'no_search'}, ), ) def _parse(self, obj, full=True): """Extract certificate-specific data into a result object. ``obj`` Result object containing certificate, into which extracted data will be inserted. ``full`` Whether to include all fields, or only the ones we guess people want to see most of the time. Also add recognised otherNames to the generic ``san_other`` attribute when ``True`` in addition to the specialised attribute. """ cert = obj.get('certificate') if cert is not None: cert = x509.load_certificate(cert) obj['subject'] = DN(unicode(cert.subject)) obj['issuer'] = DN(unicode(cert.issuer)) obj['serial_number'] = cert.serial_number if full: obj['valid_not_before'] = unicode(cert.valid_not_before_str) obj['valid_not_after'] = unicode(cert.valid_not_after_str) obj['md5_fingerprint'] = unicode( nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) obj['sha1_fingerprint'] = unicode( nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) try: ext_san = cert.get_extension(nss.SEC_OID_X509_SUBJECT_ALT_NAME) general_names = x509.decode_generalnames(ext_san.value) except KeyError: general_names = [] for name_type, _desc, name, der_name in general_names: try: self._add_san_attribute(obj, full, name_type, name, der_name) except Exception: # Invalid GeneralName (i.e. not a valid X.509 cert); # don't fail but log something about it root_logger.warning( "Encountered bad GeneralName; skipping", exc_info=True) serial_number = obj.get('serial_number') if serial_number is not None: obj['serial_number_hex'] = u'0x%X' % serial_number def _add_san_attribute(self, obj, full, name_type, name, der_name): name_type_map = { nss.certRFC822Name: 'san_rfc822name', nss.certDNSName: 'san_dnsname', nss.certX400Address: 'san_x400address', nss.certDirectoryName: 'san_directoryname', nss.certEDIPartyName: 'san_edipartyname', nss.certURI: 'san_uri', nss.certIPAddress: 'san_ipaddress', nss.certRegisterID: 'san_oid', (nss.certOtherName, x509.SAN_UPN): 'san_other_upn', (nss.certOtherName, x509.SAN_KRB5PRINCIPALNAME): 'san_other_kpn', } default_attrs = { 'san_rfc822name', 'san_dnsname', 'san_other_upn', 'san_other_kpn', } attr_name = name_type_map.get(name_type, 'san_other') if full or attr_name in default_attrs: if attr_name != 'san_other': name_formatted = name else: # display as "OID : b64(DER)" name_formatted = u'{}:{}'.format(name_type[1], base64.b64encode(der_name)) attr_value = self.params[attr_name].type(name_formatted) obj.setdefault(attr_name, []).append(attr_value) if full and attr_name.startswith('san_other_'): # also include known otherName in generic otherName attribute name_formatted = u'{}:{}'.format(name_type[1], base64.b64encode(der_name)) attr_value = self.params['san_other'].type(name_formatted) obj.setdefault('san_other', []).append(attr_value)
class BaseCertObject(Object): takes_params = ( Str( 'cacn?', cli_name='ca', default=IPA_CA_CN, autofill=True, label=_('Issuing CA'), doc=_('Name of issuing CA'), flags={'no_create', 'no_update', 'no_search'}, ), Bytes( 'certificate', validate_certificate, label=_("Certificate"), doc=_("Base-64 encoded certificate."), normalizer=x509.normalize_certificate, flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'subject', label=_('Subject'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_rfc822name*', label=_('Subject email address'), flags={'no_create', 'no_update', 'no_search'}, ), DNSNameParam( 'san_dnsname*', label=_('Subject DNS name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_x400address*', label=_('Subject X.400 address'), flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'san_directoryname*', label=_('Subject directory name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_edipartyname*', label=_('Subject EDI Party name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_uri*', label=_('Subject URI'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_ipaddress*', label=_('Subject IP Address'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_oid*', label=_('Subject OID'), flags={'no_create', 'no_update', 'no_search'}, ), Principal( 'san_other_upn*', label=_('Subject UPN'), flags={'no_create', 'no_update', 'no_search'}, ), Principal( 'san_other_kpn*', label=_('Subject Kerberos principal name'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'san_other*', label=_('Subject Other Name'), flags={'no_create', 'no_update', 'no_search'}, ), DNParam( 'issuer', label=_('Issuer'), doc=_('Issuer DN'), flags={'no_create', 'no_update', 'no_search'}, ), DateTime( 'valid_not_before', label=_('Not Before'), flags={'no_create', 'no_update', 'no_search'}, ), DateTime( 'valid_not_after', label=_('Not After'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'md5_fingerprint', label=_('Fingerprint (MD5)'), flags={'no_create', 'no_update', 'no_search'}, ), Str( 'sha1_fingerprint', label=_('Fingerprint (SHA1)'), flags={'no_create', 'no_update', 'no_search'}, ), Int( 'serial_number', label=_('Serial number'), doc=_( 'Serial number in decimal or if prefixed with 0x in hexadecimal' ), normalizer=normalize_serial_number, flags={'no_create', 'no_update', 'no_search'}, ), Str( 'serial_number_hex', label=_('Serial number (hex)'), flags={'no_create', 'no_update', 'no_search'}, ), ) def _parse(self, obj, full=True): """Extract certificate-specific data into a result object. ``obj`` Result object containing certificate, into which extracted data will be inserted. ``full`` Whether to include all fields, or only the ones we guess people want to see most of the time. Also add recognised otherNames to the generic ``san_other`` attribute when ``True`` in addition to the specialised attribute. """ if 'certificate' in obj: cert = x509.load_certificate(obj['certificate']) obj['subject'] = DN(cert.subject) obj['issuer'] = DN(cert.issuer) obj['serial_number'] = cert.serial obj['valid_not_before'] = x509.format_datetime( cert.not_valid_before) obj['valid_not_after'] = x509.format_datetime(cert.not_valid_after) if full: obj['md5_fingerprint'] = x509.to_hex_with_colons( cert.fingerprint(hashes.MD5())) obj['sha1_fingerprint'] = x509.to_hex_with_colons( cert.fingerprint(hashes.SHA1())) general_names = x509.process_othernames( x509.get_san_general_names(cert)) for gn in general_names: try: self._add_san_attribute(obj, full, gn) except Exception: # Invalid GeneralName (i.e. not a valid X.509 cert); # don't fail but log something about it root_logger.warning( "Encountered bad GeneralName; skipping", exc_info=True) serial_number = obj.get('serial_number') if serial_number is not None: obj['serial_number_hex'] = u'0x%X' % serial_number def _add_san_attribute(self, obj, full, gn): name_type_map = { cryptography.x509.RFC822Name: ('san_rfc822name', attrgetter('value')), cryptography.x509.DNSName: ('san_dnsname', attrgetter('value')), # cryptography.x509.???: 'san_x400address', cryptography.x509.DirectoryName: ('san_directoryname', lambda x: DN(x.value)), # cryptography.x509.???: 'san_edipartyname', cryptography.x509.UniformResourceIdentifier: ('san_uri', attrgetter('value')), cryptography.x509.IPAddress: ('san_ipaddress', attrgetter('value')), cryptography.x509.RegisteredID: ('san_oid', attrgetter('value.dotted_string')), cryptography.x509.OtherName: ('san_other', _format_othername), x509.UPN: ('san_other_upn', attrgetter('name')), x509.KRB5PrincipalName: ('san_other_kpn', attrgetter('name')), } default_attrs = { 'san_rfc822name', 'san_dnsname', 'san_other_upn', 'san_other_kpn', } if type(gn) not in name_type_map: return attr_name, format_name = name_type_map[type(gn)] if full or attr_name in default_attrs: attr_value = self.params[attr_name].type(format_name(gn)) obj.setdefault(attr_name, []).append(attr_value) if full and attr_name.startswith('san_other_'): # also include known otherName in generic otherName attribute attr_value = self.params['san_other'].type(_format_othername(gn)) obj.setdefault('san_other', []).append(attr_value)
class certmaprule(LDAPObject): """ Certificate Identity Mapping Rules """ label = _('Certificate Identity Mapping Rules') label_singular = _('Certificate Identity Mapping Rule') object_name = _('Certificate Identity Mapping Rule') object_name_plural = _('Certificate Identity Mapping Rules') object_class = ['ipacertmaprule'] container_dn = api.env.container_certmaprules default_attributes = [ 'cn', 'description', 'ipacertmapmaprule', 'ipacertmapmatchrule', 'associateddomain', 'ipacertmappriority', 'ipaenabledflag' ] search_attributes = [ 'cn', 'description', 'ipacertmapmaprule', 'ipacertmapmatchrule', 'associateddomain', 'ipacertmappriority', 'ipaenabledflag' ] takes_params = ( Str( 'cn', cli_name='rulename', primary_key=True, label=_('Rule name'), doc=_('Certificate Identity Mapping Rule name'), ), Str( 'description?', cli_name='desc', label=_('Description'), doc=_('Certificate Identity Mapping Rule description'), ), Str( 'ipacertmapmaprule?', cli_name='maprule', label=_('Mapping rule'), doc=_('Rule used to map the certificate with a user entry'), ), Str( 'ipacertmapmatchrule?', cli_name='matchrule', label=_('Matching rule'), doc=_('Rule used to check if a certificate can be used for' ' authentication'), ), DNSNameParam( 'associateddomain*', cli_name='domain', label=_('Domain name'), doc=_('Domain where the user entry will be searched'), ), Int( 'ipacertmappriority?', cli_name='priority', label=_('Priority'), doc=_('Priority of the rule (higher number means lower priority'), minvalue=0, ), Flag('ipaenabledflag?', label=_('Enabled'), flags=['no_option'], default=True), ) permission_filter_objectclasses = ['ipacertmaprule'] managed_permissions = { 'System: Add Certmap Rules': { 'replaces_global_anonymous_aci': True, 'ipapermright': {'add'}, 'default_privileges': {'Certificate Identity Mapping Administrators'}, }, 'System: Read Certmap Rules': { 'replaces_global_anonymous_aci': True, 'ipapermbindruletype': 'all', 'ipapermright': {'read', 'search', 'compare'}, 'ipapermdefaultattr': { 'objectclass', 'cn', 'description', 'ipacertmapmaprule', 'ipacertmapmatchrule', 'associateddomain', 'ipacertmappriority', 'ipaenabledflag', }, }, 'System: Delete Certmap Rules': { 'replaces_global_anonymous_aci': True, 'ipapermright': {'delete'}, 'default_privileges': {'Certificate Identity Mapping Administrators'}, }, 'System: Modify Certmap Rules': { 'replaces_global_anonymous_aci': True, 'ipapermright': {'write'}, 'ipapermdefaultattr': { 'objectclass', 'cn', 'description', 'ipacertmapmaprule', 'ipacertmapmatchrule', 'associateddomain', 'ipacertmappriority', 'ipaenabledflag', }, 'default_privileges': {'Certificate Identity Mapping Administrators'}, }, }