def testInequalityDiffertnOperations(self): """ Modify operations for same DN but different operations are not equal. """ first = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) second = delta.ModifyOp("cn=doe,dc=example,dc=com", [delta.Delete("homeDirectory")]) self.assertNotEqual(first, second)
def testInequalityDiffertnDN(self): """ Modify operations for different DN are not equal. """ first = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) second = delta.ModifyOp("cn=doe,dc=example,dc=com", [delta.Delete("description")]) self.assertNotEqual(first, second)
def testInequalityDifferentModifications(self): """ Modify operations with different modifications are not equal """ first = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Add("description")]) second = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) self.assertNotEqual(first, second)
def testHashInequality(self): """ Different modify operations have different hash values. """ first = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) second = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("homeDirectory")]) self.assertNotEqual(first.asLDIF(), second.asLDIF()) self.assertNotEqual(hash(first), hash(second))
def disable_dn_(self, dn, client=None): """ Deprovision subject based on DN. """ log = self.log unbind = False if client is None: client = yield self.get_ldap_client_() unbind = True with LDAPClientManager(client, active=unbind) as c: o = ldapsyntax.LDAPEntry(c, dn) results = yield o.search(filterText=self.search_filter, attributes=('userAccountControl', )) if len(results) == 1: entry = results[0] ADS_UF_ACCOUNTDISABLE = 0x00000002 user_account_control = int( list(entry['userAccountControl'])[0]) user_account_control = (user_account_control | ADS_UF_ACCOUNTDISABLE) mod = delta.ModifyOp(dn, [ delta.Replace('userAccountControl', ["{}".format(user_account_control)]), ]) l = mod.asLDAP() response = yield client.send(l)
def testModification_twoAdds(self): proto = LDIFDeltaDriver() proto.dataReceived(b"""\ version: 1 dn: cn=foo,dc=example,dc=com changetype: modify add: foo foo: bar - add: thud thud: quux thud: baz - """) proto.connectionLost() self.assertEqual( proto.listOfCompleted, [ delta.ModifyOp( dn=b"cn=foo,dc=example,dc=com", modifications=[ delta.Add(b"foo", [b"bar"]), delta.Add(b"thud", [b"quux", b"baz"]), ], ), ], )
def testRootChange_Add(self): a = inmemory.ReadOnlyInMemoryLDAPEntry( "dc=example,dc=com", { "dc": ["example"], }, ) b = inmemory.ReadOnlyInMemoryLDAPEntry( "dc=example,dc=com", { "dc": ["example"], "foo": ["bar"], }, ) d = a.diffTree(b) d.addCallback( self.assertEqual, [ delta.ModifyOp( "dc=example,dc=com", [ delta.Add("foo", ["bar"]), ], ), ], ) return d
def testModify(self): op=delta.ModifyOp('cn=Paula Jensen, ou=Product Development, dc=airius, dc=com', [ delta.Add('postaladdress', ['123 Anystreet $ Sunnyvale, CA $ 94086']), delta.Delete('description'), delta.Replace('telephonenumber', ['+1 408 555 1234', '+1 408 555 5678']), delta.Delete('facsimiletelephonenumber', ['+1 408 555 9876']), ]) self.assertEquals(op.asLDIF(), """\ dn: cn=Paula Jensen,ou=Product Development,dc=airius,dc=com changetype: modify add: postaladdress postaladdress: 123 Anystreet $ Sunnyvale, CA $ 94086 - delete: description - replace: telephonenumber telephonenumber: +1 408 555 1234 telephonenumber: +1 408 555 5678 - delete: facsimiletelephonenumber facsimiletelephonenumber: +1 408 555 9876 - """)
def testComplex(self): a = entry.BaseLDAPEntry( dn="cn=Paula Jensen,ou=Product Development,dc=airius,dc=com", attributes={ "description": ["Something"], "telephonenumber": ["+123 456"], "facsimiletelephonenumber": ["+1 408 555 9876"], }, ) b = entry.BaseLDAPEntry( dn="cn=Paula Jensen,ou=Product Development,dc=airius,dc=com", attributes={ "postalAddress": ["123 Anystreet $ Sunnyvale, CA $ 94086"], "telephonenumber": ["+1 408 555 1234", "+1 408 555 5678"], }, ) result = a.diff(b) self.assertEqual( result, delta.ModifyOp( "cn=Paula Jensen,ou=Product Development,dc=airius,dc=com", [ delta.Add( "postalAddress", ["123 Anystreet $ Sunnyvale, CA $ 94086"] ), delta.Delete("description", ["Something"]), delta.Delete("facsimiletelephonenumber", ["+1 408 555 9876"]), delta.Add( "telephonenumber", ["+1 408 555 1234", "+1 408 555 5678"] ), delta.Delete("telephonenumber", ["+123 456"]), ], ), )
def cb3(got): self.assertEquals(got, [ delta.ModifyOp( self.empty.dn, [delta.Add('foo', ['bar'])], ), ])
def testComplex(self): a = entry.BaseLDAPEntry( dn='cn=Paula Jensen,ou=Product Development,dc=airius,dc=com', attributes={ 'description': ['Something'], 'telephonenumber': ['+123 456'], 'facsimiletelephonenumber': ['+1 408 555 9876'], }) b = entry.BaseLDAPEntry( dn='cn=Paula Jensen,ou=Product Development,dc=airius,dc=com', attributes={ 'postalAddress': ['123 Anystreet $ Sunnyvale, CA $ 94086'], 'telephonenumber': ['+1 408 555 1234', '+1 408 555 5678'], }) result = a.diff(b) self.assertEqual( result, delta.ModifyOp( 'cn=Paula Jensen,ou=Product Development,dc=airius,dc=com', [ delta.Add('postalAddress', ['123 Anystreet $ Sunnyvale, CA $ 94086']), delta.Delete('description', ['Something']), delta.Delete('facsimiletelephonenumber', ['+1 408 555 9876']), delta.Add('telephonenumber', ['+1 408 555 1234', '+1 408 555 5678']), delta.Delete('telephonenumber', ['+123 456']), ]))
def testAdd_NewAndExisting_ManyTypes(self): a = entry.BaseLDAPEntry( dn="dc=foo", attributes={ "foo": ["bar"], "baz": ["quux"], }, ) b = entry.BaseLDAPEntry( dn="dc=foo", attributes={ "foo": ["bar", "thud", "bang"], "baz": ["quux", "bar", "stump"], "bang": ["thud", "barble"], }, ) result = a.diff(b) self.assertEqual( result, delta.ModifyOp( "dc=foo", [ delta.Add("bang", ["thud", "barble"]), delta.Add("baz", ["bar", "stump"]), delta.Add("foo", ["thud", "bang"]), ], ), )
def testDelete_Some_OneType(self): a = entry.BaseLDAPEntry( dn="dc=foo", attributes={ "foo": ["bar"], "baz": ["quux", "thud"], }, ) b = entry.BaseLDAPEntry( dn="dc=foo", attributes={ "foo": ["bar"], "baz": ["thud"], }, ) result = a.diff(b) self.assertEqual( result, delta.ModifyOp( "dc=foo", [ delta.Delete("baz", ["quux"]), ], ), )
def testModifyOp_DNNotFound(self): op = delta.ModifyOp('cn=nope,dc=example,dc=com', [delta.Add('foo', ['bar'])]) d = op.patch(self.root) def eb(fail): fail.trap(ldaperrors.LDAPNoSuchObject) d.addCallbacks(testutil.mustRaise, eb) return d
def testInequalityNotModifyOP(self): """ Modify operations are not equal with other object types. """ sut = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) self.assertNotEqual("cn=john,dc=example,dc=com", sut)
def testHashEquality(self): """ Modify operations can be hashed and equal objects have the same hash. """ first = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) second = delta.ModifyOp("cn=john,dc=example,dc=com", [delta.Delete("description")]) self.assertEqual(first, second) self.assertEqual( first.asLDIF(), second.asLDIF(), "LDIF equality is a precondition for valid hash values", ) self.assertEqual(hash(first), hash(second))
def cb3(got): self.assertEqual( got, [ delta.ModifyOp( self.empty.dn, [delta.Add(b"foo", [b"bar"])], ), ], )
def testRepr(self): """ Getting string representation """ sut = delta.ModifyOp('cn=john,dc=example,dc=com', [delta.Delete('description')]) self.assertEqual( repr(sut), "ModifyOp(dn='cn=john,dc=example,dc=com', " "modifications=[Delete('description', [])])")
def testModification_empty(self): proto = LDIFDeltaDriver() proto.dataReceived(b"""\ version: 1 dn: cn=foo,dc=example,dc=com changetype: modify """) proto.connectionLost() self.assertEqual(proto.listOfCompleted, [ delta.ModifyOp(dn='cn=foo,dc=example,dc=com'), ])
def testAdd_Existing_OneType_OneValue(self): a = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], }) b = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar', 'quux'], }) result = a.diff(b) self.assertEqual( result, delta.ModifyOp('dc=foo', [ delta.Add('foo', ['quux']), ]))
def testModifyOp_DNNotFound(self): """ If fail to modify when the RDN does not exists. """ root = self.getRoot() sut = delta.ModifyOp( 'cn=nope,dc=example,dc=com', [delta.Add('foo', ['bar'])], ) deferred = sut.patch(root) failure = self.failureResultOf(deferred) self.assertIsInstance(failure.value, ldaperrors.LDAPNoSuchObject)
def testRootChange_Add(self): a = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', { 'dc': ['example'], }) b = inmemory.ReadOnlyInMemoryLDAPEntry('dc=example,dc=com', { 'dc': ['example'], 'foo': ['bar'], }) d = a.diffTree(b) d.addCallback(self.assertEquals, [ delta.ModifyOp('dc=example,dc=com', [ delta.Add('foo', ['bar']), ]), ]) return d
def testAdd_New_OneType_ManyValues(self): a = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], }) b = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], 'baz': ['quux', 'thud', 'foo'], }) result = a.diff(b) self.assertEqual( result, delta.ModifyOp('dc=foo', [ delta.Add('baz', ['quux', 'thud', 'foo']), ]))
def testDelete_All_OneType(self): a = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], 'baz': ['quux', 'thud'], }) b = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], }) result = a.diff(b) self.assertEqual( result, delta.ModifyOp('dc=foo', [ delta.Delete('baz', ['quux', 'thud']), ]))
def testModification_complex(self): proto = LDIFDeltaDriver() proto.dataReceived(b"""\ version: 1 dn: cn=foo,dc=example,dc=com changetype: modify delete: foo foo: bar - delete: garply - add: thud thud: quux thud: baz - replace: waldo - add: foo foo: baz - replace: thud thud: xyzzy - add: silly - """) proto.connectionLost() self.assertEqual( proto.listOfCompleted, [ delta.ModifyOp( dn=b"cn=foo,dc=example,dc=com", modifications=[ delta.Delete(b"foo", [b"bar"]), delta.Delete(b"garply"), delta.Add(b"thud", [b"quux", b"baz"]), delta.Replace(b"waldo"), delta.Add(b"foo", [b"baz"]), delta.Replace(b"thud", [b"xyzzy"]), delta.Add(b"silly"), ], ), ], )
def testModification_oneAdd(self): proto = LDIFDeltaDriver() proto.dataReceived(b"""\ version: 1 dn: cn=foo,dc=example,dc=com changetype: modify add: foo foo: bar - """) proto.connectionLost() self.assertEqual(proto.listOfCompleted, [ delta.ModifyOp(dn=b'cn=foo,dc=example,dc=com', modifications=[ delta.Add(b'foo', [b'bar']), ]), ])
def update_entry_(self, account, client): """ Attempt to update and LDAP entry. """ log = self.log log.info("Entered update_entry_()") updateable_attribs = { "givenName", "displayName", "sn", "userAccountControl", } attribs = [ delta.Replace(prop, list(values)) for prop, values in account.items() if prop in updateable_attribs ] log.debug("attribs: {attribs}", attribs=attribs) try: dn = account['dn'] except KeyError: raise Exception("Account template must include a `dn` property.") mod = delta.ModifyOp(dn, attribs) log.debug("LDAP MOD request: {mod_req}", mod_req=repr(mod)) unbind = False if client is None: client = yield self.get_ldap_client_() unbind = True response = None log.debug("LDAPClientManager unbind flag: {unbind}", unbind=unbind) with LDAPClientManager(client, active=unbind, log=log) as c: log.debug("Sending LDAP MOD request.") response = yield c.send(mod.asLDAP()) log.debug("LDAP MOD request sent. Response: {resp}", resp=repr(response)) log.debug("LDAP MOD response: {mod_resp}", mod_resp=repr(response)) result_code = response.resultCode allowed_results = (ldaperrors.Success.resultCode, ldaperrors.LDAPNoSuchObject.resultCode) if result_code not in allowed_results: msg = response.errorMessage raise Exception( "Error adding entry: result_code={}, msg={}".format( result_code, msg)) returnValue(result_code)
def diff(self, other): """ Compute differences between this and another LDAP entry. @param other: An LDAPEntry to compare to. @return: None if equal, otherwise a ModifyOp that would make this entry look like other. """ assert self.dn == other.dn if self == other: return None r = [] myKeys = set(key for key in self) otherKeys = set(key for key in other) addedKeys = list(otherKeys - myKeys) addedKeys.sort(key=to_bytes) # for reproducability only for added in addedKeys: r.append(delta.Add(added, other[added])) deletedKeys = list(myKeys - otherKeys) deletedKeys.sort(key=to_bytes) # for reproducability only for deleted in deletedKeys: r.append(delta.Delete(deleted, self[deleted])) sharedKeys = list(myKeys & otherKeys) sharedKeys.sort(key=to_bytes) # for reproducability only for shared in sharedKeys: addedValues = list(other[shared] - self[shared]) if addedValues: addedValues.sort(key=to_bytes) # for reproducability only r.append(delta.Add(shared, addedValues)) deletedValues = list(self[shared] - other[shared]) if deletedValues: deletedValues.sort(key=to_bytes) # for reproducability only r.append(delta.Delete(shared, deletedValues)) return delta.ModifyOp(dn=self.dn, modifications=r)
def state_WAIT_FOR_MOD_SPEC(self, line): if line == b"": # end of entry self.mode = ldifprotocol.WAIT_FOR_DN m = delta.ModifyOp(dn=self.dn, modifications=self.modifications) self.dn = None self.data = None self.modifications = None self.gotEntry(m) return key, val = self._parseLine(line) if key not in self.MOD_SPEC_TO_DELTA: raise LDIFDeltaUnknownModificationError(self.dn, key) self.mod_spec = key self.mod_spec_attr = val self.mod_spec_data = [] self.mode = IN_MOD_SPEC
def testAdd_NewAndExisting_ManyTypes(self): a = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar'], 'baz': ['quux'], }) b = entry.BaseLDAPEntry(dn='dc=foo', attributes={ 'foo': ['bar', 'thud', 'bang'], 'baz': ['quux', 'bar', 'stump'], 'bang': ['thud', 'barble'], }) result = a.diff(b) self.assertEqual( result, delta.ModifyOp('dc=foo', [ delta.Add('bang', ['thud', 'barble']), delta.Add('baz', ['bar', 'stump']), delta.Add('foo', ['thud', 'bang']), ]))