def add_s(self, dn, modlist): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN id_attr_in_modlist = False id_attr = self._dn_to_id_attr(dn) id_value = self._dn_to_id_value(dn) # The LDAP API raises a TypeError if attr name is None. for k, dummy_v in modlist: if k is None: raise TypeError('must be string, not None. modlist=%s' % modlist) if k == id_attr: for val in dummy_v: if common.utf8_decode(val) == id_value: id_attr_in_modlist = True if not id_attr_in_modlist: LOG.debug('id_attribute=%(attr)s missing, attributes=%(attrs)s' % {'attr': id_attr, 'attrs': modlist}) raise ldap.NAMING_VIOLATION key = self.key(dn) LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', { 'dn': common.utf8_decode(dn), 'attrs': modlist}) if key in self.db: LOG.debug('add item failed: dn=%s is already in store.', common.utf8_decode(dn)) raise ldap.ALREADY_EXISTS(dn) self.db[key] = {k: _internal_attr(k, v) for k, v in modlist} self.db.sync()
def _create(self, rdn=None, properties=None, basedn=None, ensure=False): """Internal implementation of create. This is used by ensure and create, to prevent code duplication. You should *never* call this method directly. """ assert (len(self._create_objectclasses) > 0) basedn = ensure_str(basedn) self._log.debug('Checking "%s" under %s : %s' % (rdn, basedn, properties)) # Add the objectClasses to the properties (dn, valid_props) = self._validate(rdn, properties, basedn) # Check if the entry exists or not? .add_s is going to error anyway ... self._log.debug('Validated dn %s : valid_props %s' % (dn, valid_props)) exists = False try: self._instance.search_ext_s(dn, ldap.SCOPE_BASE, self._object_filter, attrsonly=1, serverctrls=self._server_controls, clientctrls=self._client_controls) exists = True except ldap.NO_SUCH_OBJECT: pass if exists and ensure: # update properties self._log.debug('Exists %s' % dn) self._dn = dn # Now use replace_many to setup our values mods = [] for k, v in valid_props.items(): mods.append((ldap.MOD_REPLACE, k, v)) self._instance.modify_ext_s(self._dn, mods, serverctrls=self._server_controls, clientctrls=self._client_controls) elif exists and not ensure: # raise "already exists." raise ldap.ALREADY_EXISTS("Entry %s already exists" % dn) if not exists: self._log.debug('Creating %s' % dn) e = Entry(dn) e.update( {'objectclass': ensure_list_bytes(self._create_objectclasses)}) e.update(valid_props) # We rely on exceptions here to indicate failure to the parent. self._log.debug('Creating entry %s : %s' % (dn, e)) self._instance.add_ext_s(e, serverctrls=self._server_controls, clientctrls=self._client_controls) # If it worked, we need to fix our instance dn self._dn = dn return self
def pta_add(inst, basedn, log, args): log = log.getChild('pta_add') new_url_l = _validate_url(args.URL.lower()) plugin = PassThroughAuthenticationPlugin(inst) url_attrs = plugin.get_urls() urls = list(map(lambda url: url.lower(), [i for _, i in url_attrs.items()])) next_num = _get_url_next_num(url_attrs) if new_url_l in urls: raise ldap.ALREADY_EXISTS("Entry %s already exists" % args.URL) plugin.add("nsslapd-pluginarg%s" % next_num, args.URL)
def add_s(self, dn, attrs): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN key = "%s%s" % (self.__prefix, dn) LOG.debug("FakeLDAP add item: dn=%s, attrs=%s" % (dn, attrs)) if key in self.db: LOG.error( "FakeLDAP add item failed: dn '%s' is already in store." % dn) raise ldap.ALREADY_EXISTS(dn) self.db[key] = dict([(k, v if isinstance(v, list) else [v]) for k, v in attrs]) self.db.sync()
def modrdn_s(self, dn, new_rdn, *ign): elems = explode_dn(dn) rdn = elems[0] tree_pos = TREE.getElementByDN(elems[1:]) if rdn not in tree_pos: raise ldap.NO_SUCH_OBJECT(rdn) if new_rdn in tree_pos: raise ldap.ALREADY_EXISTS(new_rdn) rec = tree_pos.get(rdn) del tree_pos[rdn] tree_pos[new_rdn] = rec
def add_s(self, dn, attrs): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN key = '%s%s' % (self.__prefix, dn) LOG.debug( _('FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s') % { 'dn': dn, 'attrs': attrs }) if key in self.db: LOG.debug( _('FakeLdap add item failed: dn=%s is' ' already in store.'), dn) raise ldap.ALREADY_EXISTS(dn) self.db[key] = dict([(k, v if isinstance(v, list) else [v]) for k, v in attrs]) self.db.sync()
def add_s(self, dn, attrs): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN # The LDAP API raises a TypeError if attr name is None. for k, dummy_v in attrs: if k is None: raise TypeError('must be string, not None. attrs=%s' % attrs) key = '%s%s' % (self.__prefix, dn) LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', { 'dn': dn, 'attrs': attrs }) if key in self.db: LOG.debug('add item failed: dn=%s is already in store.', dn) raise ldap.ALREADY_EXISTS(dn) self.db[key] = dict([(k, _process_attr(k, v)) for k, v in attrs]) self.db.sync()
def add_s(self, dn, modlist): """Add an object with the specified attributes at dn.""" if server_fail: raise ldap.SERVER_DOWN # The LDAP API raises a TypeError if attr name is None. for k, dummy_v in modlist: if k is None: raise TypeError('must be string, not None. modlist=%s' % modlist) key = self.key(dn) LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', { 'dn': core.utf8_decode(dn), 'attrs': modlist}) if key in self.db: LOG.debug('add item failed: dn=%s is already in store.', core.utf8_decode(dn)) raise ldap.ALREADY_EXISTS(dn) self.db[key] = dict([(k, _internal_attr(k, v)) for k, v in modlist]) self.db.sync()
def add_s(self, dn, attr_list): elems = explode_dn(dn) rdn = elems[0] tree_pos = TREE.getElementByDN(elems[1:]) if rdn in tree_pos: raise ldap.ALREADY_EXISTS(rdn) # Add rdn to attributes as well. rdn_key, rdn_value = rdn.split(b'=') tree_pos[rdn] = {rdn_key: [rdn_value]} record = tree_pos[rdn] for key, value in attr_list: record[key] = value # Maintain memberOf if self.maintain_memberof: if key == self.member_attr: for v in value: self.modify_s(v, [(ldap.MOD_ADD, self.memberof_attr, [dn])])
def create(self, suffix=None, properties=None): """ Creates backend entry and returns its dn. If the properties 'chain-bind-pwd' and 'chain-bind-dn' and 'chain-urls' are specified the backend is a chained backend. A chaining backend is created under 'cn=chaining database,cn=plugins,cn=config'. A local backend is created under 'cn=ldbm database,cn=plugins,cn=config' @param suffix - suffix stored in the backend @param properties - dictionary with properties values supported properties are BACKEND_NAME = 'name' BACKEND_READONLY = 'read-only' BACKEND_REQ_INDEX = 'require-index' BACKEND_CACHE_ENTRIES = 'entry-cache-number' BACKEND_CACHE_SIZE = 'entry-cache-size' BACKEND_DNCACHE_SIZE = 'dn-cache-size' BACKEND_DIRECTORY = 'directory' BACKEND_DB_DEADLOCK = 'db-deadlock' BACKEND_CHAIN_BIND_DN = 'chain-bind-dn' BACKEND_CHAIN_BIND_PW = 'chain-bind-pw' BACKEND_CHAIN_URLS = 'chain-urls' BACKEND_SUFFIX = 'suffix' BACKEND_SAMPLE_ENTRIES = 'sample_entries' @return backend DN of the created backend @raise LDAPError """ def _getBackendName(parent): ''' Use to build a backend name that is not already used ''' index = 1 while True: bename = "local%ddb" % index base = ("%s=%s,%s" % (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], bename, parent)) filt = "(objectclass=%s)" % BACKEND_OBJECTCLASS_VALUE self.log.debug("_getBackendName: baser=%s : fileter=%s", base, filt) try: self.conn.getEntry(base, ldap.SCOPE_BASE, filt) except (NoSuchEntryError, ldap.NO_SUCH_OBJECT): self.log.info("backend name will be %s", bename) return bename index += 1 # suffix is mandatory. If may be in the properties if isinstance(properties, dict) and properties.get( BACKEND_SUFFIX, None) is not None: suffix = properties.get(BACKEND_SUFFIX) if not suffix: raise ldap.UNWILLING_TO_PERFORM('Missing Suffix') else: nsuffix = normalizeDN(suffix) # Check it does not already exist a backend for that suffix if self.conn.verbose: self.log.info("Checking suffix %s for existence", suffix) ents = self.conn.backend.list(suffix=suffix) if len(ents) != 0: raise ldap.ALREADY_EXISTS # Check if we are creating a local/chained backend chained_suffix = (properties and (BACKEND_CHAIN_BIND_DN in properties) and (BACKEND_CHAIN_BIND_PW in properties) and (BACKEND_CHAIN_URLS in properties)) if chained_suffix: self.log.info("Creating a chaining backend") dnbase = DN_CHAIN else: self.log.info("Creating a local backend") dnbase = DN_LDBM # Get the future backend name if properties and BACKEND_NAME in properties: cn = properties[BACKEND_NAME] else: cn = _getBackendName(dnbase) # Check the future backend name does not already exists # we can imagine having no backends for 'suffix' but having a backend # with the same name dn = "%s=%s,%s" % (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], cn, dnbase) ents = self.conn.backend.list(backend_dn=dn) if ents: raise ldap.ALREADY_EXISTS( "Backend already exists with that DN: %s" % ents[0].dn) # All checks are done, Time to create the backend try: entry = Entry(dn) entry.update({ 'objectclass': ['top', 'extensibleObject', BACKEND_OBJECTCLASS_VALUE], BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME]: cn, BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_SUFFIX]: nsuffix, }) if chained_suffix: entry.update({ BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_URLS]: properties[BACKEND_CHAIN_URLS], BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_DN]: properties[BACKEND_CHAIN_BIND_DN], BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_PW]: properties[BACKEND_CHAIN_BIND_PW] }) self.log.debug("adding entry: %r", entry) self.conn.add_s(entry) except ldap.ALREADY_EXISTS as e: self.log.error("Entry already exists: %r", dn) raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn)) except ldap.LDAPError as e: self.log.error("Could not add backend entry: %r", dn) raise e backend_entry = self.conn._test_entry(dn, ldap.SCOPE_BASE) return backend_entry
def add(self, suffix, binddn=None, bindpw=None, urls=None, attrvals=None, benamebase='localdb', setupmt=False, parent=None): """Setup a backend and return its dn. Blank on error XXX should RAISE! @param suffix @param benamebase - the backend common name @param setupmt - eventually setup Mapping Tree entry @param urls - a string of ldapurl - create a chaining backend @oaram binddn - chaining proxy user @param bindpw - chaining proxy password @param attrvals: a dict with further params like for ldbm { 'nsslapd-cachememsize': '1073741824', 'nsslapd-cachesize': '-1', } for chain { 'nsmaxresponsedelay': '60', 'nsslapd-sizelimit': '-1' } ex. benamebase="Isle0-0" urls=[ "ldaps://f0-ldap-vip.example.it:636/", "ldaps://ldap-18.example.it:636/", "ldaps://ldap-19.example.it:636/" ] NOTE: The suffix attribute is a mere string for the backend. the following action will work nicely: c.backend.add(suffix="foo=example,dc=com",benamebase="db1") TODO: rename benamebase with cn TODO: split CHAIN and LDBM ? eg. backend.add_chain """ attrvals = attrvals or {} dnbase = "" # figure out what type of be based on args if binddn and bindpw and urls: # its a chaining be dnbase = DN_CHAIN else: # its a ldbm be dnbase = DN_LDBM nsuffix = normalizeDN(suffix) try: cn = benamebase self.log.debug("create backend with cn: %s" % cn) dn = "cn=" + cn + "," + dnbase entry = Entry(dn) entry.update({ 'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'], 'cn': cn, 'nsslapd-suffix': nsuffix }) if binddn and bindpw and urls: # its a chaining be entry.update({ 'nsfarmserverurl': urls, 'nsmultiplexorbinddn': binddn, 'nsmultiplexorcredentials': bindpw }) # set attrvals (but not cn, because it's in dn) # TODO do it in Entry if attrvals: entry.update(attrvals) self.log.debug("adding entry: %r" % entry) self.conn.add_s(entry) except ldap.ALREADY_EXISTS, e: self.log.error("Entry already exists: %r" % dn) raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))