def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() assert nulldn.ldap_text() == nulldn.x500_text() # reverse a DN with a single RDN assert self.dn1.ldap_text() == self.dn1.x500_text() # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) assert dn3_rev.ldap_text() == dn3_x500 # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): assert longdn_rev[i] == self.base_container_dn[l - 1 - i]
def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() self.assertEqual(nulldn.ldap_text(), nulldn.x500_text()) # reverse a DN with a single RDN self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text()) # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) self.assertEqual(dn3_rev.ldap_text(), dn3_x500) # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): self.assertEqual(longdn_rev[i], self.base_container_dn[l - 1 - i])
def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() self.assertEqual(nulldn.ldap_text(), nulldn.x500_text()) # reverse a DN with a single RDN self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text()) # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) self.assertEqual(dn3_rev.ldap_text(), dn3_x500) # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): self.assertEqual(longdn_rev[i], self.base_container_dn[l-1-i])
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # Fill in a default UUID when not specified. if entry_attrs.get('ipatokenuniqueid', None) is None: entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4()) dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'], dn) if not _check_interval(options.get('ipatokennotbefore', None), options.get('ipatokennotafter', None)): raise ValidationError(name='not_after', error='is before the validity start') # Set the object class and defaults for specific token types options['type'] = options['type'].lower() entry_attrs['objectclass'] = otptoken.object_class + [ 'ipatoken' + options['type'] ] for ttype, tattrs in TOKEN_TYPES.items(): if ttype != options['type']: for tattr in tattrs: if tattr in entry_attrs: del entry_attrs[tattr] # If owner was not specified, default to the person adding this token. # If managedby was not specified, attempt a sensible default. if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs: cur_dn = DN(self.api.Backend.ldap2.conn.whoami_s()[4:]) if cur_dn: cur_uid = cur_dn[0].value prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid) if cur_uid == prev_uid: entry_attrs.setdefault('managedby', cur_dn.ldap_text()) # Resolve the owner's dn _normalize_owner(self.api.Object.user, entry_attrs) # Get the issuer for the URI owner = entry_attrs.get('ipatokenowner', None) issuer = api.env.realm if owner is not None: try: issuer = ldap.get_entry( owner, ['krbprincipalname'])['krbprincipalname'][0] except (NotFound, IndexError): pass # Check if key is not empty if entry_attrs['ipatokenotpkey'] is None: raise ValidationError(name='key', error=_(u'cannot be empty')) # Build the URI parameters args = {} args['issuer'] = issuer args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey']) args['digits'] = entry_attrs['ipatokenotpdigits'] args['algorithm'] = entry_attrs['ipatokenotpalgorithm'].upper() if options['type'] == 'totp': args['period'] = entry_attrs['ipatokentotptimestep'] elif options['type'] == 'hotp': args['counter'] = entry_attrs['ipatokenhotpcounter'] # Build the URI label = urllib.parse.quote(entry_attrs['ipatokenuniqueid']) parameters = urllib.parse.urlencode(args) uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters) setattr(context, 'uri', uri) attrs_list.append("objectclass") return dn
class TestDN: @pytest.fixture(autouse=True) def dn_setup(self): # ava1 must sort before ava2 self.attr1 = 'cn' self.value1 = u'Bob' self.str_ava1 = '%s=%s' % (self.attr1, self.value1) self.ava1 = AVA(self.attr1, self.value1) self.str_rdn1 = '%s=%s' % (self.attr1, self.value1) self.rdn1 = RDN((self.attr1, self.value1)) self.attr2 = 'ou' self.value2 = u'people' self.str_ava2 = '%s=%s' % (self.attr2, self.value2) self.ava2 = AVA(self.attr2, self.value2) self.str_rdn2 = '%s=%s' % (self.attr2, self.value2) self.rdn2 = RDN((self.attr2, self.value2)) self.str_dn1 = self.str_rdn1 self.dn1 = DN(self.rdn1) self.str_dn2 = self.str_rdn2 self.dn2 = DN(self.rdn2) self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2) self.dn3 = DN(self.rdn1, self.rdn2) self.base_rdn1 = RDN(('dc', 'redhat')) self.base_rdn2 = RDN(('dc', 'com')) self.base_dn = DN(self.base_rdn1, self.base_rdn2) self.container_rdn1 = RDN(('cn', 'sudorules')) self.container_rdn2 = RDN(('cn', 'sudo')) self.container_dn = DN(self.container_rdn1, self.container_rdn2) self.base_container_dn = DN((self.attr1, self.value1), self.container_dn, self.base_dn) ou = x509.NameAttribute( x509.NameOID.ORGANIZATIONAL_UNIT_NAME, self.value2) cn = x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1) c = x509.NameAttribute(x509.NameOID.COUNTRY_NAME, 'AU') st = x509.NameAttribute( x509.NameOID.STATE_OR_PROVINCE_NAME, 'Queensland') self.x500name = x509.Name([ou, cn]) self.x500nameMultiRDN = x509.Name([ x509.RelativeDistinguishedName([c, st]), x509.RelativeDistinguishedName([cn]), ]) self.x500nameMultiRDN2 = x509.Name([ x509.RelativeDistinguishedName([st, c]), x509.RelativeDistinguishedName([cn]), ]) def assertExpectedClass(self, klass, obj, component): assert obj.__class__ is expected_class(klass, component) def test_create(self): # Create with single attr,value pair dn1 = DN((self.attr1, self.value1)) assert len(dn1) == 1 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[0].attr, unicode) assert isinstance(dn1[0].value, unicode) assert dn1[0] == self.rdn1 # Create with single attr,value pair passed as a tuple dn1 = DN((self.attr1, self.value1)) assert len(dn1) == 1 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 # Creation with multiple attr,value string pairs should fail with pytest.raises(ValueError): dn1 = DN(self.attr1, self.value1, self.attr2, self.value2) # Create with multiple attr,value pairs passed as tuples & lists dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2]) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 assert dn1[1] == self.rdn2 # Create with multiple attr,value pairs passed as tuple and RDN dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2))) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 assert dn1[1] == self.rdn2 # Create with multiple attr,value pairs but reverse # constructor parameter ordering. RDN ordering should also be # reversed because DN's are a ordered sequence of RDN's dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1)) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn2 assert dn1[1] == self.rdn1 # Create with single RDN object dn1 = DN(self.rdn1) assert len(dn1) == 1 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 # Create with multiple RDN objects, assure ordering is preserved. dn1 = DN(self.rdn1, self.rdn2) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 assert dn1[1] == self.rdn2 # Create with multiple RDN objects in different order, assure # ordering is preserved. dn1 = DN(self.rdn2, self.rdn1) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn2 assert dn1[1] == self.rdn1 # Create with single string with 1 RDN dn1 = DN(self.str_rdn1) assert len(dn1) == 1 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 # Create with single string with 2 RDN's dn1 = DN(self.str_dn3) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 assert dn1[1] == self.rdn2 # Create with a python-cryptography 'Name' dn1 = DN(self.x500name) assert len(dn1) == 2 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') assert isinstance(dn1[i].attr, unicode) assert isinstance(dn1[i].value, unicode) assert dn1[0] == self.rdn1 assert dn1[1] == self.rdn2 # Create from 'Name' with multi-valued RDN dn1 = DN(self.x500nameMultiRDN) assert len(dn1) == 2 assert len(dn1[1]) == 2 assert AVA('c', 'au') in dn1[1] assert AVA('st', 'queensland') in dn1[1] assert len(dn1[0]) == 1 assert self.ava1 in dn1[0] # Create with RDN, and 2 DN's (e.g. attr + container + base) dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn) assert len(dn1) == 5 dn_str = ','.join([str(self.rdn1), str(self.container_rdn1), str(self.container_rdn2), str(self.base_rdn1), str(self.base_rdn2)]) assert str(dn1) == dn_str def test_str(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) assert str(dn1) == self.str_dn1 assert isinstance(str(dn1), str) assert str(dn2) == self.str_dn2 assert isinstance(str(dn2), str) assert str(dn3) == self.str_dn3 assert isinstance(str(dn3), str) def test_cmp(self): # Equality dn1 = DN((self.attr1, self.value1)) assert dn1 == self.dn1 assert dn1 == self.dn1 assert dn1 == self.str_dn1 assert dn1 == self.str_dn1 result = cmp(dn1, self.dn1) assert result == 0 # Make dn1's attr greater with pytest.raises(AttributeError): dn1[0].attr = self.attr1 + "1" dn1 = DN((self.attr1 + "1", self.value1)) assert dn1 != self.dn1 assert dn1 != self.dn1 result = cmp(dn1, self.dn1) assert result == 1 result = cmp(self.dn1, dn1) assert result == -1 # Reset dn1's attr, should be equal again with pytest.raises(AttributeError): dn1[0].attr = self.attr1 dn1 = DN((self.attr1, self.value1)) result = cmp(dn1, self.dn1) assert result == 0 # Make dn1's value greater # attr will be equal, this tests secondary comparision component with pytest.raises(AttributeError): dn1[0].value = self.value1 + "1" dn1 = DN((self.attr1, self.value1 + "1")) result = cmp(dn1, self.dn1) assert result == 1 result = cmp(self.dn1, dn1) assert result == -1 # Make sure dn's with more rdn's are greater result = cmp(self.dn1, self.dn3) assert result == -1 result = cmp(self.dn3, self.dn1) assert result == 1 # Test startswith, endswith container_dn = DN(self.container_dn) base_container_dn = DN(self.base_container_dn) assert base_container_dn.startswith(self.rdn1) assert base_container_dn.startswith(self.dn1) assert base_container_dn.startswith(self.dn1 + container_dn) assert not base_container_dn.startswith(self.dn2) assert not base_container_dn.startswith(self.rdn2) assert base_container_dn.startswith((self.dn1)) assert base_container_dn.startswith((self.rdn1)) assert not base_container_dn.startswith((self.rdn2)) assert base_container_dn.startswith((self.rdn2, self.rdn1)) assert base_container_dn.startswith((self.dn1, self.dn2)) assert base_container_dn.endswith(self.base_dn) assert base_container_dn.endswith(container_dn + self.base_dn) assert not base_container_dn.endswith(DN(self.base_rdn1)) assert base_container_dn.endswith(DN(self.base_rdn2)) assert base_container_dn.endswith( (DN(self.base_rdn1), DN(self.base_rdn2))) # Test "in" membership assert self.container_rdn1 in container_dn # pylint: disable=comparison-with-itself assert container_dn in container_dn assert self.base_rdn1 not in container_dn assert self.container_rdn1 in base_container_dn assert container_dn in base_container_dn assert container_dn + self.base_dn in base_container_dn assert self.dn1 + container_dn + self.base_dn in base_container_dn assert self.dn1 + container_dn + self.base_dn == base_container_dn assert self.container_rdn1 not in self.base_dn def test_eq_multi_rdn(self): dn1 = DN(self.ava1, 'ST=Queensland+C=AU') dn2 = DN(self.ava1, 'C=AU+ST=Queensland') assert dn1 == dn2 # ensure AVAs get sorted when constructing from x509.Name dn3 = DN(self.x500nameMultiRDN) dn4 = DN(self.x500nameMultiRDN2) assert dn3 == dn4 # ensure AVAs get sorted in the same way regardless of what # the DN was constructed from assert dn1 == dn3 assert dn1 == dn4 assert dn2 == dn3 assert dn2 == dn4 def test_indexing(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) assert dn1[0] == self.rdn1 assert dn1[self.rdn1.attr] == self.rdn1.value with pytest.raises(KeyError): dn1['foo'] # pylint: disable=pointless-statement assert dn2[0] == self.rdn2 assert dn2[self.rdn2.attr] == self.rdn2.value with pytest.raises(KeyError): dn2['foo'] # pylint: disable=pointless-statement assert dn3[0] == self.rdn1 assert dn3[self.rdn1.attr] == self.rdn1.value assert dn3[1] == self.rdn2 assert dn3[self.rdn2.attr] == self.rdn2.value with pytest.raises(KeyError): dn3['foo'] # pylint: disable=pointless-statement with pytest.raises(TypeError): dn3[1.0] # pylint: disable=pointless-statement def test_assignments(self): dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with pytest.raises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0] = RDN('t=a') with pytest.raises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0:1] = [RDN('t=a'), RDN('t=b')] def test_iter(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) assert len(dn1) == 1 assert dn1[:] == self.rdn1 for i, ava in enumerate(dn1): if i == 0: assert ava == self.rdn1 else: pytest.fail( "got iteration index %d, but len=%d" % (i, len(self.rdn1))) assert len(dn2) == 1 assert dn2[:] == self.rdn2 for i, ava in enumerate(dn2): if i == 0: assert ava == self.rdn2 else: pytest.fail( "got iteration index %d, but len=%d" % (i, len(self.rdn2))) assert len(dn3) == 2 assert dn3[:] == DN(self.rdn1, self.rdn2) for i, ava in enumerate(dn3): if i == 0: assert ava == self.rdn1 elif i == 1: assert ava == self.rdn2 else: pytest.fail( "got iteration index %d, but len=%d" % (i, len(dn3))) def test_concat(self): dn1 = DN((self.attr1, self.value1)) dn2 = DN([self.attr2, self.value2]) # in-place addtion dn1 += dn2 assert dn1 == self.dn3 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.rdn2 assert dn1 == self.dn3 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.dn2 assert dn1 == self.dn3 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.str_dn2 assert dn1 == self.dn3 self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') # concatenation dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + dn2 assert dn3 == self.dn3 self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + self.rdn2 assert dn3 == self.dn3 self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.str_rdn2 assert dn3 == self.dn3 self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') self.assertExpectedClass(DN, dn3[i][0], 'AVA') dn3 = dn1 + self.str_dn2 assert dn3 == self.dn3 self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.dn2 assert dn3 == self.dn3 self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') def test_find(self): # -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9') pat = DN('cn=bob') # forward assert dn.find(pat) == 2 assert dn.find(pat, 1) == 2 assert dn.find(pat, 1, 3) == 2 assert dn.find(pat, 2, 3) == 2 assert dn.find(pat, 6) == 6 assert dn.find(pat, 7) == -1 assert dn.find(pat, 1, 2) == -1 with pytest.raises(ValueError): assert dn.index(pat, 7) == -1 with pytest.raises(ValueError): assert dn.index(pat, 1, 2) == -1 # reverse assert dn.rfind(pat) == 6 assert dn.rfind(pat, -4) == 6 assert dn.rfind(pat, 6) == 6 assert dn.rfind(pat, 6, 8) == 6 assert dn.rfind(pat, 6, 8) == 6 assert dn.rfind(pat, -8) == 6 assert dn.rfind(pat, -8, -4) == 6 assert dn.rfind(pat, -8, -5) == 2 assert dn.rfind(pat, 7) == -1 assert dn.rfind(pat, -3) == -1 with pytest.raises(ValueError): assert dn.rindex(pat, 7) == -1 with pytest.raises(ValueError): assert dn.rindex(pat, -3) == -1 def test_replace(self): # pylint: disable=no-member dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with pytest.raises(AttributeError): dn.replace # pylint: disable=pointless-statement def test_hashing(self): # create DN's that are equal but differ in case dn1 = DN((self.attr1.lower(), self.value1.upper())) dn2 = DN((self.attr1.upper(), self.value1.lower())) # DNs that are equal should hash to the same value. assert dn1 == dn2 # Good, everyone's equal, now verify their hash values assert hash(dn1) == hash(dn2) # Different DN objects with the same value should # map to 1 common key and 1 member in a set. The key and # member are based on the object's value. dn1_a = DN(self.dn1) dn1_b = DN(self.dn1) dn2_a = DN(self.dn2) dn2_b = DN(self.dn2) dn3_a = DN(self.dn3) dn3_b = DN(self.dn3) assert dn1_a == dn1_b assert dn2_a == dn2_b assert dn3_a == dn3_b d = dict() s = set() d[dn1_a] = str(dn1_a) d[dn1_b] = str(dn1_b) d[dn2_a] = str(dn2_a) d[dn2_b] = str(dn2_b) s.add(dn1_a) s.add(dn1_b) s.add(dn2_a) s.add(dn2_b) assert len(d) == 2 assert len(s) == 2 assert sorted(d) == sorted([dn1_a, dn2_a]) assert sorted(s) == sorted([dn1_a, dn2_a]) assert dn1_a in d assert dn1_b in d assert dn2_a in d assert dn2_b in d assert dn3_a not in d assert dn3_b not in d assert dn1_a in s assert dn1_b in s assert dn2_a in s assert dn2_b in s assert dn3_a not in s assert dn3_b not in s def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() assert nulldn.ldap_text() == nulldn.x500_text() # reverse a DN with a single RDN assert self.dn1.ldap_text() == self.dn1.x500_text() # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) assert dn3_rev.ldap_text() == dn3_x500 # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): assert longdn_rev[i] == self.base_container_dn[l - 1 - i]
class TestDN(unittest.TestCase): def setUp(self): # ava1 must sort before ava2 self.attr1 = 'cn' self.value1 = u'Bob' self.str_ava1 = '%s=%s' % (self.attr1, self.value1) self.ava1 = AVA(self.attr1, self.value1) self.str_rdn1 = '%s=%s' % (self.attr1, self.value1) self.rdn1 = RDN((self.attr1, self.value1)) self.attr2 = 'ou' self.value2 = u'people' self.str_ava2 = '%s=%s' % (self.attr2, self.value2) self.ava2 = AVA(self.attr2, self.value2) self.str_rdn2 = '%s=%s' % (self.attr2, self.value2) self.rdn2 = RDN((self.attr2, self.value2)) self.str_dn1 = self.str_rdn1 self.dn1 = DN(self.rdn1) self.str_dn2 = self.str_rdn2 self.dn2 = DN(self.rdn2) self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2) self.dn3 = DN(self.rdn1, self.rdn2) self.base_rdn1 = RDN(('dc', 'redhat')) self.base_rdn2 = RDN(('dc', 'com')) self.base_dn = DN(self.base_rdn1, self.base_rdn2) self.container_rdn1 = RDN(('cn', 'sudorules')) self.container_rdn2 = RDN(('cn', 'sudo')) self.container_dn = DN(self.container_rdn1, self.container_rdn2) self.base_container_dn = DN((self.attr1, self.value1), self.container_dn, self.base_dn) self.x500name = x509.Name([ x509.NameAttribute(x509.NameOID.ORGANIZATIONAL_UNIT_NAME, self.value2), x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1), ]) def assertExpectedClass(self, klass, obj, component): self.assertIs(obj.__class__, expected_class(klass, component)) def test_create(self): # Create with single attr,value pair dn1 = DN((self.attr1, self.value1)) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[0].attr, unicode) self.assertIsInstance(dn1[0].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with single attr,value pair passed as a tuple dn1 = DN((self.attr1, self.value1)) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Creation with multiple attr,value string pairs should fail with self.assertRaises(ValueError): dn1 = DN(self.attr1, self.value1, self.attr2, self.value2) # Create with multiple attr,value pairs passed as tuples & lists dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2]) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple attr,value pairs passed as tuple and RDN dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2))) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple attr,value pairs but reverse # constructor parameter ordering. RDN ordering should also be # reversed because DN's are a ordered sequence of RDN's dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1)) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn2) self.assertEqual(dn1[1], self.rdn1) # Create with single RDN object dn1 = DN(self.rdn1) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with multiple RDN objects, assure ordering is preserved. dn1 = DN(self.rdn1, self.rdn2) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple RDN objects in different order, assure # ordering is preserved. dn1 = DN(self.rdn2, self.rdn1) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn2) self.assertEqual(dn1[1], self.rdn1) # Create with single string with 1 RDN dn1 = DN(self.str_rdn1) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with single string with 2 RDN's dn1 = DN(self.str_dn3) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with a python-cryptography 'Name' dn1 = DN(self.x500name) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with RDN, and 2 DN's (e.g. attr + container + base) dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn) self.assertEqual(len(dn1), 5) dn_str = ','.join([ str(self.rdn1), str(self.container_rdn1), str(self.container_rdn2), str(self.base_rdn1), str(self.base_rdn2) ]) self.assertEqual(str(dn1), dn_str) def test_str(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(str(dn1), self.str_dn1) self.assertIsInstance(str(dn1), str) self.assertEqual(str(dn2), self.str_dn2) self.assertIsInstance(str(dn2), str) self.assertEqual(str(dn3), self.str_dn3) self.assertIsInstance(str(dn3), str) def test_cmp(self): # Equality dn1 = DN((self.attr1, self.value1)) self.assertTrue(dn1 == self.dn1) self.assertFalse(dn1 != self.dn1) self.assertTrue(dn1 == self.str_dn1) self.assertFalse(dn1 != self.str_dn1) result = cmp(dn1, self.dn1) self.assertEqual(result, 0) # Make dn1's attr greater with self.assertRaises(AttributeError): dn1[0].attr = self.attr1 + "1" dn1 = DN((self.attr1 + "1", self.value1)) self.assertFalse(dn1 == self.dn1) self.assertTrue(dn1 != self.dn1) result = cmp(dn1, self.dn1) self.assertEqual(result, 1) result = cmp(self.dn1, dn1) self.assertEqual(result, -1) # Reset dn1's attr, should be equal again with self.assertRaises(AttributeError): dn1[0].attr = self.attr1 dn1 = DN((self.attr1, self.value1)) result = cmp(dn1, self.dn1) self.assertEqual(result, 0) # Make dn1's value greater # attr will be equal, this tests secondary comparision component with self.assertRaises(AttributeError): dn1[0].value = self.value1 + "1" dn1 = DN((self.attr1, self.value1 + "1")) result = cmp(dn1, self.dn1) self.assertEqual(result, 1) result = cmp(self.dn1, dn1) self.assertEqual(result, -1) # Make sure dn's with more rdn's are greater result = cmp(self.dn1, self.dn3) self.assertEqual(result, -1) result = cmp(self.dn3, self.dn1) self.assertEqual(result, 1) # Test startswith, endswith container_dn = DN(self.container_dn) base_container_dn = DN(self.base_container_dn) self.assertTrue(base_container_dn.startswith(self.rdn1)) self.assertTrue(base_container_dn.startswith(self.dn1)) self.assertTrue(base_container_dn.startswith(self.dn1 + container_dn)) self.assertFalse(base_container_dn.startswith(self.dn2)) self.assertFalse(base_container_dn.startswith(self.rdn2)) self.assertTrue(base_container_dn.startswith((self.dn1))) self.assertTrue(base_container_dn.startswith((self.rdn1))) self.assertFalse(base_container_dn.startswith((self.rdn2))) self.assertTrue(base_container_dn.startswith((self.rdn2, self.rdn1))) self.assertTrue(base_container_dn.startswith((self.dn1, self.dn2))) self.assertTrue(base_container_dn.endswith(self.base_dn)) self.assertTrue(base_container_dn.endswith(container_dn + self.base_dn)) self.assertFalse(base_container_dn.endswith(DN(self.base_rdn1))) self.assertTrue(base_container_dn.endswith(DN(self.base_rdn2))) self.assertTrue( base_container_dn.endswith( (DN(self.base_rdn1), DN(self.base_rdn2)))) # Test "in" membership self.assertTrue(self.container_rdn1 in container_dn) self.assertTrue(container_dn in container_dn) self.assertFalse(self.base_rdn1 in container_dn) self.assertTrue(self.container_rdn1 in base_container_dn) self.assertTrue(container_dn in base_container_dn) self.assertTrue(container_dn + self.base_dn in base_container_dn) self.assertTrue(self.dn1 + container_dn + self.base_dn in base_container_dn) self.assertTrue(self.dn1 + container_dn + self.base_dn == base_container_dn) self.assertFalse(self.container_rdn1 in self.base_dn) def test_indexing(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[self.rdn1.attr], self.rdn1.value) with self.assertRaises(KeyError): dn1['foo'] # pylint: disable=pointless-statement self.assertEqual(dn2[0], self.rdn2) self.assertEqual(dn2[self.rdn2.attr], self.rdn2.value) with self.assertRaises(KeyError): dn2['foo'] # pylint: disable=pointless-statement self.assertEqual(dn3[0], self.rdn1) self.assertEqual(dn3[self.rdn1.attr], self.rdn1.value) self.assertEqual(dn3[1], self.rdn2) self.assertEqual(dn3[self.rdn2.attr], self.rdn2.value) with self.assertRaises(KeyError): dn3['foo'] # pylint: disable=pointless-statement with self.assertRaises(TypeError): dn3[1.0] # pylint: disable=pointless-statement def test_assignments(self): dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with self.assertRaises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0] = RDN('t=a') with self.assertRaises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0:1] = [RDN('t=a'), RDN('t=b')] def test_iter(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(len(dn1), 1) self.assertEqual(dn1[:], self.rdn1) for i, ava in enumerate(dn1): if i == 0: self.assertEqual(ava, self.rdn1) else: self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn1))) self.assertEqual(len(dn2), 1) self.assertEqual(dn2[:], self.rdn2) for i, ava in enumerate(dn2): if i == 0: self.assertEqual(ava, self.rdn2) else: self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn2))) self.assertEqual(len(dn3), 2) self.assertEqual(dn3[:], DN(self.rdn1, self.rdn2)) for i, ava in enumerate(dn3): if i == 0: self.assertEqual(ava, self.rdn1) elif i == 1: self.assertEqual(ava, self.rdn2) else: self.fail("got iteration index %d, but len=%d" % (i, len(dn3))) def test_concat(self): dn1 = DN((self.attr1, self.value1)) dn2 = DN([self.attr2, self.value2]) # in-place addtion dn1 += dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.rdn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.str_dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') # concatenation dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + self.rdn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.str_rdn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') self.assertExpectedClass(DN, dn3[i][0], 'AVA') dn3 = dn1 + self.str_dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') def test_find(self): # -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9') pat = DN('cn=bob') # forward self.assertEqual(dn.find(pat), 2) self.assertEqual(dn.find(pat, 1), 2) self.assertEqual(dn.find(pat, 1, 3), 2) self.assertEqual(dn.find(pat, 2, 3), 2) self.assertEqual(dn.find(pat, 6), 6) self.assertEqual(dn.find(pat, 7), -1) self.assertEqual(dn.find(pat, 1, 2), -1) with self.assertRaises(ValueError): self.assertEqual(dn.index(pat, 7), -1) with self.assertRaises(ValueError): self.assertEqual(dn.index(pat, 1, 2), -1) # reverse self.assertEqual(dn.rfind(pat), 6) self.assertEqual(dn.rfind(pat, -4), 6) self.assertEqual(dn.rfind(pat, 6), 6) self.assertEqual(dn.rfind(pat, 6, 8), 6) self.assertEqual(dn.rfind(pat, 6, 8), 6) self.assertEqual(dn.rfind(pat, -8), 6) self.assertEqual(dn.rfind(pat, -8, -4), 6) self.assertEqual(dn.rfind(pat, -8, -5), 2) self.assertEqual(dn.rfind(pat, 7), -1) self.assertEqual(dn.rfind(pat, -3), -1) with self.assertRaises(ValueError): self.assertEqual(dn.rindex(pat, 7), -1) with self.assertRaises(ValueError): self.assertEqual(dn.rindex(pat, -3), -1) def test_replace(self): # pylint: disable=no-member dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with self.assertRaises(AttributeError): dn.replace # pylint: disable=pointless-statement def test_hashing(self): # create DN's that are equal but differ in case dn1 = DN((self.attr1.lower(), self.value1.upper())) dn2 = DN((self.attr1.upper(), self.value1.lower())) # DNs that are equal should hash to the same value. self.assertEqual(dn1, dn2) # Good, everyone's equal, now verify their hash values self.assertEqual(hash(dn1), hash(dn2)) # Different DN objects with the same value should # map to 1 common key and 1 member in a set. The key and # member are based on the object's value. dn1_a = DN(self.dn1) dn1_b = DN(self.dn1) dn2_a = DN(self.dn2) dn2_b = DN(self.dn2) dn3_a = DN(self.dn3) dn3_b = DN(self.dn3) self.assertEqual(dn1_a, dn1_b) self.assertEqual(dn2_a, dn2_b) self.assertEqual(dn3_a, dn3_b) d = dict() s = set() d[dn1_a] = str(dn1_a) d[dn1_b] = str(dn1_b) d[dn2_a] = str(dn2_a) d[dn2_b] = str(dn2_b) s.add(dn1_a) s.add(dn1_b) s.add(dn2_a) s.add(dn2_b) self.assertEqual(len(d), 2) self.assertEqual(len(s), 2) self.assertEqual(sorted(d), sorted([dn1_a, dn2_a])) self.assertEqual(sorted(s), sorted([dn1_a, dn2_a])) self.assertTrue(dn1_a in d) self.assertTrue(dn1_b in d) self.assertTrue(dn2_a in d) self.assertTrue(dn2_b in d) self.assertFalse(dn3_a in d) self.assertFalse(dn3_b in d) self.assertTrue(dn1_a in s) self.assertTrue(dn1_b in s) self.assertTrue(dn2_a in s) self.assertTrue(dn2_b in s) self.assertFalse(dn3_a in s) self.assertFalse(dn3_b in s) def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() self.assertEqual(nulldn.ldap_text(), nulldn.x500_text()) # reverse a DN with a single RDN self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text()) # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) self.assertEqual(dn3_rev.ldap_text(), dn3_x500) # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): self.assertEqual(longdn_rev[i], self.base_container_dn[l - 1 - i])
class TestDN(unittest.TestCase): def setUp(self): # ava1 must sort before ava2 self.attr1 = 'cn' self.value1 = u'Bob' self.str_ava1 = '%s=%s' % (self.attr1, self.value1) self.ava1 = AVA(self.attr1, self.value1) self.str_rdn1 = '%s=%s' % (self.attr1, self.value1) self.rdn1 = RDN((self.attr1, self.value1)) self.attr2 = 'ou' self.value2 = u'people' self.str_ava2 = '%s=%s' % (self.attr2, self.value2) self.ava2 = AVA(self.attr2, self.value2) self.str_rdn2 = '%s=%s' % (self.attr2, self.value2) self.rdn2 = RDN((self.attr2, self.value2)) self.str_dn1 = self.str_rdn1 self.dn1 = DN(self.rdn1) self.str_dn2 = self.str_rdn2 self.dn2 = DN(self.rdn2) self.str_dn3 = '%s,%s' % (self.str_rdn1, self.str_rdn2) self.dn3 = DN(self.rdn1, self.rdn2) self.base_rdn1 = RDN(('dc', 'redhat')) self.base_rdn2 = RDN(('dc', 'com')) self.base_dn = DN(self.base_rdn1, self.base_rdn2) self.container_rdn1 = RDN(('cn', 'sudorules')) self.container_rdn2 = RDN(('cn', 'sudo')) self.container_dn = DN(self.container_rdn1, self.container_rdn2) self.base_container_dn = DN((self.attr1, self.value1), self.container_dn, self.base_dn) self.x500name = x509.Name([ x509.NameAttribute( x509.NameOID.ORGANIZATIONAL_UNIT_NAME, self.value2), x509.NameAttribute(x509.NameOID.COMMON_NAME, self.value1), ]) def assertExpectedClass(self, klass, obj, component): self.assertIs(obj.__class__, expected_class(klass, component)) def test_create(self): # Create with single attr,value pair dn1 = DN((self.attr1, self.value1)) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[0].attr, unicode) self.assertIsInstance(dn1[0].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with single attr,value pair passed as a tuple dn1 = DN((self.attr1, self.value1)) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Creation with multiple attr,value string pairs should fail with self.assertRaises(ValueError): dn1 = DN(self.attr1, self.value1, self.attr2, self.value2) # Create with multiple attr,value pairs passed as tuples & lists dn1 = DN((self.attr1, self.value1), [self.attr2, self.value2]) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple attr,value pairs passed as tuple and RDN dn1 = DN((self.attr1, self.value1), RDN((self.attr2, self.value2))) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple attr,value pairs but reverse # constructor parameter ordering. RDN ordering should also be # reversed because DN's are a ordered sequence of RDN's dn1 = DN((self.attr2, self.value2), (self.attr1, self.value1)) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn2) self.assertEqual(dn1[1], self.rdn1) # Create with single RDN object dn1 = DN(self.rdn1) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with multiple RDN objects, assure ordering is preserved. dn1 = DN(self.rdn1, self.rdn2) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with multiple RDN objects in different order, assure # ordering is preserved. dn1 = DN(self.rdn2, self.rdn1) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn2) self.assertEqual(dn1[1], self.rdn1) # Create with single string with 1 RDN dn1 = DN(self.str_rdn1) self.assertEqual(len(dn1), 1) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) # Create with single string with 2 RDN's dn1 = DN(self.str_dn3) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with a python-cryptography 'Name' dn1 = DN(self.x500name) self.assertEqual(len(dn1), 2) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') self.assertIsInstance(dn1[i].attr, unicode) self.assertIsInstance(dn1[i].value, unicode) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[1], self.rdn2) # Create with RDN, and 2 DN's (e.g. attr + container + base) dn1 = DN((self.attr1, self.value1), self.container_dn, self.base_dn) self.assertEqual(len(dn1), 5) dn_str = ','.join([str(self.rdn1), str(self.container_rdn1), str(self.container_rdn2), str(self.base_rdn1), str(self.base_rdn2)]) self.assertEqual(str(dn1), dn_str) def test_str(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(str(dn1), self.str_dn1) self.assertIsInstance(str(dn1), str) self.assertEqual(str(dn2), self.str_dn2) self.assertIsInstance(str(dn2), str) self.assertEqual(str(dn3), self.str_dn3) self.assertIsInstance(str(dn3), str) def test_cmp(self): # Equality dn1 = DN((self.attr1, self.value1)) self.assertTrue(dn1 == self.dn1) self.assertFalse(dn1 != self.dn1) self.assertTrue(dn1 == self.str_dn1) self.assertFalse(dn1 != self.str_dn1) result = cmp(dn1, self.dn1) self.assertEqual(result, 0) # Make dn1's attr greater with self.assertRaises(AttributeError): dn1[0].attr = self.attr1 + "1" dn1 = DN((self.attr1 + "1", self.value1)) self.assertFalse(dn1 == self.dn1) self.assertTrue(dn1 != self.dn1) result = cmp(dn1, self.dn1) self.assertEqual(result, 1) result = cmp(self.dn1, dn1) self.assertEqual(result, -1) # Reset dn1's attr, should be equal again with self.assertRaises(AttributeError): dn1[0].attr = self.attr1 dn1 = DN((self.attr1, self.value1)) result = cmp(dn1, self.dn1) self.assertEqual(result, 0) # Make dn1's value greater # attr will be equal, this tests secondary comparision component with self.assertRaises(AttributeError): dn1[0].value = self.value1 + "1" dn1 = DN((self.attr1, self.value1 + "1")) result = cmp(dn1, self.dn1) self.assertEqual(result, 1) result = cmp(self.dn1, dn1) self.assertEqual(result, -1) # Make sure dn's with more rdn's are greater result = cmp(self.dn1, self.dn3) self.assertEqual(result, -1) result = cmp(self.dn3, self.dn1) self.assertEqual(result, 1) # Test startswith, endswith container_dn = DN(self.container_dn) base_container_dn = DN(self.base_container_dn) self.assertTrue(base_container_dn.startswith(self.rdn1)) self.assertTrue(base_container_dn.startswith(self.dn1)) self.assertTrue(base_container_dn.startswith(self.dn1 + container_dn)) self.assertFalse(base_container_dn.startswith(self.dn2)) self.assertFalse(base_container_dn.startswith(self.rdn2)) self.assertTrue(base_container_dn.startswith((self.dn1))) self.assertTrue(base_container_dn.startswith((self.rdn1))) self.assertFalse(base_container_dn.startswith((self.rdn2))) self.assertTrue(base_container_dn.startswith((self.rdn2, self.rdn1))) self.assertTrue(base_container_dn.startswith((self.dn1, self.dn2))) self.assertTrue(base_container_dn.endswith(self.base_dn)) self.assertTrue(base_container_dn.endswith(container_dn + self.base_dn)) self.assertFalse(base_container_dn.endswith(DN(self.base_rdn1))) self.assertTrue(base_container_dn.endswith(DN(self.base_rdn2))) self.assertTrue(base_container_dn.endswith((DN(self.base_rdn1), DN(self.base_rdn2)))) # Test "in" membership self.assertTrue(self.container_rdn1 in container_dn) self.assertTrue(container_dn in container_dn) self.assertFalse(self.base_rdn1 in container_dn) self.assertTrue(self.container_rdn1 in base_container_dn) self.assertTrue(container_dn in base_container_dn) self.assertTrue(container_dn + self.base_dn in base_container_dn) self.assertTrue(self.dn1 + container_dn + self.base_dn in base_container_dn) self.assertTrue(self.dn1 + container_dn + self.base_dn == base_container_dn) self.assertFalse(self.container_rdn1 in self.base_dn) def test_indexing(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(dn1[0], self.rdn1) self.assertEqual(dn1[self.rdn1.attr], self.rdn1.value) with self.assertRaises(KeyError): dn1['foo'] # pylint: disable=pointless-statement self.assertEqual(dn2[0], self.rdn2) self.assertEqual(dn2[self.rdn2.attr], self.rdn2.value) with self.assertRaises(KeyError): dn2['foo'] # pylint: disable=pointless-statement self.assertEqual(dn3[0], self.rdn1) self.assertEqual(dn3[self.rdn1.attr], self.rdn1.value) self.assertEqual(dn3[1], self.rdn2) self.assertEqual(dn3[self.rdn2.attr], self.rdn2.value) with self.assertRaises(KeyError): dn3['foo'] # pylint: disable=pointless-statement with self.assertRaises(TypeError): dn3[1.0] # pylint: disable=pointless-statement def test_assignments(self): dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with self.assertRaises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0] = RDN('t=a') with self.assertRaises(TypeError): # pylint: disable=unsupported-assignment-operation dn[0:1] = [RDN('t=a'), RDN('t=b')] def test_iter(self): dn1 = DN(self.dn1) dn2 = DN(self.dn2) dn3 = DN(self.dn3) self.assertEqual(len(dn1), 1) self.assertEqual(dn1[:], self.rdn1) for i, ava in enumerate(dn1): if i == 0: self.assertEqual(ava, self.rdn1) else: self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn1))) self.assertEqual(len(dn2), 1) self.assertEqual(dn2[:], self.rdn2) for i, ava in enumerate(dn2): if i == 0: self.assertEqual(ava, self.rdn2) else: self.fail("got iteration index %d, but len=%d" % (i, len(self.rdn2))) self.assertEqual(len(dn3), 2) self.assertEqual(dn3[:], DN(self.rdn1, self.rdn2)) for i, ava in enumerate(dn3): if i == 0: self.assertEqual(ava, self.rdn1) elif i == 1: self.assertEqual(ava, self.rdn2) else: self.fail("got iteration index %d, but len=%d" % (i, len(dn3))) def test_concat(self): dn1 = DN((self.attr1, self.value1)) dn2 = DN([self.attr2, self.value2]) # in-place addtion dn1 += dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.rdn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn1 += self.str_dn2 self.assertEqual(dn1, self.dn3) self.assertExpectedClass(DN, dn1, 'self') for i in range(0, len(dn1)): self.assertExpectedClass(DN, dn1[i], 'RDN') for j in range(0, len(dn1[i])): self.assertExpectedClass(DN, dn1[i][j], 'AVA') # concatenation dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn1 = DN((self.attr1, self.value1)) dn3 = dn1 + self.rdn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.str_rdn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') self.assertExpectedClass(DN, dn3[i][0], 'AVA') dn3 = dn1 + self.str_dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') dn3 = dn1 + self.dn2 self.assertEqual(dn3, self.dn3) self.assertExpectedClass(DN, dn3, 'self') self.assertExpectedClass(DN, dn3, 'self') for i in range(0, len(dn3)): self.assertExpectedClass(DN, dn3[i], 'RDN') for j in range(0, len(dn3[i])): self.assertExpectedClass(DN, dn3[i][j], 'AVA') def test_find(self): # -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 dn = DN('t=0,t=1,cn=bob,t=3,t=4,t=5,cn=bob,t=7,t=8,t=9') pat = DN('cn=bob') # forward self.assertEqual(dn.find(pat), 2) self.assertEqual(dn.find(pat, 1), 2) self.assertEqual(dn.find(pat, 1, 3), 2) self.assertEqual(dn.find(pat, 2, 3), 2) self.assertEqual(dn.find(pat, 6), 6) self.assertEqual(dn.find(pat, 7), -1) self.assertEqual(dn.find(pat, 1, 2), -1) with self.assertRaises(ValueError): self.assertEqual(dn.index(pat, 7), -1) with self.assertRaises(ValueError): self.assertEqual(dn.index(pat, 1, 2), -1) # reverse self.assertEqual(dn.rfind(pat), 6) self.assertEqual(dn.rfind(pat, -4), 6) self.assertEqual(dn.rfind(pat, 6), 6) self.assertEqual(dn.rfind(pat, 6, 8), 6) self.assertEqual(dn.rfind(pat, 6, 8), 6) self.assertEqual(dn.rfind(pat, -8), 6) self.assertEqual(dn.rfind(pat, -8, -4), 6) self.assertEqual(dn.rfind(pat, -8, -5), 2) self.assertEqual(dn.rfind(pat, 7), -1) self.assertEqual(dn.rfind(pat, -3), -1) with self.assertRaises(ValueError): self.assertEqual(dn.rindex(pat, 7), -1) with self.assertRaises(ValueError): self.assertEqual(dn.rindex(pat, -3), -1) def test_replace(self): # pylint: disable=no-member dn = DN('t=0,t=1,t=2,t=3,t=4,t=5,t=6,t=7,t=8,t=9') with self.assertRaises(AttributeError): dn.replace # pylint: disable=pointless-statement def test_hashing(self): # create DN's that are equal but differ in case dn1 = DN((self.attr1.lower(), self.value1.upper())) dn2 = DN((self.attr1.upper(), self.value1.lower())) # DNs that are equal should hash to the same value. self.assertEqual(dn1, dn2) # Good, everyone's equal, now verify their hash values self.assertEqual(hash(dn1), hash(dn2)) # Different DN objects with the same value should # map to 1 common key and 1 member in a set. The key and # member are based on the object's value. dn1_a = DN(self.dn1) dn1_b = DN(self.dn1) dn2_a = DN(self.dn2) dn2_b = DN(self.dn2) dn3_a = DN(self.dn3) dn3_b = DN(self.dn3) self.assertEqual(dn1_a, dn1_b) self.assertEqual(dn2_a, dn2_b) self.assertEqual(dn3_a, dn3_b) d = dict() s = set() d[dn1_a] = str(dn1_a) d[dn1_b] = str(dn1_b) d[dn2_a] = str(dn2_a) d[dn2_b] = str(dn2_b) s.add(dn1_a) s.add(dn1_b) s.add(dn2_a) s.add(dn2_b) self.assertEqual(len(d), 2) self.assertEqual(len(s), 2) self.assertEqual(sorted(d), sorted([dn1_a, dn2_a])) self.assertEqual(sorted(s), sorted([dn1_a, dn2_a])) self.assertTrue(dn1_a in d) self.assertTrue(dn1_b in d) self.assertTrue(dn2_a in d) self.assertTrue(dn2_b in d) self.assertFalse(dn3_a in d) self.assertFalse(dn3_b in d) self.assertTrue(dn1_a in s) self.assertTrue(dn1_b in s) self.assertTrue(dn2_a in s) self.assertTrue(dn2_b in s) self.assertFalse(dn3_a in s) self.assertFalse(dn3_b in s) def test_x500_text(self): # null DN x500 ordering and LDAP ordering are the same nulldn = DN() self.assertEqual(nulldn.ldap_text(), nulldn.x500_text()) # reverse a DN with a single RDN self.assertEqual(self.dn1.ldap_text(), self.dn1.x500_text()) # reverse a DN with 2 RDNs dn3_x500 = self.dn3.x500_text() dn3_rev = DN(self.rdn2, self.rdn1) self.assertEqual(dn3_rev.ldap_text(), dn3_x500) # reverse a longer DN longdn_x500 = self.base_container_dn.x500_text() longdn_rev = DN(longdn_x500) l = len(self.base_container_dn) for i in range(l): self.assertEqual(longdn_rev[i], self.base_container_dn[l-1-i])
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): # Fill in a default UUID when not specified. if entry_attrs.get('ipatokenuniqueid', None) is None: entry_attrs['ipatokenuniqueid'] = str(uuid.uuid4()) dn = DN("ipatokenuniqueid=%s" % entry_attrs['ipatokenuniqueid'], dn) if not _check_interval(options.get('ipatokennotbefore', None), options.get('ipatokennotafter', None)): raise ValidationError(name='not_after', error='is before the validity start') # Set the object class and defaults for specific token types options['type'] = options['type'].lower() entry_attrs['objectclass'] = otptoken.object_class + ['ipatoken' + options['type']] for ttype, tattrs in TOKEN_TYPES.items(): if ttype != options['type']: for tattr in tattrs: if tattr in entry_attrs: del entry_attrs[tattr] # If owner was not specified, default to the person adding this token. # If managedby was not specified, attempt a sensible default. if 'ipatokenowner' not in entry_attrs or 'managedby' not in entry_attrs: cur_dn = DN(self.api.Backend.ldap2.conn.whoami_s()[4:]) if cur_dn: cur_uid = cur_dn[0].value prev_uid = entry_attrs.setdefault('ipatokenowner', cur_uid) if cur_uid == prev_uid: entry_attrs.setdefault('managedby', cur_dn.ldap_text()) # Resolve the owner's dn _normalize_owner(self.api.Object.user, entry_attrs) # Get the issuer for the URI owner = entry_attrs.get('ipatokenowner', None) issuer = api.env.realm if owner is not None: try: issuer = ldap.get_entry(owner, ['krbprincipalname'])['krbprincipalname'][0] except (NotFound, IndexError): pass # Check if key is not empty if entry_attrs['ipatokenotpkey'] is None: raise ValidationError(name='key', error=_(u'cannot be empty')) # Build the URI parameters args = {} args['issuer'] = issuer args['secret'] = base64.b32encode(entry_attrs['ipatokenotpkey']) args['digits'] = entry_attrs['ipatokenotpdigits'] args['algorithm'] = entry_attrs['ipatokenotpalgorithm'].upper() if options['type'] == 'totp': args['period'] = entry_attrs['ipatokentotptimestep'] elif options['type'] == 'hotp': args['counter'] = entry_attrs['ipatokenhotpcounter'] # Build the URI label = urllib.parse.quote(entry_attrs['ipatokenuniqueid']) parameters = urllib.parse.urlencode(args) uri = u'otpauth://%s/%s:%s?%s' % (options['type'], issuer, label, parameters) setattr(context, 'uri', uri) attrs_list.append("objectclass") return dn