From ff6a3f8e57e2cd18563708e29d8dd3527fc5ab7e Mon Sep 17 00:00:00 2001 From: Valentin Samir Date: Sat, 25 Oct 2014 22:36:46 +0200 Subject: [PATCH] =?UTF-8?q?[utils/ldapcertfs]=20Actualisation=20r=C3=A9gul?= =?UTF-8?q?i=C3=A8re=20des=20fichier=20de=20/etc/ssl/crans?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit À la lecture des fichiers en fonction de la base ldap --- utils/ldapcertfs.py | 153 +++++++++++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 44 deletions(-) diff --git a/utils/ldapcertfs.py b/utils/ldapcertfs.py index 366a947d..cf95777a 100755 --- a/utils/ldapcertfs.py +++ b/utils/ldapcertfs.py @@ -54,6 +54,33 @@ import logging LOG_FILENAME = 'ldapcertfs.log' logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) + +CACHE = {} +CACHE_TIMEOUT = 60 + +def set_to_cache(keys, value, now=None, null=False): + global CACHE + if now is None: + now = time.time() + if not isinstance(keys, list): + keys = [keys] + for key in keys: + if key or null: + CACHE[key] = (now, value) + +def get_from_cache(key, now=None, expire=CACHE_TIMEOUT): + global CACHE + if now is None: + now = time.time() + if key in CACHE: + (ts, v) = CACHE[key] + if now - ts < expire: + return v + else: + raise ValueError("Expired") + else: + raise ValueError("Not Found") + class Pass: pass @@ -135,61 +162,65 @@ class LdapCertFS(fuse.Fuse): 'key_cert_chain.pem' : {'file':['privatekey', 'certificat', 'chain'], 'mode':0400}, 'cert_chain.pem' : {'file':['certificat', 'chain'], 'mode':0400}, } - self.build_tree() - - def build_tree(self): - """Construit l'arborescence du système de fichier""" - self._storage = {'/': Item(0755 | stat.S_IFDIR, self.uid, self.gid)} + self.conn = lc_ldap.shortcuts.lc_ldap_readonly() + self._storage = {} self.passphrase = {} - conn = lc_ldap.shortcuts.lc_ldap_readonly() - if self.ldap_filter == 'self': - machines = conn.search(u'mid=*', dn=conn.dn, scope=1) - elif self.ldap_filter: - machines = conn.search("(&(%s)(mid=*))" % self.ldap_filter, sizelimit=8000) - else: - machines = conn.get_local_machines() + def search_cache(self, filter, **kwargs): + try: + return get_from_cache(filter) + except ValueError: + objects = self.conn.search(filter, **kwargs) + set_to_cache(filter, objects) + return objects + + def make_root(self): + self._storage['/'] = Item(0755 | stat.S_IFDIR, self.uid, self.gid) + if self.ldap_filter == 'self': + machines = self.search_cache(u'mid=*', dn=self.conn.dn, scope=1) + elif self.ldap_filter: + machines = self.search_cache("(&(%s)(mid=*))" % self.ldap_filter, sizelimit=8000) + else: + machines = self.conn.get_local_machines() for machine in machines: if not machine.certificats(): continue if 'aid' in machine.dn and "cransAccount" in machine.proprio()['objectClass']: - uid = int(machine.proprio()["uidNumber"][0]) - gid = int(machine.proprio()["gidNumber"][0]) + self.uid = int(machine.proprio()["uidNumber"][0]) + self.gid = int(machine.proprio()["gidNumber"][0]) else: - uid = 0 - gid = 0 + self.uid = 0 + self.gid = 0 mpath = "/%s" % machine['host'][0] - self._storage[mpath]=Item(0755 | stat.S_IFDIR, uid, gid) + self._storage[mpath]=Item(0755 | stat.S_IFDIR, self.uid, self.gid) self._add_to_parent_dir(mpath) - for cert in machine.certificats(): - path = '%s/xid=%s' % (mpath, cert["xid"][0]) - self._storage[path]=Item(0755 | stat.S_IFDIR, uid, gid) - self._add_to_parent_dir(path) - for file, file_data in self.files.items(): - data = self._file_data(machine, cert, file) - if data: - fpath = '%s/%s' % (path, file) - self._storage[fpath]=Item(file_data['mode'] | stat.S_IFREG, uid, gid) - self._storage[fpath].data = data - self._add_to_parent_dir(fpath) - for machine in machines: - if not machine.certificats(): - continue - mpath = "/%s" % machine['host'][0] - for cert in machine.certificats(): - path = 'xid=%s' % (cert["xid"][0]) - if cert['info']: - item = Item(0644 | stat.S_IFLNK, self.uid, self.gid) - item.data = path - newpath = '%s/%s' % (mpath, cert['info'][0]) - indice = 1 - while newpath in self._storage: - newpath = '/%s (%s)' % (cert['info'][0], indice) - indice+=1 - self._storage[newpath] = item - self._add_to_parent_dir(newpath) + def make_machine(self, hostname): + machine = self.search_cache(u"host=%s" % hostname)[0] + mpath = '/%s' % machine['host'][0] + self._storage[mpath]=Item(0755 | stat.S_IFDIR, self.uid, self.gid) + for cert in machine.certificats(refresh=True): + xpath = '%s/xid=%s' % (mpath, cert["xid"][0]) + self._storage[xpath]=Item(0755 | stat.S_IFDIR, self.uid, self.gid) + self._add_to_parent_dir(xpath) + def make_cert(self, xid): + cert = self.search_cache(u"xid=%s" % xid)[0] + xpath = '/%s/xid=%s' % (cert.machine()['host'][0], cert["xid"][0]) + self._storage[xpath]=Item(0755 | stat.S_IFDIR, self.uid, self.gid) + for file, file_data in self.files.items(): + self.make_file(xid, file) + + def make_file(self, xid, file): + cert = self.search_cache(u"xid=%s" % xid)[0] + xpath = '/%s/xid=%s' % (cert.machine()['host'][0], cert["xid"][0]) + file_data = self.files[file] + data = self._file_data(cert.machine(), cert, file) + if data: + fpath = '%s/%s' % (xpath, file) + self._storage[fpath]=Item(file_data['mode'] | stat.S_IFREG, self.uid, self.gid) + self._storage[fpath].data = data + self._add_to_parent_dir(fpath) def _file_data(self, machine, cert, file): """Construit le contenue du fichier file utilisant le certificat cert de machine""" @@ -243,8 +274,42 @@ class LdapCertFS(fuse.Fuse): return None return data + def parse_path(self, path): + machine_host = None + xid = None + file = None + paths = path.split('/')[1:] + if paths: + machine_host = paths[0] + paths = paths[1:] + if paths: + if paths[0].startswith("xid="): + xid = paths[0][4:] + paths = paths[1:] + if paths: + file = paths[0] + return (machine_host, xid, file) + + def build_path(self, path): + try: + get_from_cache(path) + except ValueError: + if path in self._storage: + del self._storage[path] + if path == "/": + self.make_root() + else: + (machine_host, xid, file) = self.parse_path(path) + if machine_host and not xid and not file: + self.make_machine(machine_host) + elif machine_host and xid and not file: + self.make_cert(xid) + elif machine_host and xid and file: + self.make_file(xid, file) + set_to_cache(path, True) # --- Metadata ----------------------------------------------------------- def getattr(self, path): + self.build_path(path) if not path in self._storage: return -errno.ENOENT